Home Classroom ICEfaces ICEfaces – Part 4

ICEfaces – Part 4

1268

In my last article I explained what is Ajax Push and showed you how to use the SessionRenderer API.

This article will show you how to change the code to use RenderManager API in sample chat application explained in the last article.

Also please note that the ICEfaces 1.8.2 was released on 30th September 2009 and there is a new Eclipse update site: http://www.icefaces.org/eclipse-updates/

Introduction to RenderManager API

The RenderManager API is an advanced API, which supports more functionality over SessionRenderer API.

Following table shows a comparison of two APIs.

Table 1: Comparison of SessionRenderer and RenderManager API

 

Rendering Architecture

There are three key elements to the Ajax Push. (I mentioned these in my previous article)

  1. Render Manager – This is an application scoped managed bean to coordinate all render requests. This is also used to register render groups. The object we use is an instance of class “RenderManager”
  2. Render Group – A render group manages several Renderables (clients) that will receive same push updates. Types of render groups are: on-demand, interval and delay. Here we use objects that are instance of “GroupAsyncRenderer” class
  3. Renderable – Any request or session scoped managed bean implementing “Renderable” interface can be added to render group and push updates.
The figure 1 from ICEfaces Developer’s Guide shows how updates are pushed to client by different Group Renderers.

According to the architecture, you need to do following steps to use RenderManager API.

  1. Add Render Manager to application. This is for us to access the Render Manager in the application code.
  2. Create Render Groups, which will allow us to group the push events.
  3. Request a render on a Render Group.

Let’s see how we use above mentioned three key elements in our application. I will explain each in detail and show you the complete code in a separate section.

 

Renderable Interface

The Renderable interface has two methods.

public interface Renderable {

PersistentFacesState getState();

void renderingException(RenderingException renderingException);

}

 

This interface is typically implemented in request-scoped or session-scoped managed beans. The “getState()” method should return the current persistent faces state of the application. The “renderingException()” method is the exception callback method.

 

In order to return the PesistenceFacesState, you need to get the state from “PersistentFacesState” using the static “getInstance()” method.

You can use the constructor of the bean to get the “PersistentFacesState” in a request scoped bean.

Please note that the “PersistentFacesState” might be changed during the session, therefore in session-scoped beans you have to make sure that “getState()” returns the current state.

A recommended way is to get the state inside a valid getter method, which is bound to a page.

 

RenderManager Class

The RenderManager is the main class in the push API. There should be only one instance per application and therefore it can be configured as an application-scoped managed bean in JSF configuration file.

Then you can “inject” the RenderManager instance to any request-scoped or session-scoped managed beans.

GroupAsyncRenderer Implementations

There are several GroupAsyncRenderer implementations for use in application. Each instance provides a way to handle group rendering requests.

For example, in the sample chat application, a group is created and each user can be notified via the the group.

Each implementation allows to add or remove instances of “Renderable”.

Table 2: Comparison of GroupAsyncRenderer implementations

As you can see, the methods used to get GroupAsyncRenderer implementation has a String argument. That argument is the name we define for the group.

 

DisposableBean interface

This interface can be used to write the clean up code. This is not only used for RenderManager API.

public interface DisposableBean {

void dispose()throws Exception;

}

The “dispose()” method is called by ICEfaces framework whenever the bean goes out of scope.

 

Rendering Exceptions

Whenever server-initiated rendering fails, you will be notified via the exception callback method in Renderable. When exception is thrown, client will not receive recent set of updates.

There are three exceptions and the figure 2 shows the class hierarchy.   

Figure 2 : Rendering Exception Hierarchy

 

1. RenderingException

The RenderingException exception indicates general failure and the application may handle TransientRenderingException and FatalRenderingException subclasses in different ways.

2. TransientRenderingException

The TransientRenderingException exception is thrown when the rendering fails, but future rendering may succeed.

3. FatalRenderingException

The FatalRenderingException exception is thrown when the rendering fails and the cause might be the client is no longer connected (i.e. session expired). In this case, the server should clean up any resources used for the client.  

 

Sample application using the RenderManager API

Finally, it’s time to see the RenderManager API in action. The same chat application used in the previous article is used. Actually the chat application is similar to an IRC (Internet Relay Chat) client.

Here SessionRenderer API related code will be removed from sample application. There will be no change to the XHTML page.

1. We need to changed the code in our ManagedBean.java to use RenderManager API. (ManagedBean.java is the request scoped managed bean).

There are two interfaces to implement: Renderable and DisposableBean. Here “OnDemandRenderer” is used as we want to request a render after a chat message is added.

In the constructor, the PersistentFacesState is saved to an instance variable. The RenderManager is injected to this bean and it is configured in the faces-config.xml.

Whenever there is a failure or when the bean goes out of scope, the bean is removed from “OnDemandRenderer”.

The Renderable instance is added to the OnDemandRenderer group in the “setRenderManager()” method. This method is called when the RenderManager is injected to the bean.  

Following is the code.

package view;

import java.text.MessageFormat;

import javax.faces.event.ActionEvent;

import com.icesoft.faces.async.render.RenderManager;

import com.icesoft.faces.async.render.Renderable;

import com.icesoft.faces.context.DisposableBean;

import com.icesoft.faces.webapp.xmlhttp.PersistentFacesState;

import com.icesoft.faces.webapp.xmlhttp.RenderingException;

publicclass ManagedBean implements Renderable, DisposableBean {

private String name;

private String message;

private ApplicationBean applicationBean;

private RenderManager renderManager;

private PersistentFacesState state;

public ManagedBean(){

// Get PersistentFacesState instance.

// This is a request-scoped managed bean

// and therefore we can get the instance

// in constructor

state =PersistentFacesState.getInstance();

}

publicvoid send(ActionEvent event){

applicationBean.getMessagesList().add(

MessageFormat.format(“{0}: {1}”, name, message));

// Request render call using OnDemandRenderer

renderManager.getOnDemandRenderer(“chat”).requestRender();

}

public String getName(){

return name;

}

publicvoid setName(String name){

this.name= name;

}

public String getMessage(){

return message;

}

publicvoid setMessage(String message){

this.message= message;

}

publicvoid setApplicationBean(ApplicationBean applicationBean){

this.applicationBean= applicationBean;

}

publicvoid setRenderManager(RenderManager renderManager){

this.renderManager= renderManager;

renderManager.getOnDemandRenderer(“chat”).add(this);

}

public PersistentFacesState getState(){

// return current PersistentFacesState instance

return state;

}

publicvoid renderingException(RenderingException renderingException){

// No logic for handling exception

// Just remove this from the group

renderManager.getOnDemandRenderer(“chat”).remove(this);

}

publicvoid dispose()throws Exception {

renderManager.getOnDemandRenderer(“chat”).remove(this);

}

}

2. Configuring RenderManager application-scoped managed bean.

In faces-config.xml, we need to define the RenderManager as application-scoped managed bean

The qualified class name is “com.icesoft.faces.async.render.RenderManager” and we will use “renderManager” as the bean name.

Then the RenderManager should be injected to ManagedBean.

Following is the code for faces-config.xml

 

<?xmlversion=“1.0″encoding=“UTF-8″?>

<faces-configxmlns=“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_1_2.xsd”

version=“1.2″>

<application>

<view-handler>com.icesoft.faces.facelets.D2DFaceletViewHandler</view-handler>

</application>

<managed-bean>

<managed-bean-name>managedBean</managed-bean-name>

<managed-bean-class>view.ManagedBean</managed-bean-class>

<managed-bean-scope>request</managed-bean-scope>

<managed-property>

<property-name>applicationBean</property-name>

<value>#{applicationBean}</value>

</managed-property>

<managed-property>

<property-name>renderManager</property-name>

<value>#{renderManager}</value>

</managed-property>

</managed-bean>

<managed-bean>

<managed-bean-name>applicationBean</managed-bean-name>

<managed-bean-class>view.ApplicationBean</managed-bean-class>

<managed-bean-scope>application</managed-bean-scope>

</managed-bean>

<managed-bean>

<description>ICEfaces RenderManager</description>

<managed-bean-name>renderManager</managed-bean-name>

<managed-bean-class>com.icesoft.faces.async.render.RenderManager</managed-bean-class>

<managed-bean-scope>application</managed-bean-scope>

</managed-bean>

</faces-config>

 

Running the application

The final output of the application is same as the application I demonstrated in the previous article.

Following is a demonstration using Mozilla Firefox and Google Chrome.

 

Conclusion

In this article, you learned RenderManager API and how to use it. We used the sample application used in previous article, which used the SessionRenderer API.

You also learned how RenderManager API gives you better control over Ajax Push.

Please send your questions or suggestions to chrishantha@gmail.com

 

Resources

 

Comments

comments

Isuru Perera is a senior software engineer at wso2. He is a graduate at Informatics Institute of Technology (IIT), Sri Lanka where he completed his BSc Honours Software Engineering course offered by University of Westminster, United Kingdom. LinkedIn Profile: http://www.linkedin.com/in/chrishantha

NO COMMENTS

Leave a Reply