Skip to main content

A simple Ajax JSF 2.0 example

Posted by driscoll on November 4, 2008 at 5:24 PM PST

In my previous blog post, I talked about the New Composite Component feature of JSF. I'll come back to that shortly, but I'd like to talk about another new feature: integrated Ajax support. While this part of the specification is still being finalized, I thought it might be worthwhile to see what a simple example of the Ajax support in JSF 2.0 will look like. (Don't worry, I'll tie this together with Composite Components in a future posting.


Now, before I start, please keep in mind that the final version of JSF 2.0 will make this even easier, with a declarative (tag based) way to call out to Ajax in JSF. But for now, we'll have to be content with the Javascript centric approach described below. Also, to use this example, you'll have to use Glassfish v3 prelude, updated to build 5 of the JSF 2.0 EDR2 release via the updatetool - just released a couple hours ago. And if that doesn't say "this is Alpha level code", I don't know what does.


A fairly common "hello world" type ajax example is a counter - so let's build an app that counts upward. We'll need a simple bean to store the count, as well as increment it and reset it:



import javax.faces.event.ActionEvent;
import javax.faces.model.ManagedBean;
import javax.faces.model.SessionScoped;

@ManagedBean(name = "count")
@SessionScoped
public class Count {
    Integer count = 0;

    public Integer getCount() {
        return count++;
    }

    public void reset(ActionEvent ae) {
        count = 0;
    }
}


Note that unlike JSF 1.2, you can set up your managed bean without using the facesconfig.xml file - instead, you can just use annotations.


Now, we'll look at the facelets file that we'll be using, and then we'll go through line by line. Here's the facelets file:



<!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>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
    <title>Ajax</title>
</h:head>
<h:body>
    <h:form id="form1" prependId="false">
        <h:outputScript name="jsf.js" library="javax.faces" target="head"/>
        <h:outputText id="out1" value="#{count.count}"/>
        <br/>
        <!-- Increment the counter on the server, and the client -->
        <h:commandButton id="button1" value="Count"
                         onclick="jsf.ajax.request(this, event, {execute: this.id, render: 'out1'}); return false;"/>
        <br/>
        <!-- Resets the counter -->
        <h:commandButton id="reset" value="reset"
                            onclick="jsf.ajax.request(this, event, {execute:'reset', render: 'out1'}); return false;"
                            actionListener="#{count.reset}"/>
    </h:form>
</h:body>
</html>


This form paints three widgets: An outputText, and two commandButtons.

outputText "out1" has the contents of the count value. "button1", when pressed updates (and hence increments) the "out1" field and only that field" - there's no full page reload. Similarly, "reset" resets the counter value, and updates the "out1" field, and only that field. Useful? Not really, unless you were to put a bunch of other things on the page, and didn't want to refresh the entire page.


The h:outputScript tag says that we should include the JSF ajax library into our page. This is necessary for the call to jsf.ajax.request that we later make.


Note that even though the "out1" output text is the target of our ajax, it doesn't contain any unusual markup.


Then, we have "button1" - it's onclick method does two things - call jsf.ajax.request, and return false. The false return, for those not versed in JavaScript, means that it doesn't actually call submit on the enclosing form.


The jsf.ajax.request call, on the other hand, takes three parameters. The first is the calling object, this. The second is the calling event, event. You'll typically just use these values, so don't worry too much about them.


The last parameter is a JavaScript object with two properties - an execute property, which takes list of the ids of all the JSF components that we would like to execute - since we're executing this button, we'll include it in the list as 'this.id'. The second property is all the JSF components that we want to render - in this case, that's just 'out1'. That tells JSF to update the displayed value of the outputText component, above.


Lastly, we have 'reset' - it's onclick is pretty much identical, but there's an additional attribute, "actionListener". Since we're already executing 'reset', that means that JSF will call that method as part of the button push.


Hopefully this example was pretty clear - and fairly simple. Any questions? Ask below. (I'll be doing more complex examples as the month progresses.)


Update: I've updated this example to be more clear, and to conform with the latest JSF 2.0 PR release.

Related Topics >>

Comments

Need help.

HI, I couldn't get this working. In the bean, some of the package imports had to changed from the model package to the bean package. import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; And when I ran the JSP I kept getting: org.apache.jasper.JasperException: /index.jsp(12,41) #{...} is not allowed in template text org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:40) Head recking. Any help appreciated...

I changed the view from a JSP

I changed the view from a JSP to a Facelet and I get:
com.sun.facelets.tag.TagException: /index.xhtml @5,9 Tag Library supports namespace: http://java.sun.com/jsf/html, but no tag was defined for name: head at com.sun.facelets.compiler.CompilationManager.pushTag(CompilationManager.java:193)

Got it working

Got it working Here is the .xhtml file Ajax

Don't see the file...

I don't see the file? Where is it? Thanks. --Ebe

I'm not sure where you're seeing ajax.jsf - that's the old name of the resource. It's now jsf.js, and that's been changed in my blog for some time now.

Couldn't get it working

HI, I couldn't get this working. In the bean, some of the package imports had to changed from the model package to the bean package. import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; And when I ran the JSP I kept getting: org.apache.jasper.JasperException: /index.jsp(12,41) #{...} is not allowed in template text org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:40) Head recking. Any help appreciated...

Hi there, I can't get this example to run. I'm running GlassFish v3 Prelude with glassfish-jsf 2.0.0-9 (Feb 06 2009), but the AJAX resource seems to be missing. Effectively I get: <head> ... <script type="text/javascript" src="RES_NOT_FOUND"></script></head> My understanding is that "ajax.js" should come together with JSF, and the example should work out-of-the-box? Is this a bug in my glassfish-jsf component (build 2.0.0-9 instead of build 5, as you proposed)? Help required! CU Arno

Ah, rookie mistake. Here I am looking at ancient technology like the EDR2 release when you're marching ahead with spec and samples..

Re: Using JSF with some other Ajax library. Yes, you can do that. But unless you want a lot of bother, you'll either be using the JSF library to call to JSF pages, or using the alternate library to call a page that's not JSF. While it's possible to use the other Ajax library with a JSF page, you'd have to parse the XML returned by the JSF page. Re: Using @SessionScoped vs @ManagedBean(scope="session). Actually @SessionScoped is the new way, and ManagedBean is the old way - you've got it backwards (understandable). All my examples are built against the Mojarra Trunk, so they're always up to date.

FWIW, you use @SessionScoped in the example but I believe it's been replaced with an attribute of @ManagedBean, e.g. @ManagedBean(name="count", scope="session")

very richfaces-y. it looks good. can the managed bean data be accessed from a non-jsf 2.0 javascript api with the same name? rephrased: can i issue an ajax request to "count" from jquery? basically i want javascript pros to be able to work around the default js api if they feel like it. currently with richfaces that's really hard so you have to use their js tags etc and call them from non-a4j functions.

You wrote: I need jsf 2.0 to give me something that when I look at it I will say "Oh, it's quite difficult to do this with jsf 1.2 + richfaces/icefaces.

Sorry, but I think you're missing the point. Without this kind of standardization, there isn't a way for two different Ajax component libraries to interoperate. They might, but they might not, or they might sometimes, but not others. Standardization may not seem to matter to you, but try to use two different Ajax libraries in the same page right now, and I suspect you'll change your mind.

My next example will be how to write a component using Composite Components and the new Ajax features. For most JSF developers, what they'll really want is a bunch of great Ajax aware, interoperable components that can share a page without locking up. For advanced uses, you'll also want a way to easily create new ones.

But that said, the Ajax tags that are currently in discussion will hopefully give you a little of that "wow factor" that you're looking for, letting you declare that certain areas are Ajax without having to write any code.

As for "If jsf 2.0 wants to standardize those features, just copy them from RichFaces, IceFaces ... " - who do you think is working on the standardization?

Does anybody know how far with ajax the jsf 2.0 will go? I don't need jsf 2.0 to provide these re-render features (RichFaces can do it easily, I don't know about IceFaces so I cannot talk anything about it). If jsf 2.0 wants to standardize those features, just copy them from RichFaces, IceFaces ... (RichFaces is LGPL) and spend time on other things. I need jsf 2.0 to give me something that when I look at it I will say "Oh, it's quite difficult to do this with jsf 1.2 + richfaces/icefaces. Now it's easy with jsf 2.0."

I'd like to see an example of three or four dropdown lists (category, subcategory 1, subcategory 2, subcategory 3). As you make a selection all of the dropdown lists that come after are updated. Only the next dropdown list is enabled, and the rest are empty & disabled.