Sharing A Stage: JDeveloper/ADF & NetBeans/Java EE 6?
- by Geertjan
A highlight for me during last week's Oracle Developer Day in Romania (which I blogged about here) was meeting Jernej Kaše (who is from Slovenia, just like my philosopher hero Slavoj Žižek), who is an Oracle Fusion Middleware evangelist. At the conference, while I was presenting NetBeans and Java EE 6 in one room, Jernej was presenting JDeveloper and ADF in another room. The application he created looks as follows, i.e., a realistic CRUD app, with a master/detail view, a search feature, and validation:
In a conversation during a break, we started imagining a scenario where the two of us would be on the same stage, taking turns talking about NetBeans/Java EE and JDeveloper/ADF. In that way, attendees at a conference wouldn't need to choose which of the two topics to attend, because they'd be handled in the same session, with the session possibly being longer so that sufficient time could be spent on the respective technologies. (The JDeveloper/ADF session would then not be competing with the NetBeans/Java EE 6 session, since they'd be handled simultaneously.) The session would focus on the similarities/differences between the two respective tools/solutions, which would be extremely interesting and also unique.
The crucial question in making this kind of co-presentation possible is whether (and how quickly) an application such as the one created above with JDeveloper/ADF could be created with NetBeans/Java EE 6. The NetBeans/Java EE 6 story is extremely strong on the model and controler levels, but less strong on the view layer. Though there are choices between using PrimeFaces, RichFaces, and IceFaces, that support is quite limited in the absence of a visual designer or of other specific tools (e.g., code generators to generate snippets of PrimeFaces) connected to JSF component libraries.
However, it so happens that in recent months we at NetBeans have established really good connections with the PrimeFaces team (more about that another time). So I asked them what it would take to write the above UI in PrimeFaces. The PrimeFaces team were very helpful. They sent me the following screenshot, which is of the UI they created in PrimeFaces, reproducing the ADF screenshot above:
Of course, the above is purely the UI layer, there's no EJB and entity classes and data connection hooked into it yet. However, this is the Facelets file that the PrimeFaces team sent me, i.e., using the PrimeFaces component library, that produces the above result:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<f:view>
<h:head>
<style type="text/css">
.alignRight {
text-align: right;
}
.alignLeft {
text-align: left;
}
.alignTop {
vertical-align: top;
}
.ui-validation-required {
color: red;
font-size: 14px;
margin-right: 5px;
position: relative;
vertical-align: top;
}
.ui-selectonemenu .ui-selectonemenu-trigger .ui-icon {
margin-top: 7px !important;
}
</style>
</h:head>
<h:body>
<h:form prependId="false" id="form">
<p:panel header="Employees">
<h:panelGrid columns="4" id="searchPanel">
Search
<p:selectOneMenu>
<f:selectItem itemLabel="FirstName" itemValue="FirstName" />
<f:selectItem itemLabel="LastName" itemValue="LastName" />
<f:selectItem itemLabel="Email" itemValue="Email" />
<f:selectItem itemLabel="PhoneNumber" itemValue="PhoneNumber" />
</p:selectOneMenu>
<p:inputText />
<p:commandLink process="searchPanel" update="@form">
<h:graphicImage name="next.gif" library="img" />
</p:commandLink>
</h:panelGrid>
<h:panelGrid columns="3" columnClasses="alignTop,,alignTop"
style="width:90%;margin-left:10%">
<h:panelGrid columns="2" columnClasses="alignRight,alignLeft">
<h:outputLabel for="firstName">FirstName</h:outputLabel>
<p:inputText id="firstName" />
<h:outputLabel for="lastName">
<sup class="ui-validation-required">*</sup>LastName
</h:outputLabel>
<p:inputText id="lastName" style="width:250px;" />
<h:outputLabel for="email">
<sup class="ui-validation-required">*</sup>Email
</h:outputLabel>
<p:inputText id="email" style="width:250px;" />
<h:outputLabel for="phoneNumber" value="PhoneNumber" />
<p:inputMask id="phoneNumber" mask="999.999.9999" />
<h:outputLabel for="hireDate">
<sup class="ui-validation-required">*</sup>HireDate</h:outputLabel>
<p:calendar id="hireDate" pattern="MM/dd/yyyy" showOn="button" />
</h:panelGrid>
<p:outputPanel style="min-width:40px;" />
<h:panelGrid columns="2" columnClasses="alignRight,alignLeft">
<h:outputLabel for="jobId">
<sup class="ui-validation-required">*</sup>JobId
</h:outputLabel>
<p:selectOneMenu id="jobId" >
<f:selectItem itemLabel="Administration Vice President" itemValue="Administration Vice President" />
<f:selectItem itemLabel="Vice President" itemValue="Vice President" />
</p:selectOneMenu>
<h:outputLabel for="salary">Salary</h:outputLabel>
<p:inputText id="salary" styleClass="alignRight" />
<h:outputLabel for="commissionPct">CommissionPct</h:outputLabel>
<p:inputText id="commissionPct" style="width:30px;" maxlength="3" />
<h:outputLabel for="manager">ManagerId</h:outputLabel>
<p:selectOneMenu id="manager">
<f:selectItem itemLabel="Steven King" itemValue="Steven" />
<f:selectItem itemLabel="Michael Cook" itemValue="Michael" />
<f:selectItem itemLabel="John Benjamin" itemValue="John" />
<f:selectItem itemLabel="Dav Glass" itemValue="Dav" />
</p:selectOneMenu>
<h:outputLabel for="department">DepartmentId</h:outputLabel>
<p:selectOneMenu id="department">
<f:selectItem itemLabel="90" itemValue="90" />
<f:selectItem itemLabel="80" itemValue="80" />
<f:selectItem itemLabel="70" itemValue="70" />
<f:selectItem itemLabel="60" itemValue="60" />
<f:selectItem itemLabel="50" itemValue="50" />
<f:selectItem itemLabel="40" itemValue="40" />
<f:selectItem itemLabel="30" itemValue="30" />
<f:selectItem itemLabel="20" itemValue="20" />
</p:selectOneMenu>
</h:panelGrid>
</h:panelGrid>
<p:outputPanel id="buttonPanel">
<p:commandButton value="First" process="@this" update="@form" />
<p:commandButton value="Previous" process="@this" update="@form"
style="margin-left:15px;" />
<p:commandButton value="Next" process="@this" update="@form"
style="margin-left:15px;" />
<p:commandButton value="Last" process="@this" update="@form"
style="margin-left:15px;" />
</p:outputPanel>
<p:tabView style="margin-top:25px">
<p:tab title="Job History">
<p:dataTable var="history">
<p:column headerText="StartDate">
<h:outputText value="#{history.startDate}">
<f:convertDateTime pattern="MM/dd/yyyy" />
</h:outputText>
</p:column>
<p:column headerText="EndDate">
<h:outputText value="#{history.endDate}">
<f:convertDateTime pattern="MM/dd/yyyy" />
</h:outputText>
</p:column>
<p:column headerText="JobId">
<h:outputText value="#{history.jobId}" />
</p:column>
<p:column headerText="DepartmentId">
<h:outputText value="#{history.departmentIdId}" />
</p:column>
</p:dataTable>
</p:tab>
</p:tabView>
</p:panel>
</h:form>
</h:body>
</f:view>
</html>
Right now, NetBeans IDE only has code completion to create the above. So there's not much help for creating such a UI right now. I don't believe that a visual designer is mandatory to create the above. A few code generators and file templates could do the job too. And I'm looking forward to seeing those kinds of tools for PrimeFaces, as well as other JSF component libraries, appearing in NetBeans IDE in upcoming releases. A related option would be for the NetBeans generated CRUD app to include the option of having a master/detail view, as well as the option of having a search feature, i.e., the application generators would provide the option of having additional features typical in Java enterprise apps.
In the absence of such tools, there still is room, I believe, for NetBeans/Java EE and JDeveloper/ADF sharing a stage at a conference. The above file would have been prepared up front and the presenter would state that fact. The UI layer is only one aspect of a Java EE 6 application, so that the presenter would have ample other features to show (i.e., the entity class generation, the tools for working with servlets, with session beans, etc) prior to getting to the point where the statement would be made: "On the UI layer, I have prepared this Facelets file, which I will now show you can be connected to the lower layers of the application as follows." At that point, the session beans could be hooked into the Facelets file, the file would be saved, the browser refreshed, and then the whole application would work exactly as the ADF application does.
So, Jernej, let's share a stage soon!