`
acrbb
  • 浏览: 11691 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

JSF 生命周期 - JSF Liefcycle (1)

阅读更多

ZZ.



Listen and debug JSF lifecycle phases
The JSF lifecycle will be explained and debugged here using the "poor man's debugging" approach with sysout's. We'll also check what happens if you add immediate="true" to the UIInput and UICommand and what happens when a ConverterException and ValidatorException will be thrown.

Well, you probably already know that the JSF lifecycle contains 6 phases:

  • 1.Restore view
  • 2.Apply request values
  • 3.Process validations
  • 4.Update model values
  • 5.Invoke application
  • 6.Render response


You can use a PhaseListener to trace the phases of the JSF lifecycle and execute some processes where required. But you can also use a "dummy" PhaseListener to debug the phases to see what is happening in which phase. Here is a basic example of such a LifeCycleListener:

Note: if you don't have a JSF playground environment setup yet, then you may find this tutorial useful as well: JSF tutorial with Eclipse and Tomcat.

package mypackage;

import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;

public class LifeCycleListener implements PhaseListener {

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

    public void beforePhase(PhaseEvent event) {
        System.out.println("START PHASE " + event.getPhaseId());
    }

    public void afterPhase(PhaseEvent event) {
        System.out.println("END PHASE " + event.getPhaseId());
    }

}

 

Add the following lines to the faces-config.xml to activate the LifeCycleListener.

<lifecycle>
    <phase-listener>mypackage.LifeCycleListener</phase-listener>
</lifecycle>

 

This produces like the following in the system output:


START PHASE RESTORE_VIEW 1
END PHASE RESTORE_VIEW 1
START PHASE APPLY_REQUEST_VALUES 2
END PHASE APPLY_REQUEST_VALUES 2
START PHASE PROCESS_VALIDATIONS 3
END PHASE PROCESS_VALIDATIONS 3
START PHASE UPDATE_MODEL_VALUES 4
END PHASE UPDATE_MODEL_VALUES 4
START PHASE INVOKE_APPLICATION 5
END PHASE INVOKE_APPLICATION 5
START PHASE RENDER_RESPONSE 6
END PHASE RENDER_RESPONSE 6

 

Basic debug example

To trace all phases of the JSF lifecycle, here is some sample code which represents simple JSF form with a "dummy" converter and validator and the appropriate backing bean. The code sample can be used to give us more insights into the phases of the JSF lifecycle, to understand it and to learn about it.

The minimal contents of the test JSF file: test.jsp

 

<%@taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@taglib uri="http://java.sun.com/jsf/html" prefix="h" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<f:view>
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
            <title>Debug JSF lifecycle</title>
        </head>
        <body>
            <h:form>
                <h:inputText
                    binding="#{myBean.inputComponent}"
                    value="#{myBean.inputValue}"
                    valueChangeListener="#{myBean.inputChanged}">
                    <f:converter converterId="myConverter" />
                    <f:validator validatorId="myValidator" />
                </h:inputText>
                <h:commandButton
                    value="submit"
                    action="#{myBean.action}" />
                <h:outputText
                    binding="#{myBean.outputComponent}"
                    value="#{myBean.outputValue}" />
                <h:messages />
            </h:form>
        </body>
    </html>
</f:view>

 

The dummy converter: MyConverter.java

package mypackage;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

public class MyValidator implements Validator {

    public void validate(FacesContext context, UIComponent component, Object value)
        throws ValidatorException
    {
        System.out.println("MyValidator validate: " + value);
    }

}


package mypackage;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

public class MyValidator implements Validator {

    public void validate(FacesContext context, UIComponent component, Object value)
        throws ValidatorException
    {
        System.out.println("MyValidator validate: " + value);
    }

}


package mypackage;

import javax.faces.component.html.HtmlInputText;
import javax.faces.component.html.HtmlOutputText;
import javax.faces.event.ValueChangeEvent;

public class MyBean {

    // Init ----------------------------------------------------------------------------------------

    private HtmlInputText inputComponent;
    private String inputValue;
    private HtmlOutputText outputComponent;
    private String outputValue;

    // Constructors -------------------------------------------------------------------------------

    public MyBean() {
        log("constructed");
    }

    // Actions ------------------------------------------------------------------------------------

    public void action() {
        outputValue = inputValue;
        log("succes");
    }

    // Getters ------------------------------------------------------------------------------------

    public HtmlInputText getInputComponent() {
        log(inputComponent);
        return inputComponent;
    }

    public String getInputValue() {
        log(inputValue);
        return inputValue;
    }

    public HtmlOutputText getOutputComponent() {
        log(outputComponent);
        return outputComponent;
    }

    public String getOutputValue() {
        log(outputValue);
        return outputValue;
    }

    // Setters ------------------------------------------------------------------------------------

    public void setInputComponent(HtmlInputText inputComponent) {
        log(inputComponent);
        this.inputComponent = inputComponent;
    }

    public void setInputValue(String inputValue) {
        log(inputValue);
        this.inputValue = inputValue;
    }

    public void setOutputComponent(HtmlOutputText outputComponent) {
        log(outputComponent);
        this.outputComponent = outputComponent;
    }

    // Listeners ----------------------------------------------------------------------------------

    public void inputChanged(ValueChangeEvent event) {
        log(event.getOldValue() + " to " + event.getNewValue());
    }

    // Helpers ------------------------------------------------------------------------------------

    private void log(Object object) {
        String methodName = Thread.currentThread().getStackTrace()[2].getMethodName();
        System.out.println("MyBean " + methodName + ": " + object);
    }
}

 

The minimal faces configuration: faces-config.xml

 

 

 

<converter>
    <converter-id>myConverter</converter-id>
    <converter-class>mypackage.MyConverter</converter-class>
</converter>
<validator>
    <validator-id>myValidator</validator-id>
    <validator-class>mypackage.MyValidator</validator-class>
</validator>
<managed-bean>
    <managed-bean-name>myBean</managed-bean-name>
    <managed-bean-class>mypackage.MyBean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
</managed-bean>

 

The first call

The first call in a freshly started webapplication with a fresh session should output at least:

START PHASE RESTORE_VIEW 1
END PHASE RESTORE_VIEW 1
START PHASE RENDER_RESPONSE 6
MyBean <init>: constructed
MyBean getInputComponent: null
MyBean setInputComponent: javax.faces.component.html.HtmlInputText@2a9fca57
MyBean getInputValue: null
MyBean getOutputComponent: null
MyBean setOutputComponent: javax.faces.component.html.HtmlOutputText@13bbca56
MyBean getOutputValue: null
END PHASE RENDER_RESPONSE 6

1. Restore view.
As the session is fresh, there's no means of any UIViewRoot to restore, so nothing to see here.

2. Apply request values.
This phase is skipped because there is no form submit.

3. Process validations.
This phase is skipped because there is no form submit.

4. Update model values.
This phase is skipped because there is no form submit.

5. Invoke application.
This phase is skipped because there is no form submit.

6. Render response.
The bean is constructed. Behind the scenes a new UIViewRoot is created and stored in the session. If the component binding getters returns precreated components (precreated in e.g. the constructor) and not null, then those will be used, otherwise JSF will create new components. The components will be stored in the UIViewRoot and the bounded components are set in the component bindings. The values to be shown are retrieved from the value binding getters in the backing bean. If the values aren't set yet, they defaults to null. The component bindings are not required by the way. Only use them if you actually need the component in the backing bean for other means than getting/setting the value. In this article they are included just to demonstrate what all happens in the lifecycle.

The form submit

The form submit with the value "test" entered should output at least:

START PHASE RESTORE_VIEW 1
MyBean <init>: constructed
MyBean setInputComponent: javax.faces.component.html.HtmlInputText@2a9fca57
MyBean setOutputComponent: javax.faces.component.html.HtmlOutputText@13bbca56
END PHASE RESTORE_VIEW 1
START PHASE APPLY_REQUEST_VALUES 2
END PHASE APPLY_REQUEST_VALUES 2
START PHASE PROCESS_VALIDATIONS 3
MyConverter getAsObject: test
MyValidator validate: test
MyBean getInputValue: null
MyBean inputChanged: null to test
END PHASE PROCESS_VALIDATIONS 3
START PHASE UPDATE_MODEL_VALUES 4
MyBean setInputValue: test
END PHASE UPDATE_MODEL_VALUES 4
START PHASE INVOKE_APPLICATION 5
MyBean action: succes
END PHASE INVOKE_APPLICATION 5
START PHASE RENDER_RESPONSE 6
MyBean getInputValue: test
MyConverter getAsString: test
MyBean getOutputValue: test
END PHASE RENDER_RESPONSE 6

1. Restore view.
The bean is constructed. The UIViewRoot is restored from session and the bounded components are set in the component bindings.

2. Apply request values.
Nothing to see here. Behind the scenes the submitted form values are obtained as request parameters and set in the relevant components in the UIViewRoot , for example inputComponent.setSubmittedValue("test" ) .

3. Process validations.
The submitted values are passed through the converter getAsObject() method and validated by the validator. If the conversion and validation succeeds, then the initial input value will be retrieved from the value binding getter and behind the scenes the inputComponent.setValue(submittedValue) and inputComponent.setSubmittedValue(null ) will be executed. If the retrieved initial input value differs from the submitted value, then the valueChangeListener method will be invoked.

4. Update model values.
The converted and validated values will now be set in the value binding setters of the backing bean. E.g. myBean.setInputValue(inputComponent.getValue()) .

5. Invoke application.
The real processing of the form submission happens here.

6. Render response.
The values to be shown are retrieved from the value binding getters in the backing bean. If a converter is definied, then the value will be passed through the converter getAsString() method and the result will be shown in the form.

Back to top

Add immediate="true" to UIInput only

Extend the h:inputText in the test.jsp with immediate="true" :

 

 

 ...
    <h:inputText
        binding="#{myBean.inputComponent}"
        value="#{myBean.inputValue}"
        valueChangeListener="#{myBean.inputChanged}"
        immediate="true">
    ...
 

The form submit with the value "test" entered should output at least:

START PHASE RESTORE_VIEW 1
MyBean <init>: constructed
MyBean setInputComponent: javax.faces.component.html.HtmlInputText@2a9fca57
MyBean setOutputComponent: javax.faces.component.html.HtmlOutputText@13bbca56
END PHASE RESTORE_VIEW 1
START PHASE APPLY_REQUEST_VALUES 2
MyConverter getAsObject: test
MyValidator validate: test
MyBean getInputValue: null
MyBean inputChanged: null to test
END PHASE APPLY_REQUEST_VALUES 2
START PHASE PROCESS_VALIDATIONS 3
END PHASE PROCESS_VALIDATIONS 3
START PHASE UPDATE_MODEL_VALUES 4
MyBean setInputValue: test
END PHASE UPDATE_MODEL_VALUES 4
START PHASE INVOKE_APPLICATION 5
MyBean action: succes
END PHASE INVOKE_APPLICATION 5
START PHASE RENDER_RESPONSE 6
MyBean getInputValue: test
MyConverter getAsString: test
MyBean getOutputValue: test
END PHASE RENDER_RESPONSE 6

 

 

1. Restore view.
The bean is constructed. The UIViewRoot is restored from session and the bounded components are set in the component bindings.

2. Apply request values.
Behind the scenes the submitted form values are obtained as request parameters and set in the relevant components in the UIViewRoot , for example inputComponent.setSubmittedValue("test" ) . The submitted values are immediately passed through the converter getAsObject() method and validated by the validator. If the conversion and validation succeeds, then the initial input value will be retrieved from the value binding getter and behind the scenes the inputComponent.setValue(submittedValue) and inputComponent.setSubmittedValue(null ) will be executed. If the retrieved initial input value differs from the submitted value, then the valueChangeListener method will be invoked. This all happens in this phase instead of the Process validations phase due to the immediate="true" in the h:inputText .

3. Process validations.
Nothing to see here. The conversion and validation is already processed in the Apply request values phase, before the values being put in the components. This is due to the immediate="true" in the h:inputText .

4. Update model values.
The converted and validated values will now be set in the value binding setters of the backing bean. E.g. myBean.setInputValue(inputComponent.getValue()) .

5. Invoke application.
The real processing of the form submission happens here.

6. Render response.
The values to be shown are retrieved from the value binding getters in the backing bean. If a converter is definied, then the value will be passed through the converter getAsString() method and the result will be shown in the form.

Note for other components without immediate : any other UIInput components inside the same form which don't have immediate="true" set will just continue the lifecycle as usual .

 

 

Add immediate="true" to UIInput only

1. Restore view.
The bean is constructed. The UIViewRoot is restored from session and the bounded components are set in the component bindings.

 

2. Apply request values.
Behind the scenes the submitted form values are obtained as request parameters and set in the relevant components in the UIViewRoot , for example inputComponent.setSubmittedValue("test" ) . The submitted values are immediately passed through the converter getAsObject() method and validated by the validator. If the conversion and validation succeeds, then the initial input value will be retrieved from the value binding getter and behind the scenes the inputComponent.setValue(submittedValue) and inputComponent.setSubmittedValue(null ) will be executed. If the retrieved initial input value differs from the submitted value, then the valueChangeListener method will be invoked. This all happens in this phase instead of the Process validations phase due to the immediate="true" in the h:inputText .

 

验证与转化提到第二阶段,inputComponent.setValue(submittedValue) and inputComponent.setSubmittedValue(null ) 会被执行!

 

3. Process validations.
Nothing to see here. The conversion and validation is already processed in the Apply request values phase, before the values being put in the components. This is due to the immediate="true" in the h:inputText .

4. Update model values.
The converted and validated values will now be set in the value binding setters of the backing bean. E.g. myBean.setInputValue(inputComponent.getValue()) .

5. Invoke application.
The real processing of the form submission happens here.

6. Render response.
The values to be shown are retrieved from the value binding getters in the backing bean. If a converter is definied, then the value will be passed through the converter getAsString() method and the result will be shown in the form.

Note for other components without immediate : any other UIInput components inside the same form which don't have immediate="true" set will just continue the lifecycle as usual .

 

 

 

Add immediate="true" to UICommand only

 ...
    <h:commandButton
        value="submit"
        action="#{myBean.action}"
        immediate="true" />
    ...
 

The form submit with the value "test" entered should output at least:

START PHASE RESTORE_VIEW 1
MyBean <init>: constructed
MyBean setInputComponent: javax.faces.component.html.HtmlInputText@2a9fca57
MyBean setOutputComponent: javax.faces.component.html.HtmlOutputText@13bbca56
END PHASE RESTORE_VIEW 1
START PHASE APPLY_REQUEST_VALUES 2
MyBean action: succes
END PHASE APPLY_REQUEST_VALUES 2
START PHASE RENDER_RESPONSE 6
MyBean getOutputValue: null
END PHASE RENDER_RESPONSE 6

1. Restore view.
The bean is constructed. The UIViewRoot is restored from session and the bounded components are set in the component bindings.

2. Apply request values.
The real processing of the form submission happens here. This happens in this phase instead of the Invoke application phase due to the immediate="true" in the h:commandButton . The UIInput components which don't have immediate="true" set will not be converted, validated nor updated, but behind the scenes the inputComponent.setSubmittedValue(submittedValue) will be executed before the action() method will be executed.

Action 会在这个阶段执行!

3. Process validations.
This phase is skipped due to the immediate="true" in the h:commandButton .

4. Update model values.
This phase is skipped due to the immediate="true" in the h:commandButton .

5. Invoke application.
This phase is skipped due to the immediate="true" in the h:commandButton .

6. Render response.
The values to be shown are retrieved from the value binding getters in the backing bean, expect for the UIInput components which don't have immediate="true" set. Behind the scenes those will be retrieved from the components in the UIViewRoot, e.g. inputComponent.getSubmittedValue() .

输入 <h:inputText,的值是从inputComponent.getSubmittedValue()得到的。可以在action中去改它,变成一个新value.那UI显示就会成updated后的值,如!

 public void action() {
    	String temp = (String)inputComponent.getSubmittedValue();
    	System.out.println(" --> Action getSubmittedValue: "+temp);
    	inputComponent.setSubmittedValue(temp+" _updated");
    	temp = (String)inputComponent.getValue();
    	System.out.println(" --> Action getValue: "+temp);
    	
        outputValue = inputValue;
        log("succes");
    }

 那在UI 上就成了:aaaaa _updated...

 

Note for all components without immediate : as the Update model values phase is skipped, the value bindings aren't been set and the value binding getters will return null. But the values are still available as submitted value of the relevant components in the UIViewRoot . In this case you can retrieve the non-converted and non-validated input value from inputComponent.getSubmittedValue() in the action() method. You could even change it using inputComponent.setSubmittedValue(newValue) in the action() method.

 

 

分享到:
评论

相关推荐

    jsf-api-2.0.3.jar.zip_jsf api_jsf jar包_jsf-api-2.0.3.jar_jsf-api

    3. **Managed Beans**:作为业务逻辑的容器,提供了一种简化的方法来管理bean对象,包括依赖注入(DI)和生命周期管理。 4. **Faces Flow**:提供了一种新的方式来组织和导航复杂的UI流程,使得多个视图之间的转换...

    JSF生命周期总结JSF生命周期总结

    JSF生命周期总结JSF生命周期总结JSF生命周期总结JSF生命周期总结JSF生命周期总结JSF生命周期总结

    JSF-AV-rules.rar_JSF AV rule_JSF-AV_JSF-AV-rules_航空C++编程规范

    《JSF-AV-rules.rar》是一个压缩包文件,包含了航空C++编程规范,这个规范主要针对的是在航空系统开发中使用C++编程时应当遵循的一系列规则和标准。航空系统的软件开发对于安全性、可靠性和可维护性有着极高的要求,...

    jboss-ajax4jsf-1.1.1-src

    【标题】"jboss-ajax4jsf-1.1.1-src" 是一个开源项目,主要涉及Ajax4jsf框架的源代码版本,版本号为1.1.1。Ajax4jsf是针对JavaServer Faces (JSF) 技术的一个扩展,它允许开发者在JSF应用中无缝集成Ajax功能,提升...

    jsf-api-2.0.jar

    这是jsf-api-2.0.jar,为了使用方便传上来.只是个jar包.

    参考合同-集体林权流转合同(JSF-2015-2602).zip

    《集体林权流转合同》(JSF-2015-2602)是针对我国农村集体林地使用权和林木所有权转移的一种规范性法律文件。这份文档,以.docx格式存储在压缩包内,旨在为涉及集体林权交易的各方提供一个标准化的合同模板,确保...

    JSF 生命周期 实例详解

    在深入理解JSF请求处理生命周期之前,我们先要明白JSF的核心目标是简化Web开发,尤其是处理用户输入和更新服务器端状态的过程。生命周期的概念在JSF中扮演着至关重要的角色,因为它自动化了许多传统Web技术中需要...

    jsf-api-1.2

    综上所述,"jsf-api-1.2"提供了丰富的API和功能,使开发者能够高效地构建和维护企业级的Java Web应用程序。通过对组件、事件、Managed Beans、视图状态、转换验证、导航、国际化以及错误处理的理解和熟练运用,...

    jsf-api,jsf-impl,jst1-1.2,javaee

    "jsf-api" JAR文件包含了JSF框架的公共接口和类,定义了各种组件、事件和生命周期方法,供开发者在代码中引用。而"jsf-impl" JAR文件则提供了这些API的具体实现,包括渲染器、生命周期管理器等,使得开发者可以直接...

    jsf-spring-4.0.3

    3. **FacesContext与ApplicationContext**:在JSF中获取Spring的ApplicationContext,以便于在JSF的生命周期中使用Spring服务。 4. **安全整合**:如Spring Security可以与JSF集成,提供用户认证和授权功能。 5. **...

    jsf-impl-2.0.0-src.jar

    jsf-impl-2.0.0源代码文件, jsf-impl-2.0.0-SNAPSHOT-sources.jar

    一个简单的jsf例子------JSF2学习笔记1

    - `jsf-impl.jar` 和 `jsf-api.jar` 包含了JSF2的核心实现和API,供应用程序使用。 - `commons-collections-3.1.jar` 提供了集合操作的扩展,常常用于辅助处理数据。 - `commons-beanutils-1.8.0.jar` 提供了对...

    jsf-spring-boot-starter-2.2.6.zip

    【标题】"jsf-spring-boot-starter-2.2.6.zip" 是一个基于Java Server Faces (JSF) 和Spring Boot的启动器项目,版本为2.2.6。这个压缩包通常包含了用于快速搭建JSF应用在Spring Boot环境中的必要组件和配置。 ...

    jsf-impl-1.2_15.jar

    这是jsf-impl-1.2_15.jar,为了使用方便传上来.只是个jar包.

    JSF资源---精心收集,奉献给大家

    1. **JSF基础**:JSF的基本概念,如UI组件、生命周期、渲染树和事件处理。这些组件是预定义的可重用HTML元素,例如按钮、文本输入框等,它们简化了HTML标记的编写。 2. **JSF架构**:JSF的工作原理,包括视图、控制...

    jsf-api-src.zip

    `jsf-api-src.zip`是一个压缩包,包含了JSF API的源代码,这对于开发者深入理解JSF的工作原理、调试和自定义组件非常有帮助。 在这个源码包中,`jsf127src`很可能代表JSF 1.2或2.7版本的源代码。JSF 1.2是JSF的第一...

    JSF-Java-jar包

    1. **jsf-api.jar**: `jsf-api.jar`包含了JSF框架的核心API,开发者可以使用这些API来创建JSF组件、定义事件处理、管理bean属性等。这个库提供了JSF的核心接口和抽象类,包括但不限于: - `javax.faces....

    jsf-by-example-源码.rar

    在这个名为"jsf-by-example-源码"的压缩包中,我们很可能会找到一系列关于JSF应用开发的示例代码。 **1. JSF框架概述** JSF遵循MVC(Model-View-Controller)设计模式,提供了一种声明式的方式来管理Web界面的生命...

    JSF-api-1.2_14-sources.jar

    JSF-api-1.2_14-sources.jar,提供了jsf使用时的多种内部类。

    jsf1.2 source code

    `jsf-ri`包含了JSF生命周期的执行逻辑,包括渲染、事件处理、数据绑定等关键流程。通过研究`jsf-ri`的源码,开发者可以了解JSF如何处理请求、更新模型、调用生命周期方法,以及如何处理视图状态。 ### 3. `jsf-...

Global site tag (gtag.js) - Google Analytics