Jim Driscoll's Blog

Notes on Technology and the Web

Archive for the ‘ajax’ Category

ui:repeat and Ajax

with one comment

A nice feature of Facelets is the ui:repeat tag, which iterates over a supplied list of values to do a full list on your page. One problem: it’ll add an index to the generated id’s, which can make using it with Ajax a bit of a drag. But if you’re just using the f:ajax tag, that index is detected automatically, making ajaxifying the tag relatively easy. Here’s a quick example:


Say you want to make a page that offers three drop down menus with three choices each (it’s a simple example, work with me here). Here’s the data structure, set up as a bean:

   1 package demo;
   2 
   3 import java.util.ArrayList;
   4 import java.util.Arrays;
   5 import java.util.List;
   6 import javax.faces.bean.ManagedBean;
   7 
   8 @ManagedBean
   9 public class RepeatBean {
  10 
  11     private String[] sarray = {"one", "two", "three"};
  12     private String[] sarray2 = {"four", "five", "six"};
  13     private String[] sarray3 = {"seven", "eight", "nine"};
  14 
  15     private List<List<String>> llist;
  16 
  17     private String[] resultArray = {"two", "four", "nine"};
  18 
  19     public RepeatBean() {
  20         List<String> slist = Arrays.asList(sarray);
  21         List<String> slist2 = Arrays.asList(sarray2);
  22         List<String> slist3 = Arrays.asList(sarray3);
  23 
  24         llist = new ArrayList<List<String>>();
  25         llist.add(slist);
  26         llist.add(slist2);
  27         llist.add(slist3);
  28 
  29     }
  30     public List<List<String>> getLlist() {
  31         return llist;
  32     }
  33     public String[] getResultArray() {
  34         return resultArray;
  35     }
  36     public String getResultArray(int i) {
  37         return resultArray[i];
  38     }
  39     public void setResultArray(int i, String value) {
  40         resultArray[i] = value;
  41     }
  42     public void setResultArray(String[] resultArray) {
  43         this.resultArray = resultArray;
  44     }
  45 }


We create three lists – they’ll be the content of the drop down menus. We then create a list of String lists – llist – we’ll use this as the input for the . We also make a list to hold the results: resultArray.

Now: to use it in a page:

   1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   2 <html xmlns="http://www.w3.org/1999/xhtml"
   3       xmlns:ui="http://java.sun.com/jsf/facelets"
   4       xmlns:h="http://java.sun.com/jsf/html"
   5       xmlns:f="http://java.sun.com/jsf/core"
   6       xmlns:c="http://java.sun.com/jsp/jstl/core">
   7     <h:head>
   8         <title>Repeat Test Demo</title>
   9     </h:head>
  10     <h:body>
  11 
  12         <h:form id="repeatForm">
  13             <ui:repeat value="#{repeatBean.llist}" var="list" varStatus="current" id="repeat">
  14                 <h:selectOneMenu value="#{repeatBean.resultArray[current.index]}" id="chooseOne">
  15                     <f:selectItems value="#{list}"/>
  16                     <f:ajax render="outText"/>
  17                 </h:selectOneMenu>
  18                 <h:outputText value="#{repeatBean.resultArray[current.index]}" id="outText"/>
  19                 <br/>
  20             </ui:repeat>
  21         </h:form>
  22     </h:body>
  23 </html>


This ends up generating ids for the outputText field that look like: repeatForm:repeat:2:outText. But because we’re using the f:ajax tag, we only need to specify “outText” – the tag takes care of the work of finding out what the real id is.


Neat, huh? In case you’re not familiar with the ui:repeat tag – you should take a minute to get familiar with it, it’s core Facelets functionality. By using the var value, we’re saying that we want to create a list variable that will contain one of the lists in llist every iteration. By using varStatus and the index property, we’re keeping track of all of the values selected.


Just a simple example of the use of the f:ajax tag in a complex rendered environment. As always, let me know if you have any questions.

(This article originally published on my java.net blog on August 17, 2009.)

Written by jamesgdriscoll

February 9, 2010 at 10:03 PM

Posted in ajax, JSF

Keeping focus

leave a comment »


A recent user question, which has been repeated enough times to warrant a blog posting. In short: Why am I losing focus when I use the <f:ajax> tag?


Let’s imagine you have a form, with two input fields and two output fields:

   1 <h:form>
   2 <f:ajax event="blur" render="@form">
   3   <h:inputText id="onein" value="#{bean.one}">
   4   </h:inputText>
   5   <h:outputText id="oneout" value="#{bean.one}" />
   6   <h:inputText id="twoin" value="#{bean.two}">
   7   </h:inputText>
   8   <h:outputText id="twoout" value="#{bean.two}" />
   9 </f:ajax>
  10 <h:commandButton value="Submit" />
  11 </h:form>

You enter data in field one, tab to field two, and bam! the focus on field two is lost.


Why?


When you tabbed out of field one, you generated a blur event. This calls an Ajax request, which updates the entire form. That, in turn, removes and re-adds all of the elements in that form – including field 2. With that field (momentarily) gone, the focus is lost.


So, how to deal with this?


Simple rule: Don’t replace the parent element of the element whose focus you want to keep. There’s also a simple corollary: Don’t update stuff you don’t have to.


Here’s the changed markup that works:

   1 <h:form>
   2   <h:inputText id="onein" value="#{bean.one}">
   3     <f:ajax render="oneout"/>
   4   </h:inputText>
   5   <h:outputText id="oneout" value="#{bean.one}" />
   6   <h:inputText id="twoin" value="#{bean.two}">
   7     <f:ajax render="twoout"/>
   8   </h:inputText>
   9   <h:outputText id="twoout" value="#{bean.two}" />
  10 <h:commandButton value="Submit" />
  11 </h:form>


Note that you could also say render=”onein oneout twoout twoin” and it will still work because you aren’t updating the parent (the h:form) – even though you’re updating the field that has the focus.

Questions? Ask below.

(This article originally published on my java.net blog on August 11, 2009.)

Written by jamesgdriscoll

February 9, 2010 at 10:03 PM

Posted in ajax, JSF

Making a YUI Calendar Component in JSF2

leave a comment »


In my last blog entry, I went over getting a YUI widget working on JSF2. This time, let’s go over what’s required to move that widget into a JSF component. No Java required, but a fair bit of JavaScript.


In a lot of ways, this is just like other components that I’ve written about. The tricks are much the same – saving values into a JavaScript context. Including scripts into the component, that sort of thing.


Let’s go over the component, one file at a time. First, the using page:


   1    <ez:yuical id="cal1" value="#{date.date1}" render="out1"/>
   2    <h:outputText id="out1" value="#{date.date1}">
   3        <f:convertDateTime pattern="MM/dd/yyyy"/>
   4    </h:outputText>



To use the component, we just pass it two attributes – value, which is a managed property of type Date, and an optional render attribute, which will be updated via an ajax call when we click on a date in the component.


Simple enough. But since we’re using the version of the YUI code that’s served from Google, we’ll have to include the code in the head.



<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/yui/2.7.0/build/yuiloader/yuiloader.js"></script>


Why? Because JSF’s resource API assumes all resources are local – meaning that you can’t use the h:outputScript and h:outputStylesheet with resources external to your server. I thought about showing this example with locally available resources (it’s cleaner, of course), but thought the point was worth making. Hopefully, the 2.1 version of JSF will have the ability to specify a URL, in addition to just a local resource name.


So, that’s the using page: what’s the component look like? Not much, it turns out:

   1    <composite:interface name="yuical"
   2                         displayName="YUI Cal Component"
   3                         shortDescription="YUI Calendar Component">
   4        <composite:attribute name="value" required="true" type="java.util.Date"/>
   5        <composite:attribute name="render" required="false" type="java.lang.String"/>
   6    </composite:interface>
   7    
   8    <composite:implementation>
   9        <h:outputScript name="jsf.js" library="javax.faces" target="head" />
  10        <h:outputScript name="yuical/calendar.js" target="head" />
  11    
  12        <h:panelGrid class="yui-skin-sam" id="holdingContainer">
  13            <h:panelGroup layout="block" id="calContainer"/>
  14            <h:inputHidden id="date" value="#{cc.attrs.value}">
  15                <f:convertDateTime pattern="MM/dd/yyyy"/>
  16            </h:inputHidden>
  17        </h:panelGrid>
  18        <script type="text/javascript">
  19             demo.calendar.init("#{cc.clientId}", "#{cc.attrs.render}");
  20        </script>
  21    </composite:implementation>



The interface section (lines 1-6) just details what I’ve already gone over – two attributes, a value that’s a date, and required, and a value that’s a string, and that optionally points to an id that will be updated when the date value is selected.


Lines 9-10 are where we include the scripts for the component – and as I’ve previously mentioned, if we were to have the YUI JavaScripts locally, this is where we’d include those as well.


Lines 12-17 are the same as our previous blog, where we set up the necessary structure for the widget, as well as the hidden field which we’ll update when a date is selected in the widget.


Last, we have the script at line 19 – a simple call to init, passing in the contextual render value, so we can use more than one of these components in a page.


Now, let’s look at the JavaScript code. It’s long (for a simple demo), but much of it is the same as my previous blog, and quite a bit is simply necessary fluff. We’ll take it on in three chunks, corresponding to the three sections of the code – the setup, the init function, and the handler function.

   1    if (typeof demo == "undefined" && !demo) {
   2        var demo = {};
   3    }
   4    
   5    if (typeof demo.calendar == "undefined" && !demo.calendar) {
   6        demo.calendar = {};
   7    }
   8    
   9    if (typeof demo.calendar.contextMap === "undefined" && !demo.calendar.contextMap) {
  10        demo.calendar.contextMap = [];
  11    }



This is just a simple initialization of the objects we’ll be using the JavaScript. We escape it, so we don’t set them up twice – this lets us use more than one component in a page.


Now we’ll look at the init function that’s called within the component’s XHTML:

  13    demo.calendar.init = function init(context, render) {
  14    
  15        // record the render attribute, if applied
  16        demo.calendar.contextMap[context] = render;
  17    
  18        demo.calendar.loader = new YAHOO.util.YUILoader({
  19            base: "http://ajax.googleapis.com/ajax/libs/yui/2.7.0/build/",
  20            require: ["calendar"],
  21            loadOptional: false,
  22            combine: false,
  23            filter: "RAW",
  24            allowRollup: false,
  25            onSuccess: function() {
  26                try {
  27                    demo.calendar.cal1 = new YAHOO.widget.Calendar("demo.calendar.cal1", context+":calContainer");
  28                    demo.calendar.cal1.render();
  29                    demo.calendar.cal1.selectEvent.subscribe(demo.calendar.handleSelect, demo.calendar.cal1, true);
  30                } catch (e) {
  31                    alert(e);
  32                }
  33            },
  34            // should a failure occur, the onFailure function will be executed
  35            onFailure: function(o) {
  36                alert("error: " + YAHOO.lang.dump(o));
  37            }
  38    
  39        });
  40    
  41        //
  42        // Calculate the dependency and insert the required scripts and css resources
  43        // into the document
  44        demo.calendar.loader.insert();
  45    }



This code is almost the same as in the previous blog – naturally, since most of this is necessary for setting up the Calendar itself. Two changes, to let it be in a reusable component: line 16, which records the render attribute, and associates it with the component’s id value, and line 27, where we also take into account the component’s value.


And, finally, here’s the handler, which does most of the heavy (JSF specific) lifting for this component:

  48    demo.calendar.handleSelect = function handleSelect(type, args, obj) {
  49    
  50        if (type === "select") {
  51            var calId = obj.containerId;
  52            var index = calId.indexOf(":") + 1;
  53            var tmpindex = calId.substring(index).indexOf(":") + 1;
  54            // keep looking until you get the last child index
  55            while (tmpindex !== 0) {
  56                index += tmpindex;
  57                tmpindex = calId.substr(index).indexOf(":") + 1;
  58            }
  59            var containerId = calId.substring(0,index - 1);
  60            var dateId = containerId + ":" + "date";
  61            var dates = args[0];
  62            var date = dates[0];
  63            var year = date[0], month = date[1], day = date[2];
  64    
  65            var txtDate = document.getElementById(dateId);
  66            txtDate.value = month + "/" + day + "/" + year;
  67    
  68            var render = demo.calendar.contextMap[containerId];
  69            try {
  70                // if a render is defined for the component, then include it.
  71                if (typeof render !== "undefined" && render ) {
  72                    jsf.ajax.request(dateId,null,{
  73                        render: render,
  74                        execute: dateId
  75                    })
  76                } else {
  77                    jsf.ajax.request(dateId,null,{
  78                        execute: dateId
  79                    })
  80                }
  81            } catch (e) {
  82                alert(e);
  83            }
  84        }
  85    }



By using the passed in ID of the widget that was triggered, we obtain the id’s of the component, and from there the id of the date field (lines 51-60).


As in the previous blog, we then get the element that corresponds to the hidden field, and set it (lines 65-66).


Then retrieve the render value based on the component’s id. If there is a value (remember, it’s an optional value), use it, otherwise, don’t.


And finally, perform a jsf.ajax call with the hidden value as the executed portion – which will set it on the server.


And that’s it – we now have a component that graphically allows for selecting a date, and having it reflected on the server. Neat, huh?


Anyway, I’ll be uploading this into the Project Mojarra demo directory now that it’s complete, in the ajax-component demo. You can check out the full code there.


Feel free to ask questions, below.

(This article originally published on my java.net blog on August 9, 2009.)

Written by jamesgdriscoll

February 9, 2010 at 9:58 PM

Posted in ajax, JSF, YUI

Using the YUI Calendar widget with JSF 2

leave a comment »

If you’re not developing JSF with third party component libraries, you’re really missing out on the best part of JSF. But there’s lots of Ajax widgets out there, which contain all kinds of useful functionality. Wouldn’t it be useful to use those within your JSF pages?


The Yahoo UI library is pretty nifty stuff, and the Calendar widget is useful, pretty, and powerful. Let’s wire it into a JSF page, and bind the return of that widget to the property of a bean. How hard could it be? 71 lines, of which about 45 or so are non-boilerplate. Let’s take a look. Here’s what the page is going to look like when we’re done:
Screen Shot


And, line by line, here’s the breakout of the code – note that for this example, I’ve placed everything in one file, but you’d really want to break things out for a production environment.


   1    <?xml version="1.0" encoding="UTF-8"?>
   2    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
   3    <html xmlns="http://www.w3.org/1999/xhtml"
   4          xmlns:h="http://java.sun.com/jsf/html"
   5          xmlns:f="http://java.sun.com/jsf/core"
   6          xmlns:ui="http://java.sun.com/jsf/facelets">
   7        <h:head>
   8            <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/yui/2.7.0/build/yuiloader/yuiloader.js"></script>
   9            <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  10            <title>Test Binding</title>
  11        </h:head>
  12        <h:body>
  13            <h:outputScript name="jsf.js" library="javax.faces" target="head" />



The above code is mostly preamble, but there’s one necessary part worth exploring – Line 8 – we must use the script tag, rather than a h:outputScript tag, since outputScript is only for local resources, and this is calling an external URL. We’re using the Yahoo loader API, which we’ll call later on line 53 to load everything we need from yahoo. We’re loading this from Google’s website, primarily to keep everything in one file – whether to use local files or Google’s copies is an interesting question, but out of scope for this blog entry.

  14            <h:form id="form1" prependId="false">
  15                <div class="yui-skin-sam">
  16                    <div id="cal1Container"></div>
  17                </div>
  18                <h:inputHidden id="date" value="#{date.date}">
  19                    <f:convertDateTime pattern="MM/dd/yyyy"/>
  20                </h:inputHidden>
  21                <p>
  22                    The set date is:
  23                    <h:outputText id="out" value="#{date.date}" >
  24                        <f:convertDateTime/>
  25                    </h:outputText>
  26                </p>



Line 15-17 are the two divs that the YUI Calendar wants to see to set itself up. Note that we’re calling calendar div “cal1Container”. This will be the only part of our page that accepts input.


Line 18-20 is an h:inputHidden field that we’ll use to store the date entered into by the Calendar widget. We call it “date”, and we’ll reference it later on in the page.


Line 21-26 is our output mechanism for this page – strictly speaking, we don’t need this at all. After all, we’re already displaying the value of the calendar widget in the widget itself. This is just a way to show that, yes, we are in fact updating the bean on the server.

  27                <script type="text/javascript">
  28                    var cal1;
  29                    var loader = new YAHOO.util.YUILoader({
  30                        base: "http://ajax.googleapis.com/ajax/libs/yui/2.7.0/build/",
  31                        require: ["calendar"],
  32                        loadOptional: false,
  33                        combine: false,
  34                        filter: "RAW",
  35                        allowRollup: false,
  36                        onSuccess: function() {
  37                            try {
  38                                cal1 = new YAHOO.widget.Calendar("cal1", "cal1Container");
  39                                cal1.render();
  40                                cal1.selectEvent.subscribe(handleSelect, cal1, true);
  41                            } catch (e) {
  42                                alert(e);
  43                            }
  44                        },
  45                        // should a failure occur, the onFailure function will be executed
  46                        onFailure: function(o) {
  47                            alert("error: " + YAHOO.lang.dump(o));
  48                        }
  49                    });
  50    
  51                    // Calculate the dependency and insert the required scripts and css resources
  52                    // into the document
  53                    loader.insert();



With the exception of lines 36-44, this code is pretty much just YUI Loader boilerplate code. In fact, much of it can even be generated automatically by utilities on the main YUI site. All that this code is doing, is simply loading all of the JavaScript and CSS files required to run the Calendar widget.


Lines 36-44 set up the calendar, display it, and then register a listener on the widget. Line 40 says that we should call the selectHandler function, whenever the cal1 component has a select event.

  55                    function handleSelect(type,args,obj) {
  56                        var dates = args[0];
  57                        var date = dates[0];
  58                        var year = date[0], month = date[1], day = date[2];
  59    
  60                        var txtDate = document.getElementById("date");
  61                        txtDate.value = month + "/" + day + "/" + year;
  62                        try {
  63                            jsf.ajax.request("date",null,{render: 'out', execute: 'date'})
  64                        } catch (e) {
  65                            alert(e);
  66                        }
  67                    }
  68                </script>
  69            </h:form>
  70        </h:body>
  71    </html>


And this selectHandler function is the last part of the page. We get the date selected in the widget, assign it to the date hidden field, and then commit it to the server via the jsf.ajax.request call. Note that we also use that ajax call to update the output field as well – though I mentioned earlier that that was not strictly required – you could just use the YUI Calendar widget with the hidden field, skipping any additional display of values.


There’s more that can be done with this example – adding two way communication between the widget and the bean, for instance, or putting this into a component. But I’ve already spent a fair bit of text on this example, that’s a topic for another day.


As always, let me know if you have any questions about this example in the comments below.

(This article originally published on my java.net blog on August 9, 2009.)

Written by jamesgdriscoll

February 9, 2010 at 9:33 PM

Posted in ajax, JSF, YUI

Including scripts in JSF 2 Ajax requests

leave a comment »

I’d wanted to blog some time ago about including scripts in your JSF ajax requests, but Hazem Saleh beat me to it. Hazem is the creator of the nifty Google Maps component for JSF, gmaps4jsf.

So, go and follow the link, but I’ll just add three short comments to Hazem’s blog:

  • In many popular ajax solutions for JSF, <script> tags were simply interpreted in place. This is not, for whatever reason, part of the JSF spec right now – so you’ll have to use one of the two ways that Hazem describes, in order for it to be a portable solution.
  • The first solution Hazem notes uses the event system for JSF client side – it simply adds an event listener that’s called every time a page is updated, and calls the eval for any included scripts.
  • The second solution is the “preferred” way that is specified in the spec – simply return the script you want to execute as part of the xml that goes to the client.

Hope this note helps someone trying to execute an arbitrary script on a JSF client page.

(This article originally published on my java.net blog on July 18, 2009.)

Written by jamesgdriscoll

February 9, 2010 at 9:04 PM

Posted in ajax, JSF

A tale of two components (JSF2)

with one comment

Today, I’d like to take a look at two different ways to create a poll component. Poll components are a way to periodically update a page with new information. We’ll take a look at examples of these in a second, but first, a caveat: I’ve assumed throughout my blogs on Ajax components in JSF that you have at least a passing familiarity with JavaScript. This post assumes a bit more knowledge of JavaScript than some other posts. I’ll try to explain what I’m doing as I go along, but if you find yourself mystified by closures, I’d like to suggest the book JavaScript: The Good Parts. It’s a wonderful book, and quite short. Check it out.


With that out of the way, here’s how you’d use these two poll components within a page:

Count:<br/>
<h:outputText id="target" value="#{count.count}"/><br/>
<ez:polltag id="poll" interval="200" timeout="5000" render=":form:target"/>
<h:outputText id="target2" value="#{count.count2}"/>
<ez:poll id="poll2" interval="1000" timeout="10000" render="form:target2"/>

Let’s go over what this does: We have a two components, polltag and poll. They each have three attributes, interval (how often to refresh the target), timeout (when to stop), and render (the target we’ll refresh). These tags are identical in function, with the only difference being the format of their render attribute (more on that momentarily) and the method they use to make the Ajax call. Run this page, and you’ll see the numbers increment – one quickly, and the other more slowly (count.count just increments every time it’s accessed).


Let’s start by taking a look at the polltag component. I decided to start with just a quick, naive component that uses the Ajax tag. Let’s take a look at what that tag looks like (resources/poll/polltag.xhtml):

<cc:implementation>
    <span id="#{cc.clientId}">
    <h:outputScript name="poll/polltag.js" target="head" />
        <h:commandButton id="hidden" type="button" style="display: none;">
            <f:ajax render="#{cc.attrs.render}"/>
        </h:commandButton>
    </span>
    <script type="text/javascript">
        jsfdemo.polltag.init("#{cc.clientId}","#{cc.attrs.interval}", "#{cc.attrs.timeout}");
    </script>
</cc:implementation>


For those of you following my previous blogs, much of this isn’t new: We wrap the whole component to get a span on the page with the supplied id. We include a script (resources/poll/polltag.js) which adds the backing JavaScript. We also inject a small script which calls that backing JavaScript function. And that injected script includes the necessary context to allow multiple tags to be placed in the page.


But the new thing here is that we’re including a hidden button, and attaching an Ajax tag to it. That Ajax tag will then inject code that activates when the button is clicked. Since the button is hidden, we’ll “click” the button programatically, inside the init function. Let’s take a look at that backing JavaScript.

if (!window.jsfdemo) {
    var jsfdemo = {};
}

if (!jsfdemo.polltag) {
    jsfdemo.polltag = {};
}

if (!jsfdemo.polltag.init) {
    jsfdemo.polltag.init = function init(id, inc, to) {
        var componentID = id;
        var increment = inc;
        var timeout = to;
        var elapsed = 0;
        var token = null;

        // If increment isn't set, or it's less than some reasonable value (50) default to 200ms
        if (isNaN(increment) || increment <= 50) {
            increment = 200;
        }
        // If timeout isn't set, default to no timeout
        if (isNaN(timeout) || timeout == 0) {
            timeout = -1;
        }

        var poll = function poll() {
            var hiddenID = componentID + ":" + "hidden";
            var hidden = document.getElementById(hiddenID);
            hidden.click();  // this executes the ajax request
            if (timeout != -1) {
                // Not an accurate timeout - but simple to compute
                elapsed += increment;
                if (elapsed > timeout) {
                    window.clearInterval(token);
                }
            }
        }

        token = window.setInterval(poll, increment);
    }
}

OK, this is a little long, let’s break it down to see what’s going on here.

First, we do namespacing: by creating objects, and placing the function onto that object, we make sure that we don’t accidentally have two init() functions in a page – such as when we’re creating two different poll tags with init functions. We also need to check if those objects already exist before creating them – after all, we may want to have multiple namespaces placed onto the “jsfdemo” object.


Then, we define a module – we have an init() function, and inside that init() function, we also define a poll() function. The poll() function has access to the variables inside the init() function, but calling the init function multiple times results in multiple contexts. This is a pretty common pattern in JavaScript, but it does look awkward to folks coming from Java.


At the end of the file, after setting up the poll() function, we have the line:

token = window.setInterval(poll, increment);


Which sets up the poll – we’re simply using the JavaScript setInterval function to periodically call the poll() function, every increment milliseconds.


When the poll function is called, we find the button, and click it. This will, in turn, trigger the Ajax call. Then, we determine if the timeout time has come, and if it has, we turn off the timer with the clearInterval call.


OK, a little kludgy – but it works, after a fashion. There are some problems with this approach: Since we’re using the f:ajax tag, we need to use the UIComponent.findComponent syntax for locating the target to update – some may prefer this, some won’t. And while having a button that you could “unhide” to restart the poll might be handy, in general it’s just cluttering up your page. Also, if the server stops responding for some reason, you’ll get pummeled with error alerts if you’re in development mode.


So, let’s go ahead and rewrite this to instead use the jsf.ajax.request function, provided by jsf.js in JSF 2.


We’ll only have to make a few quick changes to do this, as well as adding error handling. First, in the component page, we’ll say add an output script call. And, we’ll also change the call to init to be wrapped inside a jsf.ajax.addOnError function call. This will add a function to the list of listeners that get called if there’s an error on the page. Note that the init function itself is not the function that will get added – rather, it’s return value will be what’s added. And we’ll make that return value be a function (you’ll see it in a second). We also remove all the markup associated with the button.

<cc:implementation>
    <span id="#{cc.clientId}">
        <h:outputScript name="jsf.js" library="javax.faces" target="head"/>
        <h:outputScript name="poll/poll.js" target="head" />
    </span>
    <script type="text/javascript">
        /* <![CDATA[ */
        jsf.ajax.addOnError(jsfdemo.poll.init("#{cc.clientId}","#{cc.attrs.interval}", "#{cc.attrs.timeout}", "#{cc.attrs.render}"));
        /* ]]> */
    </script>
</cc:implementation>

In the backing JavaScript, we’re going to have to make two changes. We’ll have to change the poll function, and we’ll have to add a return value to the init function. Here’s the entirety of the backing JavaScript file:

if (!window.jsfdemo) {
    var jsfdemo = {};
}

if (!jsfdemo.poll) {
    jsfdemo.poll = {};
}

if (!jsfdemo.poll.init) {
    jsfdemo.poll.init = function init(id, inc, to, rend) {
        var componentID = id;
        var increment = inc;
        var timeout = to;
        var elapsed = 0;
        var token = null;
        var render = rend;

        // If increment isn't set, or it's less than some reasonable value (50) default to 200ms
        if (isNaN(increment) || increment <= 50) {
            increment = 200;
        }
        // If timeout isn't set, default to no timeout
        if (isNaN(timeout) || timeout == 0) {
            timeout = -1;
        }

        var poll = function poll() {
            jsf.ajax.request(componentID, null, {render: render});
            if (timeout != -1) {
                // Not an accurate timeout - but simple to compute
                elapsed += increment;
                if (elapsed > timeout) {
                    window.clearInterval(token);
                }
            }
        }

        token = window.setInterval(poll, increment);

        return function cancelPoll(data) {
            if (data.source.id == componentID) {
                window.clearInterval(token);
            }
        }
    }
}

Let’s look at the return value first:

return function cancelPoll(data) {
    if (data.source.id == componentID) {
        window.clearInterval(token);
    }
}


We add this at the end of the init function – which means that init will return this function as it’s return value, and that this function will be what’s added to the list of listeners that get called when there’s an error. Because this function will get called regardless of what component causes the error, we add a check to make sure that the current component is the one that got the error. And, as in the poll function, because this function is defined inside init, it has access to all of the context that’s there when init is called – in this case, the componentID variable, passed in by the script tag in the component.


The changes for the poll function to use jsf.ajax.request are relatively straightforward:

var poll = function poll() {
    jsf.ajax.request(componentID, null, {render: render});
    if (timeout != -1) {
        // Not an accurate timeout - but simple to compute
        elapsed += increment;
        if (elapsed > timeout) {
            window.clearInterval(token);
        }
    }
}


Much simpler than the corresponding code surrounding the tag method.


As always, this code can be found in the jsf-demo/ajax-components directory of the Project Mojarra codebase. You’ll find this and much more code there, including most of the code I’ve blogged about in the past.


If you have questions, please let me know in the comments section.

(This article originally published on my java.net blog on July 3, 2009.)

Written by jamesgdriscoll

February 9, 2010 at 9:03 PM

Posted in ajax, JSF

Automatic compression of jsf.js

leave a comment »

Just a quick note that we’ve now added automatic compression of the jsf.js file served by JSF 2. The file size of jsf.js, 71k uncompressed, comes to about 16k compressed (there are a lot of comments in there).


There is no user action required to make this happen: If the Project stage is Development, the file is served uncompressed (for ease in debugging with something like Firebug), but if the Project stage is anything else, then the file is compressed (and essentially unreadable, since besides stripping all comments, variable names are stripped, as well as all line breaks).


To enable Project Stage as Development, place the following in your web.xml file:


    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>

(This article originally published on my java.net blog on July 3, 2009.)

Written by jamesgdriscoll

February 9, 2010 at 9:00 PM

Posted in ajax, JSF

A final look at the Switchlist JSF 2 component

leave a comment »

It’s been a long time, but I’ve revisited the Switchlist component I blogged about here here and here. Read through those old entries to see where we are with things. I will assume you’re already familiar with the content of those entries, we’ve got a lot to cover as it is.


Today, we’re going to completely rework this code, to illustrate some best practices. We’ll make the component use Ajax, we’ll have it separate out the control from the model, and we’ll make the whole component addressable with an Ajax tag itself as well.


First, the change in the backing Java classes. Previously, I’d just tossed together all the of the necessary functions into a single monolithic Java class, which exposed four data properties (which means 8 getters and setters), as well as two action methods, used in an action listener. For obvious reasons, this is a sloppy design. Better to have the data separated out, with the control methods hidden from the enduser.


With that in mind, we’ll create an interface, let’s call it ListHolder. It looks like this:

public interface ListHolder {

    public String[] getList();

    public void setList(String[] list);

    public Map getItems();

}


This encapsulates the data that each list operates on. We’ll also make two classes that actually hold that data, like this:


@ManagedBean(name="listholder1")
@SessionScoped
public class ListHolder1 implements ListHolder, Serializable {

    private static final long serialVersionUID = -4047970327214634942L;

    String[] list = null;
    Map items = new LinkedHashMap();

    {
        items.put("one", "one");
        items.put("two", "two");
        items.put("three", "three");
        items.put("four", "four");
    }

    public String[] getList() {
        return list;
    }

    public void setList(String[] list) {
        this.list = list;
    }

    public Map getItems() {
        return items;
    }
}

Though we could use any class which implemented the interface. And lastly, we'll create a controller class:

@ManagedBean
@RequestScoped
public class SwitchlistController implements Serializable {

    private static final long serialVersionUID = -4002627066189080830L;

    ListHolder listholder1, listholder2;

    public String m1_2() {
        String[] list1 = listholder1.getList();
        Map<String, String> items2 = listholder2.getItems();
        Map<String, String> items1 = listholder1.getItems();
        if (list1 != null && list1.length > 0) {
            for (String item : list1) {
                items2.put(item, items1.remove(item));
            }
        }
        return null;
    }

    public String m2_1() {
        String[] list2 = listholder2.getList();
        Map<String, String> items2 = listholder2.getItems();
        Map<String, String> items1 = listholder1.getItems();
        if (list2 != null && list2.length > 0) {
            for (String item : list2) {
                items1.put(item, items2.remove(item));
            }
        }
        return null;
    }

    public void setListHolder1(ListHolder listholder1) {
        this.listholder1 = listholder1;
    }

    public void setListHolder2(ListHolder listholder2) {
        this.listholder2 = listholder2;
    }

}

Again, little here that's surprising - the m1_2 and m2_1 methods are now action methods, instead of actionListener methods, for reasons I'll go into in a minute. We also have two setter methods, which we'll use with setPropertyActionListener.


So, now we've got the model and the controller all laid out, let's see how this would be used in a view. Here's the tag we'd like to use in the using page:

<ez:switchlist id="switchlist"
   listholder1="#{listholder1}" 
   listholder2="#{listholder2}"/>

Two parameters, each pointing to the listholder classes that implement the listholder interface.


Now, let's look at the interface in the composite component itself:

<cc:interface name="switchlist">

    <cc:attribute name="listholder1" required="true">
        <cc:attribute name="list" required="true"/>
        <cc:attribute name="items" required="true"/>
    </cc:attribute>
    <cc:attribute name="listholder2" required="true">
        <cc:attribute name="list" required="true"/>
        <cc:attribute name="items" required="true"/>
    </cc:attribute>
</cc:interface>

What's here: Only the CompositeComponent version of the interface that we've defined earlier. For each of the two attribute, there are two properties - list and items.


And lastly, let's take a look at the implementation.

<cc:implementation>
    <h:outputStylesheet name="switchlist/switchlist.css"/>
    <div id="#{cc.clientId}">
    <h:selectManyListbox id="list1" value="#{cc.attrs.listholder1.list}" styleClass="switchlist">
        <f:selectItems value="#{cc.attrs.listholder1.items}"/>
    </h:selectManyListbox>
    <h:panelGroup id="buttonGroup" styleClass="switchlistButtons">
        <h:commandButton id="move1to2" value="&gt;&gt;" action="#{switchlistController.m1_2}"
                         styleClass="switchlistButton">
            <f:setPropertyActionListener value="#{cc.attrs.listholder1}" target="#{switchlistController.listHolder1}"/>
            <f:setPropertyActionListener value="#{cc.attrs.listholder2}" target="#{switchlistController.listHolder2}"/>
            <f:ajax execute="@this list1" render="list1 list2"/>
        </h:commandButton>
        <h:commandButton id="move2to1" value="&lt;&lt;" action="#{switchlistController.m2_1}"
                         styleClass="switchlistButton">
            <f:setPropertyActionListener value="#{cc.attrs.listholder1}" target="#{switchlistController.listHolder1}"/>
            <f:setPropertyActionListener value="#{cc.attrs.listholder2}" target="#{switchlistController.listHolder2}"/>
            <f:ajax execute="@this list2" render="list1 list2"/>
        </h:commandButton>
    </h:panelGroup>
    <h:selectManyListbox id="list2" value="#{cc.attrs.listholder2.list}" styleClass="switchlist">
        <f:selectItems value="#{cc.attrs.listholder2.items}"/>
    </h:selectManyListbox>
    </div>
</cc:implementation>


Now, top to bottom, let's look at what we've done here.


First, wrap everything in a div, and give it an id that's the same as the composite component as a whole. This is something you'll need to do to let ajax tags operate on your component - otherwise, there won't be anything in your page with the id of the component you just added - in our case "switchlist", in the using page. There would only be "switchlist:buttonGroup" and such. Doing this also means that you can better do styling with css, since you now have a block you can work with, instead of a loose group of tags with no wrapper.


Next, see that we have a bunch of references that look like #{cc.attrs.listholder1.list}. This is how we get access to the properties that we defined in the interface section, above, as well as in the ListHolder interface.


Also, note that we've changed from using an actionListener attribute on the buttons, to an action. We're also passing values into the controller via the f:setPropertyActionListener - these two things are related. If we'd just continued to use the actionListener method of executing a method, the setPropertyActionListeners wouldn't be called until after the actionListener - which makes sense, since those listeners are called in the order they're added, but not terribly useful for our purposes. So we instead use a action, which returns null - meaning no navigation.


Lastly, note that for making this ajax enabled, we simply need to say: f:ajax execute="@this list2" render="list1 list2". @this means to execute the button it's placed on, which calls the action method. Executing list2 (note the relative path, it uses the same semantics as UIComponent.findComponent()) is necessary for populating the contents of the items array. And lastly, the render command is necessary to show the results.


So, a brief recap:

  • Separate out your model from your controller. See how clean the code looks now?
  • You can nest attributes in the composite:interface section.
  • Once nested, you can access those values with dot notation.
  • Wrap your components in a top level div or span with the cc.clientId - you'll be glad later.
  • You can use setPropertyActionListener to pass params, but you'll need to use an action method. This is no different from standard JSF 1.2. Indeed, using the Ajax tag is usually just a matter of adding it to already working code. Neat!
  • @this refers the current component. (And, by the way @form refers the the wrapping form, and @all and @none are kinda self explanatory)

Lots of code in a short space, but we've already covered a lot in other blogs. Questions? Ask away, in the comments, and I'll do my best to answer.


And, one last note: If you're attending JavaOne, this example is the basis for a talk that Ryan Lubke and I will be giving at JavaOne - BOF 4146, on Wednesday, at 745pm, Esplanade 307. Come on by and ask questions. I'll post the slides and the full example code in a later blog, after the conference.

(This article originally published on my java.net blog on May 27, 2009.)

Written by jamesgdriscoll

February 9, 2010 at 8:52 PM

Posted in ajax, JSF

JSF 2: Ajax Events and Errors

leave a comment »

Today I want to look at how to handle Ajax events and errors in JSF 2.

JSF 2’s Ajax support includes a very basic facility to listen for events and errors within JSF’s client side processing code. It’s envisioned that this will primarily be used by component developers that wish to monitor events – for instance, turning an image yellow when there’s an outstanding Ajax request, and black when there isn’t.

So, without further ado, here’s a few snips of code from Mojarra’s ajax-queue demo:

In a page with some Ajax calls, we have the following field:

<h3> Status:</h3>
<textarea id="statusArea" cols="40" rows="10" readonly="readonly" />

A simple textarea, not even hooked into the backend server data model.

Then in our javascript (for the demo, in a separately loaded file, though it could just as easily be in page) we have:

var statusUpdate = function statusUpdate(data) {
    var statusArea = document.getElementById("statusArea");
    var text = statusArea.value;
    text = text + "Name: "+data.source.id;
    if (data.type === "event") {
        text = text +" Event: "+data.name+"\n";
    } else {  // otherwise, it's an error
        text = text + " Error: "+data.name+"\n";
    }
    statusArea.value = text;
};

// Setup the statusUpdate function to hear all events on the page
jsf.ajax.addOnEvent(statusUpdate);
jsf.ajax.addOnError(statusUpdate);

When run, you'll see a stream of data going through the textarea as ajax events happen elsewhere in the page. Try out the demo to see more. (Again, it's in the Mojarra codebase, under jsf-demo/ajax-queue)

What's happening: first we define a JavaScript function, place it in a variable, and then call two JSF ajax api functions: addOnEvent and addOnError. These functions use the statusUpdate function as their callback, passing the data object as it's first parameter.

That data object, along with the functions themselves, are defined in Section 14.4 of the JSF 2 specification. I'll outline a little of what's in there here, but be sure to check it out for the full scoop - it's a pretty easy to read and understand part of the spec.

For Events, there are three named events: begin, complete, and success.

  • begin - happens before the request is sent.
  • complete - happens once the request has completed, before javax.faces.response is called.
  • success - happens after the response method finishes.

This means that for a normal request, all three will be called, while if there is some sort of error, then only begin and complete will be called.

For Errors, there are four named errors possible.

  • httpError - happens if the client receives any HTTP status other than something between 200 and 299, inclusive.
  • emptyResponse - happens when the connection is dropped without a response.
  • malformedXML - means that the XML that was received couldn't be parsed correctly.
  • serverError - what happens when an error is generated on the server and transmitted back to the client.

The data payload consists of:

  • type - one of event or error
  • name - the name of the error or event, as above.
  • source - the DOM element that triggered the event (which is why you can see a data.source.id access in there, to get the id of the element)
  • for errors named serverError, there's also an errorName and errorMessage field, for passing through server errors.
  • plus responseCode, responseXML, and responseTxt, as in the XMLHttpResponse object.

So, when to you need to use this functionality? Probably not very often. But since it's not really documented anywhere else yet, I wanted to get some description out there for what it does.

(This article originally published on my java.net blog on May 15, 2009.)

Written by jamesgdriscoll

February 9, 2010 at 8:50 PM

Posted in ajax, JSF

Redirecting from a JSF 2.0 Ajax Request

leave a comment »

Somewhat recently, I had a user of JSF 2.0 ask how to do a redirect from a JSF 2.0 Ajax request. Here’s one way, that I’ve lifted from one of our tests:


First, the bean that does the work:

@ManagedBean
@RequestScoped
public class RedirectBean {

    public String redirect() {

        FacesContext ctx = FacesContext.getCurrentInstance();

        ExternalContext extContext = ctx.getExternalContext();
        String url = extContext.encodeActionURL(ctx.getApplication().getViewHandler().getActionURL(ctx, "/ajax/redirecttarget.xhtml"));
        try {

            extContext.redirect(url);
        } catch (IOException ioe) {
            throw new FacesException(ioe);

        }
        return null;
 
    }



Hopefully, I don’t have to explain what this is doing – it’s sending a redirect request – regardless of whether it’s an Ajax request or not.


Next, the code that’s calling it:


<h:head>
    <title>Ajax Redirect</title>
</h:head>
<h:body>
    <h:form id="form">
        <h:commandButton id="redirect" value="Redirect" action="#{redirectBean.redirect}">
             <f:ajax execute="@this" render="@none"/>
        </h:commandButton>
    </h:form>
</h:body>



So, what’s happening here? Well, once the bean sends the redirect, the ajax client receives a message from the server telling the client to redirect to a new page – all invisibly to the user. In case you’re curious, here’s what’s going back to the client along the wire:


"<?xml version="1.0" encoding="utf-8"?>
<partial-response>
  <redirect url="/contextpath/faces/ajax/redirecttarget.xhtml">
  </redirect>
</partial-response>"



So, a simple ajax request can redirect you to a new page. Like most of the new JSF 2 stuff, we’ve tried to make things “just work” as much as possible.


A little more edgecase than some of my previous blogs perhaps, but probably a useful trick to keep in mind. The code was originally written by Ryan Lubke, BTW, just to make sure that credit lands where it’s due.

Now that our big push for JavaOne is wrapping up, I’m hoping to have more time to blog in the immediate future. Stay tuned.

(This article originally published on my java.net blog on May 15, 2009.)

Written by jamesgdriscoll

February 9, 2010 at 8:45 PM

Posted in ajax, JSF