JSF PhaseListener – Modifying view components example

In this post we show the JSF PhaseListener concept. During a request processing in JSF, the request that is being processed is taken through a number of phase. The phases are as follows, in the order of execution:

  • RESTORE_VIEW
  • APPLY_REQUEST_VALUES
  • PROCESS_VALIDATIONS
  • UPDATE_MODEL_VALUES
  • INVOKE_APPLICATION
  • RENDER_RESPONSE

You can attach a phase listener to each of the phases. You can modify request data as well as the view that is rendered. In our example we are we are going to disable or hide an InputText component present in the view. When you type in the “hide me!” text and send it to the application, our PhaseListener is going to set set the rendered attribute of the component to false.

When you type in the “disable me!” text then the InputText component is going to be disabled.

JSF2 - PhaseListener - disabling and hiding InputText component

JSF2 – PhaseListener – disabling and hiding InputText component

Our project structure is shown below. We are using the Eclipse IDE and the Maven plugin. If you want to learn more on how to configure the development environment please follow our tutorials – Maven 3 installation and configuration and Maven 3 Eclipse plugin setup.

Project generation procedure can be found here – Creating Maven 3 WebApp project.

JSF2 - PhaseListener - Eclipse project structure

JSF2 – PhaseListener – Eclipse project structure

FieldDisableListener.java

This class implements the PhaseListener interface. This code is executed before the RENDER_RESPONSE phase. In the beforePhase method the view tree is being processed recursively down. When the InputText component is found, which is done by checking processed component’s IDs ("dummy-text-id" is the value that we are looking for), then the value entered is checked. If the text value matches "hide me!" or "disable me!", then the component is modified – it is being hidden or disabled.

package com.itcuties.listeners;

import javax.faces.component.UIComponent;
import javax.faces.component.html.HtmlInputText;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;

/**
 * This listener disables a text field with a given ID when it contains a specific text.
 * @author itcuties
 */
public class FieldDisableListener implements PhaseListener {

	private static final long serialVersionUID = -7607159318721947672L;

	// The phase where the listener is going to be called
	private PhaseId phaseId = PhaseId.RENDER_RESPONSE;

	/**
	 * Recursively walk through the view tree, 
	 */
	public void beforePhase(PhaseEvent event) {
		processViewTree(event.getFacesContext().getViewRoot());	
	}
	
	public void afterPhase(PhaseEvent event) {
		// Do nothing here	
	}

	public PhaseId getPhaseId() {
		return phaseId;
	}
	
	private void processViewTree(UIComponent component) {
		// Go to every child
		for (UIComponent child: component.getChildren()) {
			// Display component ID and its type
			System.out.println("+ " + child.getId() + " ["+child.getClass()+"]");
			
			// If component has a given ID then check if you can hide it
			if ("dummy-text-id".equals(child.getId())) {
				// Get the input text
				HtmlInputText inputText		= (HtmlInputText)child;
				// Get input text value
				String  inputTextValue 	= (String)inputText.getValue();
				
				// Hide the field when its value match the "hide me!" string
				if ("hide me!".equals(inputTextValue))
					inputText.setRendered(false);
				
				// Disable the field
				if ("disable me!".equals(inputTextValue))
					inputText.setReadonly(true);
			
			}
			
			// Process next node
			processViewTree(child);
		}
	}
	
}

index.xhtml

This is our sample application view. "dummy-text-id" InputText is present here.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"      
      xmlns:h="http://java.sun.com/jsf/html">
 
    <h:head>
        <title>Phase Listener example</title>
    </h:head>
    <h:body>
    	<h3>Phase Listener example</h3>
    	<h:form>
    	   <h:inputText id="dummy-text-id"/>
    	   
    	   <h:commandButton id="button" value="Submit" />
    	   
    	   <h:messages />
    	   
    	</h:form>
    </h:body>
</html>

faces-config.xml

To use the PhaseListener you need to configure it in the faces-config.xmlfile. Use tag for it. When you configure multiple listeners then the order of them to execute is the same as configured here.

<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 

http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd"

	version="2.1">
 
	<lifecycle>
  		<phase-listener>com.itcuties.listeners.FieldDisableListener</phase-listener>
  	</lifecycle>
 
</faces-config>

web.xml

Here we enable the JSF2 framework in our application.

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
	<display-name>JSF 2 Phase listener example</display-name>
	<!-- The welcome page -->
	<welcome-file-list>
		<welcome-file>index.xhtml</welcome-file>
	</welcome-file-list>

	<!-- Start JSF -->
	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<!-- JSF URL mapping -->
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.xhtml</url-pattern>
	</servlet-mapping>
</web-app>

pom.xml

Here is the project’s maven configuration.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.itcuties.examples.webapps</groupId>
	<artifactId>jsf2-phase-listener-example</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>jsf2-phase-listener-example Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<!-- JSF 2 API -->
		<dependency>
			<groupId>com.sun.faces</groupId>
			<artifactId>jsf-api</artifactId>
			<version>2.2.0-m07</version>
			<scope>provided</scope>
		</dependency>
		<!-- JSF 2 Implementation -->
		<dependency>
			<groupId>com.sun.faces</groupId>
			<artifactId>jsf-impl</artifactId>
			<version>2.2.0-m07</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>
	<build>
		<finalName>listener</finalName>
	</build>
</project>

Running the application

To build this code you need to call the mvn package command. As a result the listener.war package gets created in the target directory of your project. Deploy the WAR package on the application server. The application server you are deploying your application to, has to have a JSF implementation in it’s classpath. Using JBoss, WebLogic, WebSphere, Glassfish or any other application platform that comes bundled with the JSF 2 implementation is recommended.

Download this sample code here.

This code is available on our GitHub repository as well.

2 Responses to "JSF PhaseListener – Modifying view components example"

  1. Mehran says:

    Hi
    thank for your useful post
    I have a question! i need to manipulate state of component on before my page rendered for first request!
    in other word I try to implement a phase listener that help me to secure my webpage and disable / enable or set rendered value based on user role and let sys admin change user permission on run time
    but i for first http request , phase listener dose not affect on page rendering!!!?

    Reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Java by Example App is available at Google Play Store NOW