Pages

Friday, February 21, 2014

Understanding JSF Lifecycle:

ADF lifecycle is developed on top of JSF life cycle. Any JSF page is a run time  representation of a Tree which has child components (components can be input components, display components or action components). Once the user request got initialized the JSF page request life cycle begins and the eventual result of the cycle will be a component tree that has to be shown for the initialized request.  Here are the phases.
  • Restore View: If the tree is already available for the user request, then skip to Render Response phase and return the tree to page by resuming its state. Otherwise request a view for creating a tree.
  • Apply Request Values: Components of the tree extracts values from the page and stores them locally. If any of the components has immediate property set to true, validators (type conversion, required and format validation) are processed for those components. For other components validators are processed during process Validation Phase
  • Process Validations:  Process validations in the following order (type conversion, required check and format validation) for all the components. If validation fails for any of the components jump to Render Response phase only after processing validations for all the components. Otherwise go to Update Model Values phase. 
  • Update Model Values: The phase where the values are updated to model. The binding values or EL expression values gets updated here.
  • Invoke Application: Executes actionListeners and actions and performs business logic for preparing the component tree.                                                                                                                                    
  • Render Response: The component tree is returned. State of the view is saved for Restore View phase.

JSF Life Cycle Demo: Download the work space from here.

Using beforePhase and afterPhase methods of the ADF page is not always a good approach as the methods will be executed in every phase. It should be used with limitations. But to understand the lifecycle let’s use these methods to see what happens before and after every phase. In the following application we should notice that the components don’t have any immediate, autosubmit or required values set to true(Immediate and required attributes will be explained in the next post). It is just a basic form with save button. The inputText  component at the bottom with label “TEST STRING FROM BEAN” value is mapped to “testStringValue” in bean and the binding value of the inputtextbox in bean is “textbox”. The values of the  “testStringValue” and “textbox” component value is also printed in beforePhase and afterPhase methods for careful observation. We are not saving the value of inputText  component with label “TEST STRING FROM BEAN” in the table. We are using this to show when the component and its actual model value will get updated. Here are the steps.



Step 1.  Run index.jspx
Step 2:  Enter values in the form.



Step 3: Enter value for “TEST STRING FROM BEAN” and Click Save button.

Output: 



Understanding from the above output: 

1.The value of the EL expression, Component value and the string value itself are null in Apply Request Values phase. 
2.Validators and ValueChangeListeners are executed during Process Validations phase(Validator method got executed first and then valueChangeListener got executed). 
3. After Process Validation phase the component value printed is not null any more but still the EL expression value and string value is null as the values are not submitted to model. 
4.After the phase Update Model Values the values are submitted to model and hence EL expression and string value are not null any more.
5. ActionListener and Action methods of the button are executed during Invoke Application phase. (ActionListener got executed first and then Action method got executed). Business logic is performed here.
6. Hence during the time of RenderResponse phase, you can see the values printed for the EL Expression, Component value and string value are same as it is saved in the application state. Here we are not showing a response to the user, how ever you can create a string and display it to the user. For Instance "Record Saved Succesfully."


Bean Code: 

public class LifeCycleDemoBean {
    
    private String testStringValue= null;
    private RichInputText textBox;
    
    public LifeCycleDemoBean() {
    }

  
    
    public String saveAction() {
        
        System.out.println(" Executed saveAction() in "+FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get("oracle.adfinternal.view.faces.lifecycle.CURRENT_PHASE_ID"));
        BindingContext bindingContext = BindingContext.getCurrent();
        BindingContainer bindings = bindingContext.getCurrentBindingsEntry();
        OperationBinding method =  bindings.getOperationBinding("Commit");
        method.execute();
        return null;
    }

    public void saveActionListener(ActionEvent actionEvent) {
       
        System.out.println(" Executed saveActionListener() in "+FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get("oracle.adfinternal.view.faces.lifecycle.CURRENT_PHASE_ID"));
        System.out.println(" Executed saveActionListener(), Last Name #{bindings.LastName.inputValue} Expression value:"+evaluateEL("#{bindings.LastName.inputValue}"));
    }

    public void lastNameChangeListener(ValueChangeEvent valueChangeEvent) {
      
        System.out.println(" Executed lastNameChangeListener() in "+FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get("oracle.adfinternal.view.faces.lifecycle.CURRENT_PHASE_ID"));
        
    }

    public void lastNameValidator(FacesContext facesContext,
                                  UIComponent uIComponent, Object object) {
        
        System.out.println(" Executed lastNameValidator() in "+FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get("oracle.adfinternal.view.faces.lifecycle.CURRENT_PHASE_ID"));
        
    }

    public void beforePhaseListener(PhaseEvent phaseEvent) {
            System.out.println(" Before Phase:"+phaseEvent.getPhaseId()+" Last Name #{bindings.LastName.inputValue} Expression value:"+evaluateEL("#{bindings.LastName.inputValue}"));
            if(this.getTextBox()!=null)
            System.out.println(" Component Value of Test String:"+this.getTextBox().getValue());
            else
            System.out.println(" Component Value of Test String:"+null);   
            System.out.println(" Value of the actual Test String:"+testStringValue);
    }

    public void afterPhaseListener(PhaseEvent phaseEvent) {
       System.out.println(" After Phase:"+phaseEvent.getPhaseId()+" Last Name #{bindings.LastName.inputValue} Expression value:"+evaluateEL("#{bindings.LastName.inputValue}"));
        if(this.getTextBox()!=null)
        System.out.println(" Component Value of Test String:"+this.getTextBox().getValue());
        else
        System.out.println(" Component Value of Test String:"+null); 
        System.out.println(" Value of the actual Test String:"+testStringValue);
        System.out.println();
    }
    
     public static Object evaluateEL(String el){
     FacesContext facesContext = FacesContext.getCurrentInstance();
     ELContext elCtx = facesContext.getELContext();
     ExpressionFactory expFactory =facesContext.getApplication().getExpressionFactory();
     ValueExpression valExp =expFactory.createValueExpression(elCtx, el, Object.class);
     return valExp.getValue(elCtx);
     }


    public void setTestStringValue(String testStringValue) {
        this.testStringValue = testStringValue;
    }

    public String getTestStringValue() {
        return testStringValue;
    }

    public void setTextBox(RichInputText textBox) {
        this.textBox = textBox;
    }

    public RichInputText getTextBox() {
        return textBox;
    }
}

No comments:

Post a Comment