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

  1. In the Projects window, expand the Web Pages > consultant node. Right-click Edit.jsp and select Copy.
  2. Right-click on the Web Pages node and select Paste.
  3. Under the Web Pages node, rename Edit.jsp to login.jsp.
  4. Change <title>Editing Consultant</title> to <title>Consultant Timecard Application &ndash; Login</title>.
  5. Change

    Editing Consultant

    to

    Consultant Timecard Application &ndash; Login

    .
  6. Remove the following:
<h:outputText value="ConsultantId:"/> <h:outputText value="#{consultant.consultant.consultantId}" title="ConsultantId" />
  1. 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." />.
  2. Remove the following:
<h:outputText value="HourlyRate:"/> <h:inputText id="hourlyRate" value="#{consultant.consultant.hourlyRate}" title="HourlyRate" required="true" requiredMessage="The hourlyRate field is required." /> <h:outputText value="BillableHourlyRate:"/> <h:inputText id="billableHourlyRate" value="#{consultant.consultant.billableHourlyRate}" title="BillableHourlyRate" required="true" requiredMessage="The billableHourlyRate field is required." /> <h:outputText value="HireDate (MM/dd/yyyy):"/> <h:inputText id="hireDate" value="#{consultant.consultant.hireDate}" title="HireDate" > <f:convertDateTime pattern="MM/dd/yyyy" /> </h:inputText> <h:outputText value="Resume:"/> <h:inputTextarea rows="4" cols="30" id="resume" value="#{consultant.consultant.resume}" title="Resume" /> <h:outputText value="ProjectCollection:"/> <h:selectManyListbox id="projectCollection" value="#{consultant.consultant.jsfcrud_transform[[Jsfcrud_class[jsf.util.JsfUtil | jsfcrud_class['jsf.util.JsfUtil']].jsfcrud_method.collectionToArray][Jsfcrud_class[jsf.util.JsfUtil].jsfcrud_method.arrayToList].projectCollection}" title="ProjectCollection" size="6" converter="#{project.converter}" > <f:selectItems value="#{project.projectItemsAvailableSelectMany}"/> </h:selectManyListbox> <h:outputText value="BillableCollection:"/> <h:selectManyListbox id="billableCollection" value="#{consultant.consultant.jsfcrud_transform[[Jsfcrud_class[jsf.util.JsfUtil | jsfcrud_class['jsf.util.JsfUtil']].jsfcrud_method.collectionToArray][Jsfcrud_class[jsf.util.JsfUtil].jsfcrud_method.arrayToList].billableCollection}" title="BillableCollection" size="6" converter="#{billable.converter}" > <f:selectItems value="#{billable.billableItemsAvailableSelectMany}"/> </h:selectManyListbox> <h:outputText value="StatusId:"/> <h:selectOneMenu id="statusId" value="#{consultant.consultant.statusId}" title="StatusId" required="true" requiredMessage="The statusId field is required." > <f:selectItems value="#{consultantStatus.consultantStatusItemsAvailableSelectOne}"/> </h:selectOneMenu> <h:outputText value="RecruiterId:"/> <h:selectOneMenu id="recruiterId" value="#{consultant.consultant.recruiterId}" title="RecruiterId" > <f:selectItems value="#{recruiter.recruiterItemsAvailableSelectOne}"/> </h:selectOneMenu>
  1. Change <h:commandLink action="#{consultant.edit}" value="Save"> to <h:commandLink action="#{consultant.login}" value="Login" />.
  2. Remove the following:
<f:param name="jsfcrud.currentConsultant" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Consultant.consultant | consultant.consultant]][Consultant.converter].jsfcrud_invoke}"/> </h:commandLink> <br /> <br /> <h:commandLink action="#{consultant.detailSetup}" value="Show" immediate="true"> <f:param name="jsfcrud.currentConsultant" value="#{jsfcrud_class[[jsf.util.JsfUtil | 'jsf.util.JsfUtil']].jsfcrud_method[[getAsConvertedString | 'getAsConvertedString']][[Consultant.consultant | consultant.consultant]][Consultant.converter].jsfcrud_invoke}"/> </h:commandLink> <br /> <h:commandLink action="#{consultant.listSetup}" value="Show All Consultant Items" immediate="true"/> <br /> <h:commandLink value="Index" action="welcome" immediate="true" />

Editing welcomeJSF.jsp

In Web Pages > welcomeJSF.jsp, make the following changes.

  1. Change <title>JSP Page</title> to <title>Consultant Timecard Application</title>.
  2. Add the following just after the <body> tag:
<h:panelGroup id="messagePanel" layout="block"> <h:messages errorStyle="color: red" infoStyle="color: green" layout="table"/> </h:panelGroup>
  1. Change

    <h:outputText value="JavaServer Faces" />

    to

    <h:outputText value="Consultant Timecard Application" />

    .
  2. Change the following:
<h:commandLink action="#{recruiter.listSetup}" value="Show All Recruiter Items"/> <br/> <h:commandLink action="#{project.listSetup}" value="Show All Project Items"/> <br/> <h:commandLink action="#{consultantStatus.listSetup}" value="Show All ConsultantStatus Items"/> <br/> <h:commandLink action="#{consultant.listSetup}" value="Show All Consultant Items"/> <br/> <h:commandLink action="#{client.listSetup}" value="Show All Client Items"/> <br/> <h:commandLink action="#{billable.listSetup}" value="Show All Billable Items"/> <br/> <h:commandLink action="#{address.listSetup}" value="Show All Address Items"/>
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

  1. In the Projects window, expand the Web Pages > billable node. Right-click Edit.jsp and select Copy.
  2. Right-click on the Web Pages > billable node and select Paste.
  3. Under the Web Pages > billable node, rename Edit_1.jsp to Search.jsp.
  4. Change <title>Editing Billable</title> to <title>Search Billable Items</title>.
  5. Change

    Editing Billable

    to

    Search Billable Items

    .
  6. Change <h:form> to <h:form id="form1">.
  7. 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."/>.
  8. Change the following:
<h:outputText value="StartDate (MM/dd/yyyy HH:mm:ss):"/> <h:inputText id="startDate" value="#{billable.billable.startDate}" title="StartDate" > <f:convertDateTime pattern="MM/dd/yyyy HH:mm:ss" /> </h:inputText>
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>

  1. 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>
  1. 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."/>.
  2. 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."/>.
  3. 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." />
  1. 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>

  1. 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>

  1. 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"/>

  1. 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.

  1. Change <title>Listing Billable Items</title> to <title>Billable Results</title>.
  2. Change

    Listing Billable Items

    to

    Billable Results

    .
  3. After <h:outputText value="#{item.startDate}">, change <f:convertDateTime pattern="MM/dd/yyyy HH:mm:ss" /> to <f:convertDateTime pattern="MM/dd/yyyy" />.
  4. After <h:outputText value="#{item.endDate}">, change <f:convertDateTime pattern="MM/dd/yyyy HH:mm:ss" /> to <f:convertDateTime pattern="MM/dd/yyyy" />.
  5. Remove the following:
<h:column> <f:facet name="header"> <h:outputText value="BillableHourlyRate"/> </f:facet> <h:outputText value=" #{item.billableHourlyRate}"/> </h:column>
  1. Remove the following:
                       <h:column>
                           <f:facet name="header">
                               <h:outputText value="ConsultantId"/>
                           </f:facet>
                           <h:outputText value=" #{item.consultantId}"/>
                       </h:column>

  1. 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>

  1. 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.

  1. Change <h:form> to <h:form id="form1">.
  2. Change the following:
<h:outputText value="StartDate (MM/dd/yyyy HH:mm:ss):"/> <h:inputText id="startDate" value="#{billable.billable.startDate}" title="StartDate" > <f:convertDateTime pattern="MM/dd/yyyy HH:mm:ss" /> </h:inputText>
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>

  1. 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>

  1. 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." />.
  2. 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" />}}.

  1. 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." />

  1. 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>

  1. Change <tt><f:selectItems value="#{project.projectItemsAvailableSelectOne}"/> to <f:selectItems value="#{project.assignedProjectsForLoggedInConsultantSelectOne}"/>.
  2. 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.

  1. 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" />.
  2. 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" />.
  3. Remove the following:
<h:outputText value="BillableHourlyRate:"/> <h:outputText value="#{billable.billable.billableHourlyRate}" title="BillableHourlyRate" />
  1. 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>

  1. 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}"/>


  1. 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>

  1. 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.

  1. Change <h:form> to <h:form id="form1">.
  2. Change the following:
<h:outputText value="StartDate (MM/dd/yyyy HH:mm:ss):"/> <h:inputText id="startDate" value="#{billable.billable.startDate}" title="StartDate" > <f:convertDateTime pattern="MM/dd/yyyy HH:mm:ss" /> </h:inputText>
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>

  1. 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>

  1. 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." />.
  2. 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" />}}.

  1. 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." />

  1. 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>

  1. Change <tt><f:selectItems value="#{project.projectItemsAvailableSelectOne}"/> to <f:selectItems value="#{project.assignedProjectsForLoggedInConsultantSelectOne}"/>.
  2. 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

  1. Create a new class in the jsf.util package called AuthenticationPhaseListener that implements PhaseListener.
  2. Insert the following into the class definition between the curly braces:
/** * <p>The outcome to trigger navigation to the login page.</p> */ private static final String LOGIN_OUTCOME = "login"; /** * <p>The outcome to trigger navigation to the welcome page.</p> */ private static final String WELCOME_OUTCOME = "welcome"; /** * <p>The session attribute key used to store an authenticated consultant.</p> */ public static final String AUTHENTICATED_CONSULTANT_KEY = "jsfcrud.timecard.consultant"; /** * <p>Invoke <code>verifyView</code> if the current phase is apply request values or render response.</p> */ public void beforePhase(PhaseEvent event) { PhaseId phase = event.getPhaseId(); if (PhaseId.APPLY_REQUEST_VALUES.equals(phase) || PhaseId.RENDER_RESPONSE.equals(phase)) { verifyView(event); } } /** * <p>No-op.</p> */ public void afterPhase(PhaseEvent event) { } /** * <p>If the requested view is forbidden, change the requested * view to the welcome view; then if the user * is not logged in and is requesting a secure view, * direct the user to the login page; otherwise, direct the user * to the requested view.</p> */ private void verifyView(PhaseEvent event) { FacesContext context = event.getFacesContext(); String viewId = context.getViewRoot().getViewId(); String forwardToOutcome = null; if (isForbiddenView(viewId)) { JsfUtil.addErrorMessage("You do not have permission to view the requested page."); //change requested view to the welcome view //and assume we will forward to that view viewId = "/welcomeJSF.jsp"; forwardToOutcome = WELCOME_OUTCOME; } if (getLoggedInConsultant() == null) { if (isSecureView(viewId)) { forwardToOutcome = LOGIN_OUTCOME; } } if (forwardToOutcome != null) { context.getApplication(). getNavigationHandler().handleNavigation(context, null, forwardToOutcome); } } /** * <p>Specify <code>PhaseId.ANY_PHASE</code> and execute logic conditionally * in <code>beforePhase</<code> if the phase is apply request values or * render response.</p> * @return <code>PhaseId.ANY_PHASE</code>. */ public PhaseId getPhaseId() { return PhaseId.ANY_PHASE; } /** * <p>Obtain the logged in consultant stored in session (or null).</p> * @return the logged in <code>Consultant</code> or <code>null</code> if * no such <code>Consultant</code> exists. */ public static Consultant getLoggedInConsultant() { return (Consultant)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(AuthenticationPhaseListener.AUTHENTICATED_CONSULTANT_KEY); } /** * <p>Determines if the requested view requires authentication.</p> * @param context the <code>FacesContext</code> for the current request. * @return <code>true</code> if the requested view requires authentication, otherwise <code>false</code>. */ private boolean isSecureView(String viewId) { if (viewId == null) { return false; } if (isUnrestrictedView(viewId)) { return false; } return ("/welcomeJSF.jsp".equals(viewId) || viewId.startsWith("/billable/")); } /** * <p>Determines if the requested view is forbidden, namely, * any resource that is not considered unrestricted or secure.</p> * @param context the <code>FacesContext</code> for the current request. * @return <code>true</code> if the requested view is forbidden, otherwise <code>false</code>. */ private boolean isForbiddenView(String viewId) { if (viewId == null) { return true; } //only unrestricted and secure views are permitted if (isUnrestrictedView(viewId) || isSecureView(viewId)) { return false; } return true; } /** * <p>Determine if the view supplied is unrestricted, that is, can be accessed * without authenticating. For this example, the login page, JavaScript resources, * CSS resources, and image resources are unrestricted.</p> * @param viewId The supplied view. * @return Whether the supplied view is unrestricted. */ private boolean isUnrestrictedView(String viewId) { return "/login.jsp".equals(viewId) || "/jsfcrud.js".equals(viewId) || "/jsfcrud.css".equals(viewId) || "/busy.gif".equals(viewId); }
  1. Right-click and select Fix Imports. Click Save All on the main toolbar.

Modifying the JPA Controllers

  1. 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();
       }
   }

  1. Right-click and select Fix Imports. Click Save All on the main toolbar.
  2. Append the following code to the jpa.controllers.ConsultantJpaController class:
public List<Consultant> findConsultantEntities(int maxResults, int firstResult, String query, Map<String,Object> parameters) { return findConsultantEntities(false, maxResults, firstResult, query, parameters); } private List<Consultant> findConsultantEntities(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(); } }
  1. Right-click and select Fix Imports. Click Save All on the main toolbar.
  2. Append the following code to the jpa.controllers.ProjectJpaController class:
public List<Project> findProjectEntities(String query, Map<String,Object> parameters) { return findProjectEntities(true, -1, -1, query, parameters); } private List<Project> findProjectEntities(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(); } }
  1. 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.

  1. Add the following member fields:
   private Map<String,Object> searchParameters = null;
   private static final String[] properties = {"billableId", "startDate", "endDate", "hours", "hourlyRate", "description", "project", "consultantId"};

  1. 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);
   }

  1. In the getPagingInfo() method, change pagingInfo.setItemCount(jpaController.getBillableCount()); to pagingInfo.setItemCount(getItemCount());.
  2. In the getBillable() method, change billable = new Billable(); to billable = getNewBillable();.
  3. In the createSetup() method, change billable = new Billable(); to billable = getNewBillable();.
  4. In the create() method, before the try block, add the following:
if (isOperationForbidden()) { return null; }
  1. In the scalarSetup(String) method, before return destination;, add the following:
       if (isOperationForbidden()) {
           return null;
       }

  1. In the edit() method, before the try block, add the following:
       if (isOperationForbidden()) {
           return null;
       }

  1. In the destroy() method, before String idAsString = JsfUtil.getRequestParameter("jsfcrud.currentBillable");, add the following:
       if (isOperationForbidden()) {
           return null;
       }

  1. 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);

  1. In the next() method, change reset(false); to reset(false, false);.
  2. In the prev() method, change reset(false); to reset(false, false);.
  3. Replace the reset(boolean) method with the following:
private void reset(boolean resetFirstItem, boolean resetSearchParameters) { billable = null; billableItems = null; pagingInfo.setItemCount(-1); if (resetFirstItem) { pagingInfo.setFirstItem(0); } if (resetSearchParameters) { searchParameters = null; } } private void reset(boolean resetFirstItem) { reset(resetFirstItem, true); }
  1. In the validateCreate(FacesContext,UIComponent,Object) method, change Billable newBillable = new Billable(); to Billable newBillable = getNewBillable();.
  2. Add the following methods:
public String searchSetup() { reset(false); billable = new Billable(); billable.setHours((short)-1); return "billable_search"; } public String search() { searchParameters = new HashMap<String,Object>(); Object[] values = {billable.getBillableId(), billable.getStartDate(), billable.getEndDate(), new Short(billable.getHours()), billable.getHourlyRate(), billable.getDescription(), billable.getProject(), null}; for (int i = 0; i < properties.length; i++) { if (values[I] != null) { if("hours".equals(properties[I])) { if (((Short)values[I]).shortValue() == -1) { continue; } } else if (values[I] instanceof String) { String trimmedValue = ((String)values[I]).trim(); if (trimmedValue.length() == 0) { continue; } trimmedValue = trimmedValue.replaceAll("~", "~~"); trimmedValue = trimmedValue.replaceAll("%", "~%"); values[I] = "%" + trimmedValue + "%"; } searchParameters.put(properties[[I | i]], values[I]); } } reset(true, false); return "billable_list"; } public int getItemCount() { tweakSearchParameters(); String query = getQueryForParameters("select count(o) from Billable as o"); return jpaController.getBillableCount(query, searchParameters); } private String getQueryForParameters(String baseQuery) { if (searchParameters == null) { return baseQuery; } StringBuffer where = new StringBuffer(); for (int i = 0; i < properties.length; i++) { if (searchParameters.containsKey(properties[I])) { if (where.length() > 0) { where.append(" and "); } if ("startDate".equals(properties[I])) { where.append("(o.startDate is null or o.startDate >= :startDate) and (o.endDate is null or o.endDate >= :startDate)"); } else if ("endDate".equals(properties[I])) { where.append("(o.startDate is null or o.startDate <= :endDate) and (o.endDate is null or o.endDate <= :endDate)"); } else if (searchParameters.get(properties[I]) instanceof String) { where.append("o." + properties[[I | i]] + " like :" + properties[I] + " escape '~'"); } else { where.append("o." + properties[[I | i]] + " = :" + properties[I]); } } } if (where.length() > 0) { baseQuery += " where " + where; } return baseQuery; } public void validateEndDate(FacesContext facesContext, UIComponent component, Object value) { ValueHolder startDateInputField = (ValueHolder)facesContext.getViewRoot().findComponent("form1:startDate"); Date startDate = (Date)startDateInputField.getLocalValue(); if (startDate != null) { Date endDate = (Date)value; if (startDate.after(endDate)) { throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "The end date cannot precede the start date.", null)); } } } private Billable getNewBillable() { Billable result = new Billable(); Consultant consultant = AuthenticationPhaseListener.getLoggedInConsultant(); result.setConsultantId(consultant); result.setHourlyRate(consultant.getHourlyRate()); result.setBillableHourlyRate(consultant.getBillableHourlyRate()); return result; } private boolean isOperationForbidden() { boolean forbidden = false; Consultant loggedInConsultant = AuthenticationPhaseListener.getLoggedInConsultant(); if (loggedInConsultant == null) { forbidden = true; } else if (billable == null) { //destroy operation String consultantOfCurrentBillableAsString = JsfUtil.getRequestParameter("jsfcrud.timecard.consultantOfCurrentBillable"); if (consultantOfCurrentBillableAsString != null) { Integer consultantOfCurrentBillableAsInteger = new Integer(consultantOfCurrentBillableAsString); if (!consultantOfCurrentBillableAsInteger.equals(loggedInConsultant.getConsultantId())) { forbidden = true; } } } else if (!loggedInConsultant.equals(billable.getConsultantId())) { //detail or edit operation forbidden = true; } if (forbidden) { JsfUtil.addErrorMessage("You do not have permission to perform the requested operation."); } return forbidden; } private void tweakSearchParameters() { if (searchParameters == null) { searchParameters = new HashMap<String,Object>(); } if (searchParameters.get(properties[Properties.length1]) == null) { Consultant loggedInConsultant = AuthenticationPhaseListener.getLoggedInConsultant(); searchParameters.put(properties[Properties.length1], loggedInConsultant); } }
  1. Right-click and select Fix Imports. Click Save All on the main toolbar.

Editing ConsultantController.java

  1. 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";
   }

  1. Right-click and select Fix Imports. Click Save All on the main toolbar.

Editing ProjectController.java

  1. 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);
   }

  1. Right-click and select Fix Imports. Click Save All on the main toolbar.

Editing faces-config.xml

  1. In the Projects window, expand the Configuration Files node.
  2. Double-click the faces-config.xml node.
  3. Click the XML tab to edit the raw XML source.
  4. Before the <application> element, add the following:
<lifecycle> <phase-listener> jsf.util.AuthenticationPhaseListener </phase-listener> </lifecycle>
  1. 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>

  1. 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.

  1. After <h:form id="form1">, add <h:inputHidden binding="#{billable.ajaxValidationHidden}" id="ajaxValidationHidden" valueChangeListener="#{billable.ajaxValidationHiddenChanged}" value="value" />.
  2. 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}">.
  3. 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.">.
  4. 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);" />.
  5. 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);">.


In Web Pages > jsfcrud.js, append the following:
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.

  1. 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");
   }

  1. Right-click and select Fix Imports. Click Save All on the main toolbar.
Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo