This chapter is going to talk about some "advanced" RichFaces topics. You will discover with single examples how to use and implement pushing, partial updates, session expiration handling, and so on.
By using the a:poll
component, you can periodically poll the server for data and updates using an Ajax request. The use is the same as for a:commandButton
and a:commandLink
, so you can invoke an action and re-render one or more page areas.
This component uses a form-based request, so, it is required to put the a:poll
component inside h:form
.
Here there is a little example that shows how to use it:
<h:form> <a:poll id="poll" action="#{aBean.pollAction}" interval="500" reRender="result" /> </h:form> <h:outputText id="result" value="Polling result: #{aBean.pollResult}" />
In this piece of code, we used the a:poll
component to execute an action (the method pollAction()
of the aBean
bean) every 500 milliseconds (using the interval
attribute) and, after the execution finished, to update the component with id = "result
" (that writes the value the pollAction()
method set in the pollResult
property of the web page).
As we've said, we need h:form
surrounding the a:poll
component in order to make it work.
Let's do another simple example we want to show a seconds counter updated every second with a checkbox that enables or disables it.
First, let's do our backing bean: in our project, by creating the book.richfaces.advcm.modules.main.examples.poll
package and, inside that, a new class called PollExample
. This class would look like this:
package book.richfaces.advcm.modules.main.examples.poll; @Name("pollExample") public class PollExample { private boolean pollingEnabled = true; public boolean getPollingEnabled() { return pollingEnabled; } public void setPollingEnabled(boolean pollingEnabled) { this.pollingEnabled = pollingEnabled; } public int getSeconds() { Calendar cal = Calendar.getInstance(); return cal.get(Calendar.SECOND); } }
As you can see, it is a simple Seam component with the boolean
property (pollingEnabled
) having the getter and setter, and a method that returns the current time in seconds (getSeconds()
).
Now, let's create the pollExample.xhtml
page inside the /view/examples/poll/
directory. It might look like:
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:a="http://richfaces.org/a4j" template="/layout/template.xhtml"> <ui:define name="body"> <h:form> <a:poll id="myPoll" interval="1000" enabled="#{pollExample.pollingEnabled}" reRender="pollUpdate" ajaxSingle="true"/> <h:selectBooleanCheckbox value="#{pollExample.pollingEnabled}"> <a:support event="onchange" reRender="myPoll,pollUpdate" ajaxSingle="true"/> </h:selectBooleanCheckbox> <h:panelGroup id="pollUpdate"> <h:outputText value="Polling active: " rendered="#{pollExample.pollingEnabled}"/> <h:outputText value="Polling NOT active: " rendered="#{!pollExample.pollingEnabled}"/> <h:outputText value="#{pollExample.seconds}"/> </h:panelGroup> </h:form> </ui:define> </ui:composition>
Here, we have defined the a:poll
component inside h:form
, setting the polling interval to 1000 ms (that is, one second) and re-rendering the text section at every update. Also, we have set the ajaxSingle
attribute to true
, because we don't want to process the checkbox value every time the poll is fired (we should also use two different forms for that).
Inside the h:selectBooleanCheckbox
, we inserted the a:support
component to fire an Ajax action when the user clicks on the checkbox, submitting the form, updating the model with the new checkbox value, and re-rendering the a:poll
component that is enabled or disabled, depending on the boolean
value controlled by the checkbox (pollingEnabled
).
Finally, the outputText
component renders the information back to the user; those are updated every second by the a:poll
component.
The result of the enabled polling is:
As we have said, the text is updated every second with the current time in seconds from the server clock.
When the poll component is disabled, nothing is updated and the text stays with the value of the latest update:
In order to add something interesting to this example and also to explain another useful component, we are going to edit it by adding a dynamic graphical counter. We will use the a4j:mediaOutput
RichFaces component to render an image (each second) with the current value of seconds from the server.
First of all, let's open PollExample.java
and add the paint method to create the image:
public void paint(OutputStream out, Object data) throws IOException { // Creating an image BufferedImage img = new BufferedImage(40, 40, BufferedImage.TYPE_ INT_RGB); // Getting the Graphics2D object Graphics2D graphics2D = img.createGraphics(); // Setting background color, foreground color and font size graphics2D.setBackground(Color.WHITE); graphics2D.setColor(Color.RED); graphics2D.setFont(graphics2D.getFont().deriveFont(25f)); // Clearing the background with the color set graphics2D.clearRect(0, 0, 40, 40); // Drawing the number value graphics2D.drawString(String.valueOf(getSeconds()),4,36); // Writing the image into the output stream as PNG ImageIO.write(img,"png",out); }
As you can notice, the paint method has two parameters the first one is OutputStream
used to write the output image to and the second one contains the Serializable
object, passed by the value
attribute of the component (in our case, we are not using it).
This method creates BufferedImage
, fills it with the current seconds value, and writes it as a PNG
image to the output stream.
Now, let's open pollExample.xhtml
and insert the mediaOutput
component:
Replace the following component:
<h:outputText value="#{pollExample.seconds}"/>
With this code:
<a:mediaOutput element="img" cacheable="false" value="#{pollExample.seconds}" createContent="#{pollExample.paint}" mimeType="image/png"/>
As we can see, we have set the element
attribute as img
, which is why the component supports the dynamical generation of other kinds of objects such as Flash movies, applets, or scripts.
The cacheable
attribute defines the caching strategy both for the client and the server. Anyway, for our frequent requests, it is possible that the client caches the image in any case. Therefore, it will not be refreshed each second.
In order to avoid this problem, it is sufficient to set the value
attribute with a different value for every update (in our case, the current value of the seconds from the server). As the serialized object passed becomes part of the image name, the name will change for every new generated image, which will therefore not be cached by the browser.
The object passed using the value
attribute is passed to the paint method, using the data
parameter.
For specifying which method to call in order to generate the object, we use the createContent
attribute and we've set the MIME type of the returned image (image/png
) using mimeType
.
The result, when polling is active, is as follows:
When it is not active, we will see the last image sent:
18.116.67.70