Tuesday, 29 March 2016

JSF-4

JSF - Event Handling

JSF Event Handling

  • When a user clicks a JSF button or link or changes any value in text field, JSF UI component fires event which will be handled by the the application code.
  • To handle such event, event handler are to be registered in the application code or managed bean.
  • When a UI component checks that a user event has happened, it creates an instance of the corresponding event class and adds it to an event list.
  • Then, Component fires the event, i.e., checks the list of listeners for that event and call the event notification method on each listener or handler.
  • JSF also provide system level event handlers which can be used to do some tasks when application starts or is stopping.
Following are important Event Handler in JSF 2.0:
S.N.Event Handlers & Description
1
valueChangeListener
Value change events get fired when user make changes in input components.
2
actionListener
Action events get fired when user clicks on a button or link component.
3
Application Events
Events firing during JSF lifecycle: PostConstructApplicationEvent, PreDestroyApplicationEvent , PreRenderViewEvent.





JSF Event Listener Model Example


JSF Event and Listener model is based on the JavaBeans Specification. An event is defined as a signal triggered based upon the user actions such as click of button, hyperlink, changing the input value etc. JSF tells the component to invoke the appropriate listener class that process the event generated by the user.
Lets now look in detail about the event classes and listener interfaces.

Event Classes

The classes related to the JSF events are defined in the javax.faces.event package. While implementing the event classes in JSF, the javax.faces.event package has to be extended. The generated event can be obtained by calling event.getComponent as

1
2
3
UIComponent ui = new UIComponent();
MyFacesEvent ev1 = new MyFacesEvent(ui);
UIComponent sc1 = ev1.getComponent(); 
The events can be queued at the end of request processing lifecycle by using the queue() method. The queuing at a particular stage can be done by using the following code
1
2
MyFacesEvent ev1 = new MyFacesEvent();
ev1.setPhaseId(PhaseId.PROCESS_VALIDATIONS);
In the above code, the events will occur at the end of the process validation phase.

Listener Classes

An event is associated with the listener class for all the events. For instance, if the event is a valuechange event then the corresponding listener class ValueChangeListener is associated with it. SImilarly the ActionListener is for the action event.
JavaBeans specifications makes the methods mandatory for registering a particular listener to an event. For example if the event name is MyOwnEvent and the Listener class is MyOwnListener and want this event to be called on MyOwnComponent then the following methods have to be defined for registering the listener class.
1
2
3
4
5
public void addMyOwnComponentListener(MyOwnListener l1)
public void removeMyOwnListener(MyOwnListener l1)
public void MyOwnListener[] getMyOwnListeners()

JSF Events

The JSF events fall into one of the three categories namely
  1. Action Events
  2. Value Change Events
  3. Phase Events

Action Events

Action events are the events that are generated for the ui components like command button or command hyperlink. Any number of listeners can be attached to a single event.
Consider an example of submitting a form.
Create a JSF view page mobile.xhtml as shown below.
mobile.xhtml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?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:h="http://java.sun.com/jsf/html">
<h:head>
    <title>Text fields</title>
</h:head>
<h:body>
    <h3>Mobile details</h3>
    <h:form>
        <h:panelGrid columns="3">
            <h:outputLabel for="mname">Company Name:</h:outputLabel>
            <h:inputText id="mname"></h:inputText>
            <br />
            <br />
            <h:outputLabel for="model">Model Number:</h:outputLabel>
            <h:inputText id="model"></h:inputText>
            <br />
            <br />
            <h:outputLabel for="color">Color:</h:outputLabel>
            <h:inputText id="color"></h:inputText>
            <br />
            <br />
            <h:commandButton value="Mobile Action Listener"
                actionListener="#{mobileActionListener.processAction}" />
        </h:panelGrid>
    </h:form>
</h:body>
</html>
Here we define attribute actionListener calling the method processAction of MobileActionListener class.
Create MobileActionListener.java class as;


MobileActionListener.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.journaldev.jsf.beans;
import javax.faces.FactoryFinder;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
import javax.faces.event.PhaseListener;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
@ManagedBean
@SessionScoped
public class MobileActionListener implements ActionListener {
    public MobileActionListener() {
    }
    @Override
    public void processAction(ActionEvent ae) throws AbortProcessingException {
        UIComponent ui = ae.getComponent();
        System.out.println("Event source is" + ui.getClass().getName());
    }
    public void listAllPhaseListeners() {
        LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
                .getFactory(FactoryFinder.LIFECYCLE_FACTORY);
        Lifecycle applicationLifecycle = lifecycleFactory
                .getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
        PhaseListener phaseListeners[] = applicationLifecycle
                .getPhaseListeners();
        for (PhaseListener phaseListener : phaseListeners) {
            System.out.println(phaseListener.getPhaseId());
        }
    }
}
Here we implement the ActionListener class and override the processAction method. Inside this method we are just printing the event that is invoked by the user. The ui.getClass().getName() methods prints the action event triggered.
Make the following entry in faces-config.xml file to invoke the actionlistener class.
faces-config.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
              xmlns="http://xmlns.jcp.org/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
    <managed-bean>
        <managed-bean-name>mobileActionListener</managed-bean-name>
            <managed-bean-class>
                com.journaldev.jsf.beans.MobileActionListener
            </managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
    </managed-bean>
     
    <lifecycle>
    <phase-listener>
        com.journaldev.jsf.beans.CustomPhaseListener
    </phase-listener>
     
</lifecycle>
</faces-config>
The managed bean Mobile Action Listener class path is specified in the faces-config.xml file.
Now run the application and go to the mobile.xhtml page in browser and click the submit button which produces the following output in the console
1
Event source is javax.faces.component.html.HtmlCommandButton
Since the submit button is the event fired the event is CommandButton tag which corresponds to submit button.

Value Change Event

Value change events refers to the UI components textfield, radio button, list box etc. The value change event will get fired as soon as the value is changed in the UI component. Listeners for this event usually perform validations on the fields to check whether the entered value is valid or not according to the requirements.
Consider the following example of changing a value in a listbox and displaying the new value
Create mobilevalue.xhtml as;
mobilevalue.xhtml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?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:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">
<h:head>
    <title>Value Change Event</title>
</h:head>
<h:body>
    <h3>Value Change Event Example</h3>
    <h:form>
        <h:panelGrid columns="3">
            <h:selectOneMenu id="name" value="#{mobileValueChangeListener.name}"
                onchange="submit()"
                valueChangeListener="#{mobileValueChangeListener.onSelectNames}">
                <f:selectItem itemValue="Nokia" itemLabel="Nokia" />
                <f:selectItem itemValue="Samsung" itemLabel="Samsung" />
                <f:selectItem itemValue="Blackberry" itemLabel="Blackberry" />
                <f:selectItem itemValue="Sony" itemLabel="Sony" />
                <f:selectItem itemValue="Mi3" itemLabel="Mi3" />
            </h:selectOneMenu>
        </h:panelGrid>
    </h:form>
    <br />
    <br />
    <h:outputText value="#{mobileValueChangeListener.result}"></h:outputText>
</h:body>
</html>
Here we invoke the valueChangeListener attribute and invoke the onSelectNames method of the MobileValueChangeListener bean.
Create the MobileValueChangeListener.java bean as;
MobileValueChangeListener.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.journaldev.jsf.beans;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ValueChangeEvent;
@ManagedBean
@SessionScoped
public class MobileValueChangeListener {
    private String name;
    private String result;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getResult() {
        return result;
    }
    public void setResult(String result) {
        this.result = result;
    }
    public MobileValueChangeListener() {
    }
    public void onSelectNames(ValueChangeEvent vc) {
        Object oval = vc.getOldValue();
        Object nval = vc.getNewValue();
        System.out.println("oval" + oval);
        System.out.println("nval" + nval);
        if (nval != null) {
            result = "Newly changed value is:" + (String) nval;
        }
    }
}
In the onSelectNames method we obtain the new value and old value through the getOldValue and getNewValue methods and check if the new value is not equal null and if true store the new value to the result variable and display the value of this variable on the JSF view page.
Now run the application that produces the following output on changing the value in the listbox.
JSF-Event-Listener-Example

Phase Event

This type of event involves the events to be fired in one of the six phases of JSF lifecycle either during start or towards the end of each phase.
Consider an example of capturing the phase events by creating CustomPhaseListener.java as;
CustomPhaseListener.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.journaldev.jsf.beans;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
public class CustomPhaseListener implements PhaseListener {
    private static final long serialVersionUID = -1395570878923714114L;
    @Override
    public void afterPhase(PhaseEvent pe) {
        System.out.println("After phase" + pe.getPhaseId());
    }
    @Override
    public void beforePhase(PhaseEvent pe) {
        System.out.println("Before phase" + pe.getPhaseId());
    }
    @Override
    public PhaseId getPhaseId() {
        return PhaseId.ANY_PHASE;
    }
}
Create a JSF view page phaseListener.xhtml as;
phaseListener.xhtml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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="mname" />
        <h:commandButton id="button" value="Submit" />
        <h:messages />
    </h:form>
</h:body>
</html>
Now run the application and enter some text on phaseListener page and click the submit button. Check the server logs and following output is produced.
1
2
3
4
5
6
7
8
9
10
11
12
Before phase RESTORE_VIEW 1
After phase RESTORE_VIEW 1
Before phase APPLY_REQUEST_VALUES 2
After phase APPLY_REQUEST_VALUES 2
Before phase PROCESS_VALIDATIONS 3
After phase PROCESS_VALIDATIONS 3
Before phase UPDATE_MODEL_VALUES 4
After phase UPDATE_MODEL_VALUES 4
Before phase INVOKE_APPLICATION 5
After phase INVOKE_APPLICATION 5
Before phase RENDER_RESPONSE 6
After phase RENDER_RESPONSE 6
The event id’s for each phase is printed in the console.
Finally below image shows the project structure.
JSF-Event-Listener-Project
You can download the final project from below link and play around with it to learn more about JSF Event and Listeners.

 

1 comment: