JsfCrudGenerator65Timecard
Timecard Application
The Timecard application demonstrates how to customize the code generated from the consulting agency database. The application uses version 2 of the consulting agency database, which differs from the original version only in the addition of password columns on several tables.
For general information on the JSF CRUD Generator, see JsfCrudGenerator. For information on enhancements in NetBeans 6.5, see JsfCrudGenerator65. For more information on the consulting agency database, see JsfCrudGeneratorConsultingAgency.
The instructions below are for NetBeans 6.5. You can also simply download the attached Timecard65_JsfCrudGenerator65Timecard.zip, which contains the completed Timecard project and SQL.
Requirements
The Timecard application lets consultants create, edit, destroy, and search their Billable items. The requirements are as follows:
- Present a Login screen that lets consultants authenticate. All other screens in the application require authentication.
- Present an Index screen with a link to the Search Billable Items screen, a link to the New Billable screen, and a link to logout.
- Present a Search Billable Items screen that lets consultants search Billable items associated with them.
- The consultant can supply any of the following search criteria: the Billable item ID, earliest possible start date, latest possible end date, number of hours worked, hourly rate, description of the work, and project. Only projects for which the consultant has existing Billable items should be available on the Search Billable Items screen.
- Present a Billable Results screen that displays the results of a search. Only Billable items associated with the consultant are included in the results.
- Present Billable Detail, Edit Billable, and New Billable screens.
- These screens include the following fields: start date, end date, number of hours worked, hourly rate, description of the work, artifacts as text, and project. In addition, the Billable Detail and Edit Billable screens include the Billable item ID.
Generating the Application
Follow the instructions in the tutorial entitled "Generating a JavaServer Faces CRUD Application from a Database," using version 2 of the consulting agency database instead of the original version.
Creating login.jsp
- In the Projects window, expand the Web Pages > consultant node. Right-click Edit.jsp and select Copy.
- Right-click on the Web Pages node and select Paste.
- Under the Web Pages node, rename Edit.jsp to login.jsp.
- Change <title>Editing Consultant</title> to <title>Consultant Timecard Application – Login</title>.
- Change
Editing Consultant
toConsultant Timecard Application – Login
. - Remove the following:
- Change <h:inputText id="password" value="#{consultant.consultant.password}" title="Password" required="true" requiredMessage="The password field is required." /> to <h:inputSecret id="password" value="#{consultant.consultant.password}" title="Password" required="true" requiredMessage="The password field is required." />.
- Remove the following:
- Change <h:commandLink action="#{consultant.edit}" value="Save"> to <h:commandLink action="#{consultant.login}" value="Login" />.
- Remove the following:
Editing welcomeJSF.jsp
In Web Pages > welcomeJSF.jsp, make the following changes.
- Change <title>JSP Page</title> to <title>Consultant Timecard Application</title>.
- Add the following just after the <body> tag:
- Change
<h:outputText value="JavaServer Faces" />
to<h:outputText value="Consultant Timecard Application" />
. - Change the following:
to:
<h:commandLink action="#{billable.searchSetup}" value="Search Billable Items"/>
<br />
<h:commandLink action="#{billable.createSetup}" value="New Billable"/>
<br />
<h:commandLink action="#{consultant.logout}" value="Logout"/>
Creating Search.jsp
- In the Projects window, expand the Web Pages > billable node. Right-click Edit.jsp and select Copy.
- Right-click on the Web Pages > billable node and select Paste.
- Under the Web Pages > billable node, rename Edit_1.jsp to Search.jsp.
- Change <title>Editing Billable</title> to <title>Search Billable Items</title>.
- Change
Editing Billable
toSearch Billable Items
. - Change <h:form> to <h:form id="form1">.
- Change <h:outputText value="#{billable.billable.billableId}" title="BillableId" /> to <h:inputText value="#{billable.billable.billableId}" title="BillableId" converterMessage="The billable id field must be an integer."/>.
- Change the following:
to:
<h:outputText value="Earliest Possible StartDate (MM/dd/yyyy):"/>
<h:inputText id="startDate" value="#{billable.billable.startDate}" title="StartDate" converterMessage="Invalid start date.">
<f:convertDateTime pattern="MM/dd/yyyy" />
</h:inputText>
- Change the following:
<h:outputText value="EndDate (MM/dd/yyyy HH:mm:ss):"/>
<h:inputText id="endDate" value="#{billable.billable.endDate}" title="EndDate" >
<f:convertDateTime pattern="MM/dd/yyyy HH:mm:ss" />
</h:inputText>
to:
<h:outputText value="Latest Possible EndDate (MM/dd/yyyy):"/>
<h:inputText id="endDate" value="#{billable.billable.endDate}" title="EndDate" validator="#{billable.validateEndDate}" converterMessage="Invalid end date.">
<f:convertDateTime pattern="MM/dd/yyyy" />
</h:inputText>
- Change <h:inputText id="hours" value="#{billable.billable.hours}" title="Hours" required="true" requiredMessage="The hours field is required." /> to <h:inputText id="hours" value="#{billable.searchHours}" title="Hours" converterMessage="The hours field must be an integer."/>.
- Change <h:inputText id="hourlyRate" value="#{billable.billable.hourlyRate}" title="HourlyRate" required="true" requiredMessage="The hourlyRate field is required." /> to <h:inputText id="hourlyRate" value="#{billable.billable.hourlyRate}" title="HourlyRate" converterMessage="The hourly rate field must be monetary figure."/>.
- Remove the following:
- Remove the following:
<h:outputText value="Artifacts:"/>
<h:inputTextarea rows="4" cols="30" id="artifacts" value="#{billable.billable.artifacts}" title="Artifacts" />
<h:outputText value="ConsultantId:"/>
<h:selectOneMenu id="consultantId" value="#{billable.billable.consultantId}" title="ConsultantId" required="true" requiredMessage="The consultantId field is required." >
<f:selectItems value="#{consultant.consultantItemsAvailableSelectOne}"/>
</h:selectOneMenu>
- Change the following:
<h:selectOneMenu id="project" value="#{billable.billable.project}" title="Project" required="true" requiredMessage="The project field is required." >
<f:selectItems value="#{project.projectItemsAvailableSelectOne}"/>
</h:selectOneMenu>
to:
<h:selectOneMenu id="project" value="#{billable.billable.project}" title="Project">
<f:selectItems value="#{project.billedProjectsForLoggedInConsultantSelectOne}"/>
</h:selectOneMenu>
- Change the following:
<h:commandLink action="#{billable.edit}" value="Save">
<f:param name="jsfcrud.currentBillable" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable | billable.billable]][Billable.converter].jsfcrud_invoke}"/>
</h:commandLink>
to:
<h:commandLink action="#{billable.search}" value="Search"/>
- Remove the following:
<h:commandLink action="#{billable.detailSetup}" value="Show" immediate="true">
<f:param name="jsfcrud.currentBillable" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable | billable.billable]][Billable.converter].jsfcrud_invoke}"/>
</h:commandLink>
<br />
<h:commandLink action="#{billable.listSetup}" value="Show All Billable Items" immediate="true"/>
<br />
Editing List.jsp
In Web Pages > billable > List.jsp, make the following changes.
- Change <title>Listing Billable Items</title> to <title>Billable Results</title>.
- Change
Listing Billable Items
toBillable Results
. - After <h:outputText value="#{item.startDate}">, change <f:convertDateTime pattern="MM/dd/yyyy HH:mm:ss" /> to <f:convertDateTime pattern="MM/dd/yyyy" />.
- After <h:outputText value="#{item.endDate}">, change <f:convertDateTime pattern="MM/dd/yyyy HH:mm:ss" /> to <f:convertDateTime pattern="MM/dd/yyyy" />.
- Remove the following:
- Remove the following:
<h:column>
<f:facet name="header">
<h:outputText value="ConsultantId"/>
</f:facet>
<h:outputText value=" #{item.consultantId}"/>
</h:column>
- Change the following:
<h:commandLink value="Destroy" action="#{billable.destroy}">
<f:param name="jsfcrud.currentBillable" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Item | item]][Billable.converter].jsfcrud_invoke}"/>
</h:commandLink>
to:
<h:commandLink value="Destroy" action="#{billable.destroy}">
<f:param name="jsfcrud.currentBillable" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Item | item]][[Billable.converter | billable.converter]].jsfcrud_invoke}"/>
<f:param name="jsfcrud.timecard.consultantOfCurrentBillable" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Item.consultantId | item.consultantId]][[Consultant.converter | consultant.converter]].jsfcrud_invoke}"/>
</h:commandLink>
- Before <h:commandLink action="#{billable.createSetup}" value="New Billable"/>, add the following:
<h:commandLink action="#{billable.searchSetup}" value="Modify Criteria"/>
<br />
Editing New.jsp
In Web Pages > billable > New.jsp, make the following changes.
- Change <h:form> to <h:form id="form1">.
- Change the following:
to:
<h:outputText value="StartDate (MM/dd/yyyy):"/>
<h:inputText id="startDate" value="#{billable.billable.startDate}" title="StartDate" converterMessage="Invalid start date.">
<f:convertDateTime pattern="MM/dd/yyyy" />
</h:inputText>
- Change the following:
<h:outputText value="EndDate (MM/dd/yyyy HH:mm:ss):"/>
<h:inputText id="endDate" value="#{billable.billable.endDate}" title="EndDate" >
<f:convertDateTime pattern="MM/dd/yyyy HH:mm:ss" />
</h:inputText>
to:
<h:outputText value="EndDate (MM/dd/yyyy):"/>
<h:inputText id="endDate" value="#{billable.billable.endDate}" title="EndDate" validator="#{billable.validateEndDate}" converterMessage="Invalid end date.">
<f:convertDateTime pattern="MM/dd/yyyy" />
</h:inputText>
- Change <h:inputText id="hours" value="#{billable.billable.hours}" title="Hours" required="true" requiredMessage="The hours field is required." /> to <<h:inputText id="hours" value="#{billable.billable.hours}" title="Hours" required="true" requiredMessage="The hours field is required." converterMessage="The hours field must be an integer." />.
- Change <h:inputText id="hourlyRate" value="#{billable.billable.hourlyRate}" title="HourlyRate" required="true" requiredMessage="The hourlyRate field is required." />
to <h:outputText value="#{billable.billable.hourlyRate}" title="HourlyRate" />}}.
- Remove the following:
<h:outputText value="BillableHourlyRate:"/>
<h:inputText id="billableHourlyRate" value="#{billable.billable.billableHourlyRate}" title="BillableHourlyRate" required="true" requiredMessage="The billableHourlyRate field is required." />
- Remove the following:
<h:outputText value="ConsultantId:"/>
<h:selectOneMenu id="consultantId" value="#{billable.billable.consultantId}" title="ConsultantId" required="true" requiredMessage="The consultantId field is required." >
<f:selectItems value="#{consultant.consultantItemsAvailableSelectOne}"/>
</h:selectOneMenu>
- Change <tt><f:selectItems value="#{project.projectItemsAvailableSelectOne}"/> to <f:selectItems value="#{project.assignedProjectsForLoggedInConsultantSelectOne}"/>.
- Change <h:commandLink action="#{billable.listSetup}" value="Show All Billable Items" immediate="true"/> to <h:commandLink action="#{billable.searchSetup}" value="Search Billable Items" immediate="true"/>.
Editing Detail.jsp
In Web Pages > billable > Detail.jsp, make the following changes.
- After <h:outputText value="#{billable.billable.startDate}" title="StartDate" >, change <f:convertDateTime pattern="MM/dd/yyyy HH:mm:ss" /> to <f:convertDateTime pattern="MM/dd/yyyy" />.
- After <h:outputText value="#{billable.billable.endDate}" title="EndDate" >, change <f:convertDateTime pattern="MM/dd/yyyy HH:mm:ss" /> to <f:convertDateTime pattern="MM/dd/yyyy" />.
- Remove the following:
- Remove the following:
<h:outputText value="ConsultantId:"/>
<h:panelGroup>
<h:outputText value=" #{billable.billable.consultantId}"/>
<h:panelGroup rendered="#{billable.billable.consultantId != null}">
<h:outputText value=" ("/>
<h:commandLink value="Show" action="#{consultant.detailSetup}">
<f:param name="jsfcrud.currentBillable" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable | billable.billable]][Billable.converter].jsfcrud_invoke}"/>
<f:param name="jsfcrud.currentConsultant" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable.consultantId | billable.billable.consultantId]][Consultant.converter].jsfcrud_invoke}"/>
<f:param name="jsfcrud.relatedController" value="billable"/>
<f:param name="jsfcrud.relatedControllerType" value="jsf.BillableController"/>
</h:commandLink>
<h:outputText value=" "/>
<h:commandLink value="Edit" action="#{consultant.editSetup}">
<f:param name="jsfcrud.currentBillable" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable | billable.billable]][Billable.converter].jsfcrud_invoke}"/>
<f:param name="jsfcrud.currentConsultant" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable.consultantId | billable.billable.consultantId]][Consultant.converter].jsfcrud_invoke}"/>
<f:param name="jsfcrud.relatedController" value="billable"/>
<f:param name="jsfcrud.relatedControllerType" value="jsf.BillableController"/>
</h:commandLink>
<h:outputText value=" "/>
<h:commandLink value="Destroy" action="#{consultant.destroy}">
<f:param name="jsfcrud.currentBillable" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable | billable.billable]][Billable.converter].jsfcrud_invoke}"/>
<f:param name="jsfcrud.currentConsultant" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable.consultantId | billable.billable.consultantId]][Consultant.converter].jsfcrud_invoke}"/>
<f:param name="jsfcrud.relatedController" value="billable"/>
<f:param name="jsfcrud.relatedControllerType" value="jsf.BillableController"/>
</h:commandLink>
<h:outputText value=" )"/>
</h:panelGroup>
</h:panelGroup>
- Change the following:
<h:panelGroup>
<h:outputText value=" #{billable.billable.project}"/>
<h:panelGroup rendered="#{billable.billable.project != null}">
<h:outputText value=" ("/>
<h:commandLink value="Show" action="#{project.detailSetup}">
<f:param name="jsfcrud.currentBillable" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable | billable.billable]][Billable.converter].jsfcrud_invoke}"/>
<f:param name="jsfcrud.currentProject" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable.project | billable.billable.project]][Project.converter].jsfcrud_invoke}"/>
<f:param name="jsfcrud.relatedController" value="billable"/>
<f:param name="jsfcrud.relatedControllerType" value="jsf.BillableController"/>
</h:commandLink>
<h:outputText value=" "/>
<h:commandLink value="Edit" action="#{project.editSetup}">
<f:param name="jsfcrud.currentBillable" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable | billable.billable]][Billable.converter].jsfcrud_invoke}"/>
<f:param name="jsfcrud.currentProject" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable.project | billable.billable.project]][Project.converter].jsfcrud_invoke}"/>
<f:param name="jsfcrud.relatedController" value="billable"/>
<f:param name="jsfcrud.relatedControllerType" value="jsf.BillableController"/>
</h:commandLink>
<h:outputText value=" "/>
<h:commandLink value="Destroy" action="#{project.destroy}">
<f:param name="jsfcrud.currentBillable" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable | billable.billable]][Billable.converter].jsfcrud_invoke}"/>
<f:param name="jsfcrud.currentProject" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable.project | billable.billable.project]][Project.converter].jsfcrud_invoke}"/>
<f:param name="jsfcrud.relatedController" value="billable"/>
<f:param name="jsfcrud.relatedControllerType" value="jsf.BillableController"/>
</h:commandLink>
<h:outputText value=" )"/>
</h:panelGroup>
</h:panelGroup>
to:
<h:outputText value=" #{billable.billable.project}"/>
- Change the following:
<h:commandLink action="#{billable.destroy}" value="Destroy">
<f:param name="jsfcrud.currentBillable" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable | billable.billable]][Billable.converter].jsfcrud_invoke}" />
</h:commandLink>
to:
<h:commandLink action="#{billable.destroy}" value="Destroy">
<f:param name="jsfcrud.currentBillable" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable | billable.billable]][[Billable.converter | billable.converter]].jsfcrud_invoke}" />
<f:param name="jsfcrud.timecard.consultantOfCurrentBillable" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Billable.billable.consultantId | billable.billable.consultantId]][[Consultant.converter | consultant.converter]].jsfcrud_invoke}"/>
</h:commandLink>
- Change <h:commandLink action="#{billable.listSetup}" value="Show All Billable Items"/> to <h:commandLink action="#{billable.searchSetup}" value="Search Billable Items"/>.
Editing Edit.jsp
In Web Pages > billable > Edit.jsp, make the following changes.
- Change <h:form> to <h:form id="form1">.
- Change the following:
to:
<h:outputText value="StartDate (MM/dd/yyyy):"/>
<h:inputText id="startDate" value="#{billable.billable.startDate}" title="StartDate" converterMessage="Invalid start date.">
<f:convertDateTime pattern="MM/dd/yyyy" />
</h:inputText>
- Change the following:
<h:outputText value="EndDate (MM/dd/yyyy HH:mm:ss):"/>
<h:inputText id="endDate" value="#{billable.billable.endDate}" title="EndDate" >
<f:convertDateTime pattern="MM/dd/yyyy HH:mm:ss" />
</h:inputText>
to:
<h:outputText value="EndDate (MM/dd/yyyy):"/>
<h:inputText id="endDate" value="#{billable.billable.endDate}" title="EndDate" validator="#{billable.validateEndDate}" converterMessage="Invalid end date.">
<f:convertDateTime pattern="MM/dd/yyyy" />
</h:inputText>
- Change <h:inputText id="hours" value="#{billable.billable.hours}" title="Hours" required="true" requiredMessage="The hours field is required." /> to <h:inputText id="hours" value="#{billable.billable.hours}" title="Hours" required="true" requiredMessage="The hours field is required." converterMessage="The hours field must be an integer." />.
- Change <h:inputText id="hourlyRate" value="#{billable.billable.hourlyRate}" title="HourlyRate" required="true" requiredMessage="The hourlyRate field is required." />
to <h:outputText value="#{billable.billable.hourlyRate}" title="HourlyRate" />}}.
- Remove the following:
<h:outputText value="BillableHourlyRate:"/>
<h:inputText id="billableHourlyRate" value="#{billable.billable.billableHourlyRate}" title="BillableHourlyRate" required="true" requiredMessage="The billableHourlyRate field is required." />
- Remove the following:
<h:outputText value="ConsultantId:"/>
<h:selectOneMenu id="consultantId" value="#{billable.billable.consultantId}" title="ConsultantId" required="true" requiredMessage="The consultantId field is required." >
<f:selectItems value="#{consultant.consultantItemsAvailableSelectOne}"/>
</h:selectOneMenu>
- Change <tt><f:selectItems value="#{project.projectItemsAvailableSelectOne}"/> to <f:selectItems value="#{project.assignedProjectsForLoggedInConsultantSelectOne}"/>.
- Change <h:commandLink action="#{billable.listSetup}" value="Show All Billable Items" immediate="true"/> to <h:commandLink action="#{billable.searchSetup}" value="Search Billable Items" immediate="true"/>.
Creating AuthenticationPhaseListener.java
- Create a new class in the jsf.util package called AuthenticationPhaseListener that implements PhaseListener.
- Insert the following into the class definition between the curly braces:
- Right-click and select Fix Imports. Click Save All on the main toolbar.
Modifying the JPA Controllers
- Append the following code to the jpa.controllers.BillableJpaController class:
public List<Billable> findBillableEntities(int maxResults, int firstResult, String query, Map<String,Object> parameters) {
return findBillableEntities(false, maxResults, firstResult, query, parameters);
}
private List<Billable> findBillableEntities(boolean all, int maxResults, int firstResult, String query, Map<String,Object> parameters) {
EntityManager em = getEntityManager();
try {
Query q = em.createQuery(query);
if (parameters != null) {
for (Map.Entry<String,Object> entry : parameters.entrySet()) {
q.setParameter(entry.getKey(), entry.getValue());
}
}
if (!all) {
q.setMaxResults(maxResults);
q.setFirstResult(firstResult);
}
return q.getResultList();
} finally {
em.close();
}
}
public int getBillableCount(String query, Map<String,Object> parameters) {
EntityManager em = getEntityManager();
try {
Query q = em.createQuery(query);
if (parameters != null) {
for (Map.Entry<String,Object> entry : parameters.entrySet()) {
q.setParameter(entry.getKey(), entry.getValue());
}
}
return ((Long) q.getSingleResult()).intValue();
} finally {
em.close();
}
}
- Right-click and select Fix Imports. Click Save All on the main toolbar.
- Append the following code to the jpa.controllers.ConsultantJpaController class:
- Right-click and select Fix Imports. Click Save All on the main toolbar.
- Append the following code to the jpa.controllers.ProjectJpaController class:
- Right-click and select Fix Imports. Click Save All on the main toolbar.
Editing BillableController.java
In the jsf.BillableController class, make the following changes.
- Add the following member fields:
private Map<String,Object> searchParameters = null;
private static final String[] properties = {"billableId", "startDate", "endDate", "hours", "hourlyRate", "description", "project", "consultantId"};
- Add the getSearchHours() and setSearchHours(Short) methods as follows:
public Short getSearchHours() {
if (billable == null) {
return null;
}
short billableHours = billable.getHours();
if (billableHours == -1) {
return null;
}
return new Short(billableHours);
}
public void setSearchHours(Short hours) {
if (billable == null) {
return;
}
short hoursAsPrimitive = hours == null ? -1 : hours.shortValue();
billable.setHours(hoursAsPrimitive);
}
- In the getPagingInfo() method, change pagingInfo.setItemCount(jpaController.getBillableCount()); to pagingInfo.setItemCount(getItemCount());.
- In the getBillable() method, change billable = new Billable(); to billable = getNewBillable();.
- In the createSetup() method, change billable = new Billable(); to billable = getNewBillable();.
- In the create() method, before the try block, add the following:
- In the scalarSetup(String) method, before return destination;, add the following:
if (isOperationForbidden()) {
return null;
}
- In the edit() method, before the try block, add the following:
if (isOperationForbidden()) {
return null;
}
- In the destroy() method, before String idAsString = JsfUtil.getRequestParameter("jsfcrud.currentBillable");, add the following:
if (isOperationForbidden()) {
return null;
}
- In the getBillableItems() method, change billableItems = jpaController.findBillableEntities(pagingInfo.getBatchSize(), pagingInfo.getFirstItem()); to the following:
tweakSearchParameters();
String query = getQueryForParameters("select object(o) from Billable as o");
billableItems = jpaController.findBillableEntities(pagingInfo.getBatchSize(), pagingInfo.getFirstItem(), query, searchParameters);
- In the next() method, change reset(false); to reset(false, false);.
- In the prev() method, change reset(false); to reset(false, false);.
- Replace the reset(boolean) method with the following:
- In the validateCreate(FacesContext,UIComponent,Object) method, change Billable newBillable = new Billable(); to Billable newBillable = getNewBillable();.
- Add the following methods:
- Right-click and select Fix Imports. Click Save All on the main toolbar.
Editing ConsultantController.java
- In the jsf.ConsultantController class, add the login() and logout() methods as follows:
public String login() {
if (consultant == null) {
JsfUtil.addErrorMessage("An error occurred attempting to log in.");
return null;
}
String query = "select object(o) from Consultant as o where o.email = :email and o.password = :password";
Map<String,Object> parameters = new HashMap<String,Object>();
String email = consultant.getEmail();
parameters.put("email", email);
parameters.put("password", consultant.getPassword());
List<Consultant> consultants = null;
try {
consultants = jpaController.findConsultantEntities(1, 0, query, parameters);
} catch (Exception e) {
JsfUtil.ensureAddErrorMessage(e, "A persistence error occurred.");
}
if (consultants != null && consultants.size() > 0) {
Consultant c = consultants.get(0);
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(AuthenticationPhaseListener.AUTHENTICATED_CONSULTANT_KEY, c);
JsfUtil.addSuccessMessage("Welcome, " + email + ".");
return "welcome";
} else {
JsfUtil.addErrorMessage("Invalid login.");
return null;
}
}
public String logout() {
HttpSession session = (HttpSession)
FacesContext.getCurrentInstance().getExternalContext().getSession(false);
if (session != null) {
session.invalidate();
}
JsfUtil.addSuccessMessage("You are now logged out.");
return "login";
}
- Right-click and select Fix Imports. Click Save All on the main toolbar.
Editing ProjectController.java
- In the jsf.ProjectController class, add the following methods:
public SelectItem[] getBilledProjectsForLoggedInConsultantSelectOne() {
String query = "select distinct b.project from Billable as b where b.consultantId = :consultant";
Map<String,Object> parameters = new HashMap<String,Object>();
Consultant loggedInConsultant = AuthenticationPhaseListener.getLoggedInConsultant();
parameters.put("consultant", loggedInConsultant);
return JsfUtil.getSelectItems(jpaController.findProjectEntities(query, parameters), true);
}
public SelectItem[] getAssignedProjectsForLoggedInConsultantSelectOne() {
Consultant loggedInConsultant = AuthenticationPhaseListener.getLoggedInConsultant();
Collection<Project> assignedProjectsCollection = loggedInConsultant.getProjectCollection();
List assignedProjectsList = new ArrayList(assignedProjectsCollection);
return JsfUtil.getSelectItems(assignedProjectsList, true);
}
- Right-click and select Fix Imports. Click Save All on the main toolbar.
Editing faces-config.xml
- In the Projects window, expand the Configuration Files node.
- Double-click the faces-config.xml node.
- Click the XML tab to edit the raw XML source.
- Before the <application> element, add the following:
- After the navigation rule for the welcome outcome, add the following:
<navigation-rule>
<navigation-case>
<from-outcome>login</from-outcome>
<to-view-id>/login.jsp</to-view-id>
</navigation-case>
</navigation-rule>
- After the navigation rule for the billable_detail outcome, add the following:
<navigation-rule>
<navigation-case>
<from-outcome>billable_search</from-outcome>
<to-view-id>/billable/Search.jsp</to-view-id>
</navigation-case>
</navigation-rule>
Implementing Ajax Validation
In Web Pages > billable > Edit.jsp, make the following changes.
- After <h:form id="form1">, add <h:inputHidden binding="#{billable.ajaxValidationHidden}" id="ajaxValidationHidden" valueChangeListener="#{billable.ajaxValidationHiddenChanged}" value="value" />.
- Change <h:inputText id="startDate" value="#{billable.billable.startDate}" title="StartDate" converterMessage="Invalid start date." binding="#{billable.startDateInputField}"> to <h:inputText id="startDate" value="#{billable.billable.startDate}" title="StartDate" onkeyup="AjaxUtil.fireValidationAjaxTransaction(this);" converterMessage="Invalid start date." binding="#{billable.startDateInputField}">.
- Change <h:inputText id="endDate" value="#{billable.billable.endDate}" title="EndDate" validator="#{billable.validateEndDate}" converterMessage="Invalid end date."> to <h:inputText id="endDate" value="#{billable.billable.endDate}" title="EndDate" onkeyup="AjaxUtil.fireValidationAjaxTransaction(this);" validator="#{billable.validateEndDate}" converterMessage="Invalid end date.">.
- Change <h:inputText id="hours" value="#{billable.billable.hours}" title="Hours" required="true" requiredMessage="The hours field is required." converterMessage="The hours field must be an integer." /> to <h:inputText id="hours" value="#{billable.billable.hours}" title="Hours" required="true" requiredMessage="The hours field is required." converterMessage="The hours field must be an integer." onkeyup="AjaxUtil.fireValidationAjaxTransaction(this);" />.
- Change <h:selectOneMenu id="project" value="#{billable.billable.project}" title="Project" required="true" requiredMessage="The project field is required."> to <h:selectOneMenu id="project" value="#{billable.billable.project}" title="Project" required="true" requiredMessage="The project field is required." onchange="AjaxUtil.fireValidationAjaxTransaction(this);">.
var AjaxUtil = {};
AjaxUtil.getAllInputAcceptingChildIdArray = function(parentIdArray) {
var map = {};
for (var i = 0; i < parentIdArray.length; i++) {
var element = document.getElementById(parentIdArray[I]);
if (element == null) {
continue;
}
AjaxUtil.putInputAcceptingIdsRecursively(element, map);
}
var allInputAcceptingChildIdArray = [];
for (var key in map) {
allInputAcceptingChildIdArray.push(key);
}
return allInputAcceptingChildIdArray;
}
AjaxUtil.putInputAcceptingIdsRecursively = function(element, map) {
var isInputAccepting = false;
var nodeName = element.nodeName;
if (nodeName != null) {
nodeName = nodeName.toLowerCase();
if (nodeName.indexOf('input') == 0) {
isInputAccepting = true; //includes buttons
}
else if (nodeName.indexOf('textarea') == 0) {
isInputAccepting = true;
}
else if (nodeName.indexOf('select') == 0) {
isInputAccepting = true;
}
}
if (isInputAccepting == true) {
map[Element.id] = null;
}
if (element.hasChildNodes()) {
for (var i = 0; i < element.childNodes.length; i++) {
AjaxUtil.putInputAcceptingIdsRecursively(element.childNodes[I], map);
}
}
}
AjaxUtil.fireValidationAjaxTransaction = function(sourceElement) {
if (!jsfcrud.isDynamicFacesAvailable) {
return;
}
var formId = document.forms[0].id;
var ajaxValidationHiddenId = formId + ':ajaxValidationHidden';
var ajaxValidationHidden = document.getElementById(ajaxValidationHiddenId);
if (ajaxValidationHidden) {
ajaxValidationHidden.value = 'value' + new Date();
}
var inputIdArray = AjaxUtil.getAllInputAcceptingChildIdArray([FormId]);
var inputsAsString = inputIdArray.join();
DynaFaces.fireAjaxTransaction(sourceElement, {inputs:inputsAsString,execute:inputsAsString,render:'messagePanel,' + ajaxValidationHiddenId});
}
In the jsf.BillableController class, make the following changes.
- Add the following member field and methods:
private HtmlInputHidden ajaxValidationHidden = new HtmlInputHidden();
public HtmlInputHidden getAjaxValidationHidden() {
return ajaxValidationHidden;
}
public void setAjaxValidationHidden(HtmlInputHidden hidden) {
this.ajaxValidationHidden = hidden;
}
public void ajaxValidationHiddenChanged(javax.faces.event.ValueChangeEvent vce) {
FacesContext.getCurrentInstance().renderResponse();
ajaxValidationHidden.setValue("value");
}
- Right-click and select Fix Imports. Click Save All on the main toolbar.
