40
JSF Lifecycle Diagram APPLY_REQUEST_VALUES Process Events Process Decodes RESTORE_VIEW Build Comp Tree Parse PDL Apply Saved State (Post Only) HTTP POST / Partial Submit PROCESS_VALIDATIONS Process Events Process Validators Faces Request HTTP GET If immediate=“true” then Actions, Action Listeners, and Value Change Listeners fire here <f:view> <h:form> <h:outputLabel /> <h:inputText /> Facelet View Markup UIViewRoot HtmlForm HtmlOutputLabel Component Tree Value Change Listeners Fire Here ICESOFT TECHNOLOGIES INC. www.icefaces.org Conversion/Validation Failure UPDATE_MODEL_VALUES Process Updates Process Events INVOKE_APPLICATION Process Application Process Events RENDER_RESPONSE Process Renderers Save Comp State Conversion/Validation Success Faces Response Actions & Action Listeners fire here <h:commandButton /> </h:form> </f:view> HtmlCommandButton HtmlInputText

JSF Lifecycle Diagram - ICEsoft Technologiesres.icesoft.org/self-serve-training/Intro-to-IF-1.8-Chapter-2... · JSF Lifecycle Diagram (HTTP ... be registered as a PhaseListener when

  • Upload
    ngohanh

  • View
    223

  • Download
    5

Embed Size (px)

Citation preview

JSF Lifecycle Diagram

APPLY_REQUEST_VALUES

ProcessEvents

ProcessDecodes

RESTORE_VIEW

BuildComp Tree

ParsePDL

ApplySaved State(Post Only)

HTTP POST / Partial Submit

PROCESS_VALIDATIONS

ProcessEvents

ProcessValidators

FacesRequest

HTTPGET

If immediate=“true” then Actions, Action Listeners, and Value Change Listeners fire here

<f:view><h:form><h:outputLabel /><h:inputText />

Facelet View Markup UIViewRoot

HtmlForm

HtmlOutputLabel

Component Tree

Value Change Listeners Fire

Here

ICESOFT TECHNOLOGIES INC. www.icefaces.org

Conversion/Validation Failure

UPDATE_MODEL_VALUES

ProcessUpdates

ProcessEvents

INVOKE_APPLICATION

ProcessApplication

ProcessEvents

RENDER_RESPONSE

ProcessRenderers

SaveComp State

Conversion/Validation Success

FacesResponse

Actions & Action Listeners fire

here

<h:inputText /><h:commandButton />

</h:form></f:view> HtmlCommandButton

HtmlInputText

JSF Lifecycle

• The framework defines a lifecycle that executes in distinct phases:– Restore View

– Apply Request Values

– Process Validations

– Update Model Values

ICESOFT TECHNOLOGIES INC. www.icefaces.org

– Update Model Values

– Invoke Application

– Render Response

JSF Lifecycle Phase: Restore View

RESTORE_VIEW

BuildComp Tree

ParsePDL

ApplySaved State(Post Only)

<f:view><h:form><h:outputLabel /><h:inputText />

Facelet View Markup UIViewRoot

HtmlForm

HtmlOutputLabel

Component Tree

ICESOFT TECHNOLOGIES INC. www.icefaces.org

• The Restore View phase restores an existing view from the previous request, or creates a new view for an initial request

• The resulting view is put into the current FacesContext

<h:inputText /><h:commandButton />

</h:form></f:view> HtmlCommandButton

HtmlInputText

JSF Lifecycle Diagram (HTTP GET)

RESTORE_VIEW

BuildComp Tree

ParsePDL

(GET Only)

FacesRequest

HTTPGET

<f:view><h:form><h:outputLabel /><h:inputText />

Facelet View Markup UIViewRoot

HtmlForm

HtmlOutputLabel

Component Tree

ICESOFT TECHNOLOGIES INC. www.icefaces.org

RENDER_RESPONSE

ProcessRenderers

SaveComp State

FacesResponse

<h:inputText /><h:commandButton />

</h:form></f:view> HtmlCommandButton

HtmlInputText

JSF Lifecycle Phase: Render Response

• The Render Response phase is responsible for– Invoking component renderers for the appropriate client device

– Sending a fully encoded response back to the client

– The response is typically HTML markup that is written to the HttpServletResponse OutputStream

Rendered HTML for Web Browser

ICESOFT TECHNOLOGIES INC. www.icefaces.org

RENDER_RESPONSE

ProcessRenderers

SaveComp State

<html id="document:html"><body id="document:body"><form id="form1">

<label for="firstName" /><input id="firstName" /><input type="submit" />

</form></body>

Rendered HTML for Web Browser

JSF Lifecycle Diagram (HTTP POST – Valid Values)

APPLY_REQUEST_VALUES

ProcessEvents

ProcessDecodes

RESTORE_VIEW

BuildComp Tree

ApplySaved State(POST Only)

HTTP POST / Partial Submit

PROCESS_VALIDATIONS

ProcessEvents

ProcessValidators

FacesRequest

UIViewRoot

HtmlForm

HtmlOutputLabel

Component Tree

ICESOFT TECHNOLOGIES INC. www.icefaces.org

UPDATE_MODEL_VALUES

ProcessUpdates

ProcessEvents

INVOKE_APPLICATION

ProcessApplication

ProcessEvents

RENDER_RESPONSE

ProcessRenderers

SaveComp State

Conversion/Validation Success

FacesResponse

HtmlCommandButton

HtmlInputText

JSF Lifecycle Phase: Apply Request Values

• The Apply Request Values phase is where submitted request parameters are mapped to their corresponding UIInput components

APPLY_REQUEST_VALUES

ProcessEvents

ProcessDecodes

UIViewRoot

HtmlForm

HtmlOutputLabel

Component Tree

RequestParameterValues

ICESOFT TECHNOLOGIES INC. www.icefaces.org

HtmlCommandButton

HtmlInputText

// Process decodes does something// kind of like this for each// EditableValueHolder:String firstName =

request.getParameter(“firstName”);UIInput.setSubmittedValue(firstName);

JSF Lifecycle Phase: Process Validations

• The Process Validations phase is where submitted values are processed by JSF converters and validators

PROCESS_VALIDATIONS

ProcessEvents

ProcessValidators

UIViewRoot

HtmlForm

HtmlOutputLabel

Component Tree

ICESOFT TECHNOLOGIES INC. www.icefaces.org

HtmlCommandButton

HtmlInputText

• If any component fails validation, then– The component’s valid property is set to false

– A FacesMessage is added to the FacesContext

// If validation passes:UIInput.setValid(true);

// Otherwise:UIInput.setValid(false);

JSF Lifecycle Phase: Update Model Values

• If conversion & validation passes, then the Update Model Values phase is reached

• If EL value bindings were specified on UIInput components, then those component values are set in the model

• For example, the following EL value binding:

ICESOFT TECHNOLOGIES INC. www.icefaces.org

<h:inputText value=“#{MyBean.firstName}”/>

… will cause the MyBean.setFirstName()method to be called and will pass it the result of HtmlInputText.getValue()

UPDATE_MODEL_VALUES

ProcessUpdates

ProcessEvents

Conversion/Validation Success

JSF Lifecycle Diagram (HTTP POST – Invalid Values)

APPLY_REQUEST_VALUES

ProcessEvents

ProcessDecodes

RESTORE_VIEW

BuildComp Tree

ApplySaved State(POST Only)

HTTP POST / Partial Submit

PROCESS_VALIDATIONS

ProcessEvents

ProcessValidators

FacesRequest

UIViewRoot

HtmlForm

HtmlOutputLabel

Component Tree

ICESOFT TECHNOLOGIES INC. www.icefaces.org

UPDATE_MODEL_VALUES

ProcessUpdates

ProcessEvents

INVOKE_APPLICATION

ProcessApplication

ProcessEvents

RENDER_RESPONSE

ProcessRenderers

SaveComp State

FacesResponse

HtmlCommandButton

HtmlInputText

Conversion/Validation Failure

JSF Lifecycle Phase: Invoke Application

• The Invoke Application phase is responsible for reacting to the submitted values by invoking methods in managed-beans that perform some kind of action

• ActionListener methods are called first, then Actions

• Markup Examples:

ICESOFT TECHNOLOGIES INC. www.icefaces.org

<h:commandButtonactionListener=

“#{MyBean.checkAll}” />

<h:commandButton action=“#{MyBean.submit}” />

INVOKE_APPLICATION

ProcessApplication

ProcessEvents

JSF Lifecycle Diagram: Events

APPLY_REQUEST_VALUES

ProcessEvents

ProcessDecodes

RESTORE_VIEW

BuildComp Tree

ParsePDL

ApplySaved State(Post Only)

HTTP POST / Partial Submit

PROCESS_VALIDATIONS

ProcessEvents

ProcessValidators

FacesRequest

If immediate=“true” then Actions, Action Listeners, and Value Change Listeners fire here

Value Change Listeners Fire

Here

ICESOFT TECHNOLOGIES INC. www.icefaces.org

UPDATE_MODEL_VALUES

ProcessUpdates

ProcessEvents

INVOKE_APPLICATION

ProcessApplication

ProcessEvents

RENDER_RESPONSE

ProcessRenderers

SaveComp State

Conversion/Validation Success

FacesResponse

Actions & Action Listeners fire

here

In JSF 1.x, there are no events that fire here

Phase Listeners

• PhaseListeners can be extremely helpful for application customization, optimization, and debugging

• Must implement the following interface:– javax.faces.application.PhaseListener

• Use javax.faces.event.PhaseId to specify which phase to listen for

ICESOFT TECHNOLOGIES INC. www.icefaces.org

• Register implementing class in the faces-config.xml

<lifecycle><phase-listener>training.jobApplication.lifecycle.LoggingPhaseListener

</phase-listener></lifecycle>

Exercise: Overview

• The goal of this exercise is to add a PhaseListener to the jobApplication project

• The PhaseListener will simply log the Phase ID to the Tomcat console log, before and after phases execute

ICESOFT TECHNOLOGIES INC. www.icefaces.org

Step 1: Create LoggingPhaseListener.java

LoggingPhaseListener

ICESOFT TECHNOLOGIES INC. www.icefaces.org

Step 2: Paste Java Code

• For the sake of convenience, open the LoggingPhaseListener.java file in the Eclipse Java Editor and paste the following code as the body of the LoggingPhaseListener class:

private static final long serialVersionUID = 5805974145765679633L;

private static final Log log = LogFactory.getLog(LoggingPhaseListener.class);

public void afterPhase(PhaseEvent phaseEvent) {

ICESOFT TECHNOLOGIES INC. www.icefaces.org

if (log.isInfoEnabled()) {log.info("AFTER PHASE: " + phaseEvent.getPhaseId().toString());

}}public void beforePhase(PhaseEvent phaseEvent) {if (log.isInfoEnabled()) {

log.info("BEFORE PHASE: " + phaseEvent.getPhaseId().toString());}

}public PhaseId getPhaseId() {return PhaseId.ANY_PHASE;

}

Step 3: Paste XML

• Paste the following XML fragment into the faces-config.xml file:<lifecycle>

<phase-listener>

training.jobapplication.lifecycle.LoggingPhaseListener

</phase-listener>

ICESOFT TECHNOLOGIES INC. www.icefaces.org

</lifecycle>

• This fragment will cause the LoggingPhaseListener class to be registered as a PhaseListener when the JSF framework initializes

Step 4: Configure Log4J

• Create a file named log4j.properties in the src folder

• Paste the following into the file:log4j.rootLogger=ERROR, A1

log4j.appender.A1=org.apache.log4j.ConsoleAppender

log4j.appender.A1.layout=org.apache.log4j.PatternLayout

log4j.appender.A1.layout.ConversionPattern=%d{ABSOLUTE} %-5p

ICESOFT TECHNOLOGIES INC. www.icefaces.org

log4j.appender.A1.layout.ConversionPattern=%d{ABSOLUTE} %-5p [%c{1}:%L] %m%n

log4j.logger.training.jobapplication.lifecycle.LoggingPhaseListener=DEBUG

Step 5: Copy Log4J JAR

• Find the web/WEB-INF/lib/log4j.jar file in the solution

• Copy the log4j.jar file to the WEB-INF/lib folder of your project

ICESOFT TECHNOLOGIES INC. www.icefaces.org

Step 6: Run Application

• Re-publish/Re-deploy the jobApplication project to Tomcat

• Start Firefox and visit the following URL:– http://localhost:8080/jobApplication/applicantForm.iface

ICESOFT TECHNOLOGIES INC. www.icefaces.org

Step 6: Examine Tomcat Console Log

• Examine the Tomcat console log for PhaseListener output

• Note that only RESTORE_VIEW and RENDER_RESPONSE took place

ICESOFT TECHNOLOGIES INC. www.icefaces.org

• Type a value for the First Name field and click submit

• Examine Tomcat console log again for more phase output

JSF Form Validation

• JSF provides two ways of performing form validation:

– Individual field validation

– Interdependent field validation

• Individual field validation is accomplished in several ways:

– Adding a required attribute to a tag

– Adding a validator attribute to a tag

– Adding a validator component as a child of a tag

ICESOFT TECHNOLOGIES INC. www.icefaces.org

– Adding a validator component as a child of a tag

– The h:message component is used to show validation errors in context, next to the offending field

• Interdependent field validation is performed during actions

– The h:messages component is used to show interdependent field validation error messages

Exercise: Overview

• The goal of this exercise is to add form validation to the jobApplication project

ICESOFT TECHNOLOGIES INC. www.icefaces.org

Step 1: Add required attribute

• In order to make the First Name field be a required field for validation purposes, the required attribute needs to be set

• In the applicantForm.xhtml file, replace this:<h:inputText id="firstName" value="#{applicant.firstName}" />

• With this:<h:inputText id="firstName" required="true" value="#{applicant.firstName}" />

• When the user clicks the Submit Application button, the Process

ICESOFT TECHNOLOGIES INC. www.icefaces.org

• When the user clicks the Submit Application button, the Process Validations phase will fail and the corresponding h:message component will show the error message

– Note that the value of the for attribute of the h:message component must be the same as the id attribute of the h:inputText component,i.e.: <h:message for="firstName" />

Step 2: Add Last Name Field

• Paste the following into applicantForm.xhtml below the First Name table row:

<tr>

<td><h:outputLabel for="lastName" value="Last Name:" /></td>

<td><h:inputText id="lastName" required="true" value="#{applicant.lastName}" /></td>

<td><h:message for="lastName" /></td>

</tr>

ICESOFT TECHNOLOGIES INC. www.icefaces.org

• Add a getter/setter to the Applicant.java class for the lastName property

Step 3: Add Travel Percentage Field

• Paste the following into applicantForm.xhtml below the Last Name table row:

<tr><td><h:outputLabel for="travelPercentage" value="Travel

Percentage:" /></td><td><h:inputText id="travelPercentage" required="true"

value="#{applicant.travelPercentage}"><f:validateLongRange minimum=“0" maximum="100" />

</h:inputText></td>

ICESOFT TECHNOLOGIES INC. www.icefaces.org

<td><h:message for="travelPercentage" /></td></tr>

• Note that the f:validateLongRange component is used to constrain the value between 0 and 100

• Add a getter/setter to the Application.java class for the travelPercentage property as a String (not an Integer)

Step 4: Add Log Output

• Add the following code to the top of the ApplicantForm.submit() method:

System.out.println("submit() firstName=" + this.applicant.getFirstName());

System.out.println("submit() lastName=" + this.applicant.getLastName());

System.out.println("submit() travelPercentage=" + this.applicant.getTravelPercentage());

ICESOFT TECHNOLOGIES INC. www.icefaces.org

this.applicant.getTravelPercentage());

Step 5: Interdependent Validation

• Add the following code inside the firstName=“John” condition of the ApplicantForm.submit() method:

if (this.applicant.getLastName().equals("Doe")) {

String msg = "John Doe already works for us";

FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);

FacesContext facesContext = FacesContext.getCurrentInstance();

ICESOFT TECHNOLOGIES INC. www.icefaces.org

String clientId = null; // this is a global message

facesContext.addMessage(clientId, facesMessage);

return "retry";

}

• This will cause an interdependent field validation error when the user enters “John” as the First Name and “Doe” as the Last Name

Step 6: Add Global Messages Component

• Paste the following into applicantForm.xhtml after the h:form component:

<h:messages globalOnly="true" />

ICESOFT TECHNOLOGIES INC. www.icefaces.org

Step 7: Run Application

• Run the appication in the web browser

• Enter the following and click Submit Application:– First Name: John

– Last Name: (leave it blank)– Travel Percentage: 101

• You should see an in-line error messages to the right of the Last Name and Travel Percentage files

• Enter the following and click Submit Application:– First Name: John

– Last Name: Doe

– Travel Percentage: 50abcd

ICESOFT TECHNOLOGIES INC. www.icefaces.org

– Travel Percentage: 50abcd

• You should see an in-line error message next to the Travel Percentage field

• Enter the following and click Submit Application:– First Name: John

– Last Name: Doe

– Travel Percentage: 50

• Validation should fail with the global error message “John Doe already works for us”

• Enter a different last name

• Validation should pass

JSF Converters

• Converters exist to coerce input to model bean properties of a type other than String, and to format output of model bean properties

• Resources:– J2EE 1.4 Tutorial: Using the Standard Converters

– ICEfaces Tutorial: Using JSF converters with ICEfaces components

ICESOFT TECHNOLOGIES INC. www.icefaces.org

– ICEfaces Tutorial: Using JSF converters with ICEfaces components

– John Deringer’s Article on JSF Validators/Converters

Implicit Conversion

• JSF can implicitly convert a component’s value to a model bean property that is of a type other than String

• In the previous exercise, you may have noticed that the travelPercentage JavaBean property was a String– Note that in the next exercise, we will change the travelPercentage

to an Integer type

ICESOFT TECHNOLOGIES INC. www.icefaces.org

to an Integer type

Explicit Conversion

• If you want your markup to be more precise with respect to conversion, you can specify a explicit conversion of a component’s value

• There are two ways to specify a converter:– Using the converter attribute, for example:

<h:inputText value="#{modelBean.age}"

ICESOFT TECHNOLOGIES INC. www.icefaces.org

<h:inputText value="#{modelBean.age}" converter="javax.faces.Integer" />

– Using the f:converter component, for example:

<h:inputText value="#{modelBean.age}">

<f:converter converterId="javax.faces.Integer" />

</h:inputText>

Standard Converters

• The JSF framework comes with several standard converters

• The f:converterNumber component will convert a component’s value to a concrete subclass of java.lang.Number and has several attributes that control formatting, for example:<f:convertNumber type="currency" />

ICESOFT TECHNOLOGIES INC. www.icefaces.org

• The f:convertDateTime component exists to convert a component’s value to java.util.Date, for example:<f:convertDateTime pattern= "MM/dd/yyyy" />

• See java.text.SimpleDateFormat for a listing of date format patterns

Custom Converters

• In addition to the standard converters, JSF allows you to define your own converters, for example:<my:ssnConverter />

• Custom converters must be registered in faces-config.xml in a <converter> element, and must have a corresponding Java class that implements javax.faces.convert.Converter

ICESOFT TECHNOLOGIES INC. www.icefaces.org

Java class that implements javax.faces.convert.Converter

Exercise: Overview

• The goal of this exercise is to:– Change the data type of travelPercentage from String to Integer in

order to let implicit conversion take place

– Add a Date of Birth field and use a JSF converter to convert the input to java.util.Date

ICESOFT TECHNOLOGIES INC. www.icefaces.org

Step 1: Setup Implicit Integer-Based Conversion

• In the Applicant.java file, change the datatype of the travelPercentage field from String to Integer– The getter/setter methods have to be changed as well

ICESOFT TECHNOLOGIES INC. www.icefaces.org

Step 2: Add Date of Birth Property

• In the Applicant.java file, paste the following:

private Date dateOfBirth;

public Date getDateOfBirth() {

return dateOfBirth;

}

ICESOFT TECHNOLOGIES INC. www.icefaces.org

public void setDateOfBirth(Date dateOfBirth) {

this.dateOfBirth = dateOfBirth;

}

Step 3: Add Date of Birth Markup

• In the applicantForm.xhtml file, add the following table row below the Travel Percentage row:

<tr>

<td><h:outputLabel for="dateOfBirth" value="Date of Birth:" /></td>

<td><h:inputText id="dateOfBirth" required="true" value="#{applicant.dateOfBirth}">

<f:convertDateTime pattern="MM/dd/yyyy" />

ICESOFT TECHNOLOGIES INC. www.icefaces.org

<f:convertDateTime pattern="MM/dd/yyyy" />

</h:inputText></td>

<td><h:message for="dateOfBirth" /></td>

</tr>

Step 4: Run Application

• Re-publish/deploy the jobApplication project

• Run the application in the web browser

• Enter the following and click Submit Application:– First Name: John

– Last Name: Doe

– Travel Percentage: 50

ICESOFT TECHNOLOGIES INC. www.icefaces.org

– Travel Percentage: 50

– Date of Birth: 1/1/1970

• Notice that the Date of Birth has a leading zero, since the datePattern was specified as MM/dd/yyyy