Jim Driscoll's Blog

Notes on Technology and the Web

Archive for the ‘ajax’ Category

Thin Server the Hard Way (Model layer)

leave a comment »

This post is part of a series examining the Modern Web. Currently, I’m trying to assess pain points in creating a Single Page application, and to do that, I’ve created a simple application which does inventory management. You can find the (somewhat sloppy) code on Github, if you want to follow along.

After my previous post looking at routing, today we’ll examine how to handle the model layer of our single page app.

Architecture

The first step on something like this is to decide on an initial architecture. QEDServer has a fairly simple REST API for fetching and updating records in the database – the only mildly tricky part is to format and pass it parameters. So a fairly lightweight wrapper around the jQuery AJAX API is probably all that’s required. Let’s model what how it’d be used, in this case for fetching a page of results containing the names of Categories for our products:

        qedModel.getCategories({
            page: currentPage,
            search: search,
            error: onFetchError,
            success: onFetchSuccess,
            complete: onFetchAlways
        });

Implementation

The REST API we’re using already has a paging facility (you pass it a URL param of ?page=number) as well as search (passing a URL param of ?q=searchterm), so the JavaScript API wrapper we need to develop only needs to smartly handle parameter building for the URL, which is a pretty simple task. We’ll also want to have success, error and complete callbacks, which are handled by the jQuery AJAX API already. So, the finished code is really pretty simple:

        getCategories: function getCategories(params) {
            var error = params.error || null;
            var success = params.success || null;
            var complete = params.complete || null;
            var page = params.page || 1;
            var search = params.search;
            var endpoint = '/categories.json?';
            if (!!search) {
                endpoint = endpoint + '&q=' + search;
            }
            endpoint = endpoint + '&page=' + page;
            $.ajax({
                type: 'GET',
                url: endpoint,
                success: success,
                error: error,
                complete: complete,
                dataType: 'json'
            });
        }

A thin wrapper around the AJAX API, which simply builds a URL and returns the results in the supplied callbacks.

Much like building a front controller, this was trivially easy, but it didn’t have to be – there’s other features we could add in here, the most important of which are cacheing and pagination. Rather than always using the server to handle pagination and fetching values from the server every time, it would be far, far better to prefetch large chunks of data from the server, and let the client model layer handle the caching. But because of the design of the QEDServer REST API, which only allows fetching of 10 records at a time, that would have been counter productive in this case. And cacheing server data on the client opens up the problem of currency – making sure that the client data and server data are in sync. This implementation mostly just hand-waves that away.

Pain Points

In my simple implementation, there really were no pain points, but as I mentioned, I’d hope that any client side Model layer would handle cacheing and pagination as well as offer some hints on how to implement data synchronization.

So, with the Model and Front Controller out of the way, it’s time to move into the View Layer, which presented far more problems. But first, we’ll detour into what capabilities Bootstrap provides.

Written by Jim Driscoll

January 25, 2014 at 11:44 AM

Posted in ajax, HTML5, REST, web

Progressive Enhancement with JSF

leave a comment »

Progressive Enhancement is a philosophy of web design – start with simple pages, and build them up based on the capabilities of the browser viewing the page. It’s related to (and in some ways, the opposite of) the idea of Graceful Degradation, starting with a nice, fancy page, and dealing with any browser faults in an elegant manner.

Prehaps the simplest example to see this in action is the case of JavaScript being disabled in the browser – this is occasionally true for certain corporate clients concerned about security, and sometimes the case for very old browsers.

JSF handles this usecase pretty well – consider the following code:

   1
   2 <f:ajax render="grace :text">
   3   <h:selectBooleanCheckbox value="#{grace.checked}"/>
   4 </f:ajax>
 

This creates a checkbox input with an onclick event handler registered. If there’s no JavaScript enabled, it will continue to function as thought the ajax tag wasn’t there at all. But the user will need to submit the form with a button press…

There is another way to handle this: we could instead create a link, which uses view parameters:

 

   1 <f:metadata>
   2     <f:viewParam name="checked" value="#{grace.checked}"/>
   3 </f:metadata>
   4 <h:link value="check me">
   5     <f:param name="checked" value="#{!grace.checked}"/>
   6 </h:link>

That works, but isn’t as clean looking as the first, ajax method. Combining these approachs should provide a better user experience – and doing so isn’t especially difficult:

   1 <f:metadata>
   2     <f:viewParam name="checked" value="#{grace.checked}"/>
   3 </f:metadata>
   4 <h:outputText id="text" value="Checked: #{grace.checked}"/>
   5 <h:form id="form">
   6     <h:panelGroup id="grace" layout="block">
   7         <h:panelGroup id="default">
   8             <h:link value="check me">
   9                 <f:param name="checked" value="#{!grace.checked}"/>
  10             </h:link>
  11         </h:panelGroup>
  12         <h:panelGroup id="enhanced" style="display: none">
  13             <f:ajax render="grace :text">
  14                 <h:selectBooleanCheckbox value="#{grace.checked}"/>
  15             </f:ajax>
  16         </h:panelGroup>
  17         <script type="text/javascript">
  18             var def = document.getElementById("form:default");
  19             var enh = document.getElementById("form:enhanced"); 
  20             def.style.display = "none";
  21             enh.style.display = "block";
  22         </script>
  23     </h:panelGroup>
  24 </h:form>

First, create two divs, one with the link and the other with the checkbox, which is hidden by default. If JavaScript is enabled, then hide the link and show the checkbox. This is the basic idea behind Progressive Enhancement – first, create something that you’ll be happy with in any browser, then add features (in this case, an Ajaxified checkbox) as needed.

That’s all for today. One personal note: Today is my last day officially employed by Sun Microsystems – I wasn’t offered a position at Oracle, and I’m currently actively looking for something. Please feel free to checkout my resume, and let me know if you know of any openings that you think might be a fit for me.

(This article originally published on my java.net blog on February 7, 2010.)

Written by Jim Driscoll

February 9, 2010 at 11:21 PM

Posted in ajax, JSF

Request aggregation in JSF 2 Ajax

leave a comment »

I’ve had a few requests for request aggregation, ala RichFaces queues, in JSF 2. This was deliberately not included in JSF 2.0, but it will be considered for JSF 2.1. The reason why is simple – there was simply not very much time, once all the base Ajax work was completed, to add any additional features. However, adding this functionality yourself isn’t actually very hard. Here’s an example of how.

For those not familiar with the idea of request aggregation, the idea is a pretty simple one: in cases where the user may generate a large number of requests (for instance, with the keyup event), you’re going to want to wait and see if you can bundle the requests together, so you don’t spam the server with thousands of tiny little requests.

The example will have two parts: a JSF page, and some backing JavaScript. The end result will be a program which accepts input, and echos it out to another part of the page via an Ajax request to the server. There’s also a status area to show a little of what’s going on during the call.

Here’s the form:

   1 <h:form id="form1" prependId="false">
   2     <h:outputScript name="jsf.js" library="javax.faces" target="head"/>
   3     <h:outputScript name="javascript/aggregate.js" target="head"/>
   4 
   5     Output: <h:outputText id="out1" value="#{echo.str}"/>
   6     <br/>
   7     Input: <h:inputText id="in2" value="#{echo.str}" autocomplete="off"
   8                         onkeyup="aggregate('out1 in1', this)"/>
   9     <br/>
  10     Status:
  11     <br/>
  12     <textarea id="status" rows="10" cols="50" readonly="readonly"/>
  13 </h:form>

And here’s the backing JavaScript:

   1 var increment = 1000; 
   2 var token;
   3 function aggregate(target, element) {
   4     window.clearTimeout(token);
   5     addStatusMessage("cleared request, requeued");
   6     var send = function send() {
   7         jsf.ajax.request(element, null, {render: target});
   8     };
   9     token = window.setTimeout(send, increment);
  10 }
  11 
  12 function addStatusMessage(message) {
  13     var statusElement = document.getElementById("status");
  14     var status = statusElement.value;
  15     var now = new Date();
  16     var timestamp = now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds();
  17     status = timestamp + ' ' + message + '\n' + status;
  18     statusElement.value = status;
  19 }
  20 
  21 jsf.ajax.addOnEvent(function(data) {
  22     if (data.status === "begin") {
  23         addStatusMessage("request sent");
  24     }
  25 });

This program is simple enough that it’s function should be pretty self evident – but in case you’ve never worked with JavaScript timers, here’s the control flow.

When you type a character into the input field, the aggregate function is called (JSF page line 8). If an outstanding request is already there, it will be canceled (JavaScript line 4), and a status message will be written (JavaScript lines 12-19) to a readonly textarea in the page (JSF page line 12). Then, a new request will be submitted, which will go off after 1 second (JavaScript line 9). If you type a new character before the second has elapsed, then the first request is canceled (JS line 4), before being submitted again with a new value (JS line 9). If a whole second goes by without a new keypress, then the request will finally be sent to the server, which will also trigger calling the event function (JS lines 21 – 24), which in turn writes out a status (JS lines 12-19), to the textarea (JSF line 12).

So, all told, the aggregation code was about 6 lines of JavaScript. And while that may be a trifle annoying, I can only assume that anyone writing a component like Autocomplete will include this into the component so you never need see it.

As always, feel free to ask questions on this post in the comments.

(This article originally published on my java.net blog on October 19, 2009.)

Written by Jim Driscoll

February 9, 2010 at 11:18 PM

Posted in ajax, JSF

JSF 2, Custom Java Components, and Ajax Behaviors

with one comment

Unlike most of my blog posts, where I try to describe the easiest possible way to do things, in this posting, I’ll instead go over a Java-based custom JSF component that responds to the Ajax tag. The reason being that there simply aren’t any examples out there of how to do this, and at least two people have expressed interest in finding exactly out how this is done. I’d advise anyone considering doing this to make really sure that you can’t do the same thing in a Composite Component (you usually can), but sometimes, a Java-based custom JSF component is going to be required.

We’re going to cover the following topics here, and it’s going to be a little more code than usual, but I suspect that this will end up saving some folks a bunch of time, so lets plow forward. I’ll cover:

  • Ajax listeners
  • Facelet components
  • Integrating the two

First, the Ajax Listener

An ajax listener, connected to your ajax event with the listener attribute, is a method that will be called every time the ajax request is made. For example, let’s look at the following page section:

   1 Echo test: <h:outputText id="out" value="#{custom.hello}"/>
   2 <br/>
   3 Echo count: <h:outputText id="count" value="#{custom.count}"/>
   4 <br/>
   5 <h:inputText id="in" value="#{custom.hello}" autocomplete="off">
   6     <f:ajax event="keyup" render="out count eventcount" listener="#{custom.update}"/>
   7 </h:inputText>
   8 <br/>
   9 Event count: <h:outputText id="eventcount" value="#{custom.eventCount}"/>

We’ve got three bean properties – hello (which is the string entered by the inputText), count (which is a count of the characters in hello, and eventCount (which is a count of the number of ajax requests). We also have a method on the bean, update (line 6), which will be called every time the ajax call is submitted.

The behavior of this page is pretty simple – every time you press a character in the inputText, the complete value of the input is echoed to the outputText "out" (line 1) – the length of "out" is written to "count" (line 3), and the "eventCount" outputText (line 9) has it’s value incremented by one.

So – what code is in the bean? Here’s the relevant bits:

 

   1 public void setHello(String hello) {
   2     this.hello = hello;
   3 }
   4 public int getCount() {
   5     return count;
   6 }
   7 public int getEventCount() {
   8     return eventCount;
   9 }
  10 public void update(AjaxBehaviorEvent event) {
  11     count = hello.length();
  12     eventCount++;
  13 }

 

Not so bad – the only thing new here is that AjaxBehaviorEvent class – and we’re not even using it. The update method will simply set up the values to be correct, and we let the Ajax render to the rest. So – listeners are easy.

 

Facelets Components

Now, we’ll want to create a custom tag in Java. To do that, we’ll need to make a few configuration file entries, and write a little java code. But first, let’s see it used in the page:

In the XHTML header, we’ll say:

   1 <html xmlns="http://www.w3.org/1999/xhtml"
   2       xmlns:ui="http://java.sun.com/jsf/facelets"
   3       xmlns:h="http://java.sun.com/jsf/html"
   4       xmlns:f="http://java.sun.com/jsf/core"
   5       xmlns:cu="http://javaserverfaces.dev.java.net/demo/custom-taglib">

Setting up the "cu" prefix (line 5) to point to "custom-taglib" (the whole URL is significant). Then later on in the page, we’ll use it like so:

<cu:custom id="customId">

We then need to add an entry in web.xml:

   1 <context-param>
   2    <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
   3    <param-value>/WEB-INF/custom-taglib.xml</param-value>
   4 </context-param>

This points to our next config file, which is the filename on line 3. Here’s its contents, in full:

   1 <facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee"
   2               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   3               xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
   4               version="2.0">
   5   <namespace>http://javaserverfaces.dev.java.net/demo/custom-taglib</namespace>
   6   <tag>
   7     <tag-name>custom</tag-name>
   8       <component>
   9         <component-type>mycustom</component-type>
  10       </component>
  11   </tag>
  12 </facelet-taglib>

Note that the namespace element on line 5 matches the URL we used for the namespace in the html element of the using page. We said this taglibrary will have one tag "custom" (line 7), which maps to the FacesComponent "mycustom". Where does it find the definition of "mycustom"? In the Java file defining the component, using the new @FacesComponent attribute. Here’s the full Java code, leaving out the imports:

   1 @FacesComponent(value = "mycustom")
   2 public class MyCustom extends UIComponentBase {
   3 
   4     @Override
   5     public String getFamily() {
   6         return "custom";
   7     }
   8 
   9     @Override
  10     public void encodeEnd(FacesContext context) throws IOException {
  11 
  12         ResponseWriter responseWriter = context.getResponseWriter();
  13         responseWriter.startElement("div", null);
  14         responseWriter.writeAttribute("id",getClientId(context),"id");
  15         responseWriter.writeAttribute("name", getClientId(context),"clientId");
  16         responseWriter.write("Howdy!");
  17         responseWriter.endElement("div");
  18     }
  19 }

In fact, the Java code itself is simple enough that I don’t really think it requires any explanation. Putting the cu:custom tag in your page will now render Howdy!, surrounded by a div with the same id and name as you gave the component. All that’s left is to add the Ajax. That… is a bit more complicated, but now that we’ve handled everything else, it’s really just incremental.

Using f:ajax with your custom tag

To use the f:ajax tag, we’d like to, for instance, do something like this:

   1 <cu:custom id="customId">
   2     <f:ajax render="eventcount" listener="#{custom.updateEventCount}"/>
   3 </cu:custom>

Meaning, we’d like to just decorate the tag, and let it do something "smart". In this case, we’ll default to "onclick" (since we’re dealing with a div, after all, we could also default to "onmouseover", for instance). It’d also be nice if we could still call the ajax listener. That’ll require a bit more code. Here’s the full Java component, with the additional ajax code. I’ll go over it at the end:

   1 @FacesComponent(value = "mycustom")
   2 public class MyCustom extends UIComponentBase implements ClientBehaviorHolder {
   3 
   4     @Override
   5     public String getFamily() {
   6         return "custom";
   7     }
   8 
   9     @Override
  10     public void encodeEnd(FacesContext context) throws IOException {
  11 
  12         ClientBehaviorContext behaviorContext =
  13                 ClientBehaviorContext.createClientBehaviorContext(context, 
  14                 this, "click", getClientId(context), null);
  15 
  16         ResponseWriter responseWriter = context.getResponseWriter();
  17         responseWriter.startElement("div", null);
  18         responseWriter.writeAttribute("id",getClientId(context),"id");
  19         responseWriter.writeAttribute("name", getClientId(context),"clientId");
  20         Map<String,List<ClientBehavior>> behaviors = getClientBehaviors();
  21         if (behaviors.containsKey("click") ) {
  22             String click = behaviors.get("click").get(0).getScript(behaviorContext);
  23             responseWriter.writeAttribute("onclick", click, null);
  24         }
  25         responseWriter.write("Click me!");
  26         responseWriter.endElement("div");
  27     }
  28 
  29     
  30     @Override
  31     public void decode(FacesContext context) {
  32         Map<String, List<ClientBehavior>> behaviors = getClientBehaviors();
  33         if (behaviors.isEmpty()) {
  34             return;
  35         }
  36 
  37         ExternalContext external = context.getExternalContext();
  38         Map<String, String> params = external.getRequestParameterMap();
  39         String behaviorEvent = params.get("javax.faces.behavior.event");
  40 
  41         if (behaviorEvent != null) {
  42             List<ClientBehavior> behaviorsForEvent = behaviors.get(behaviorEvent);
  43 
  44             if (behaviors.size() > 0) {
  45                 String behaviorSource = params.get("javax.faces.source");
  46                String clientId = getClientId(context);
  47                if (behaviorSource != null && behaviorSource.equals(clientId)) {
  48                    for (ClientBehavior behavior: behaviorsForEvent) {
  49                        behavior.decode(context, this);
  50                    }
  51                }
  52             }
  53         }
  54     }
  55 
  56     @Override
  57     public Collection<String> getEventNames() {
  58         return Arrays.asList("click");
  59     }
  60 
  61     @Override
  62     public String getDefaultEventName() {
  63         return "click";
  64     }
  65 }

At 65 lines, this is probably the longest code example I’ve ever posted, but most of this is either really easy, or stuff you’ve seen in the previous section. First, we define what Ajax events we’ll accept ("click") and what one is the default ("click" again), on lines 56-64. These are part of the ClientBehaviorHolder interface (line 2). We also had to add a little code to the encodeEnd method, so that we correctly output the DOM event script as part of the div (lines 12-14, 20-24). And lastly, we needed to add a decode method, since our component is no longer output only – the ajax event handling code is always part of the decode process (lines 31-50). This is the part where we actually make sure that that listener is being called.

Did I mention that you can do pretty much the same thing in a composite component?  That’ll be the subject of a future blog.

Well, I warned you this was a little more complex – hopefully it’s all fairly clear. If it isn’t – ask in the comments.

 

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

Written by Jim Driscoll

February 9, 2010 at 10:53 PM

Posted in ajax, JSF

Slides for JSF 2 and Ajax

leave a comment »

I’ve placed my slides for my JSF 2 and Ajax talk up on slideshare.

Check ‘em out, and ask questions in the comments.

(This article originally published on my java.net blog on October 5, 2009.)

Written by Jim Driscoll

February 9, 2010 at 10:47 PM

Posted in ajax, JSF

Mixing Ajax and full requests in JSF 2.0

leave a comment »

JSF 2.0 makes ajax pretty easy – but it can’t hide everything from you… It’s tempting to just add a few ajax tags into your page, and not worry too much about interactions – here’s one example of a problem you may run into.

Let’s say you’ve got a page with an input text, and a command button – like this:

   1 <h:form>
   2 <h:inputText value="#{blah.blah}">
   3 </h:inputText>
   4 <h:commandButton/>
   5 </h:form>

Now, we decide to add an ajax tag:

   1 <h:form>
   2 <h:inputText value="#{blah.blah}">
   3 <f:ajax event="blur"/>
   4 </h:inputText>
   5 <h:commandButton/>
   6 </h:form>

Can you spot what’s wrong with this example? When we push the button, we’re also blurring the inputText. That means that the ajax request is sent – but then, almost immediately, that request is canceled as the whole page is reloaded.

Is this a bad thing? For this simple example, not so much. There’s going to be a broken connection – and that can be a grim problem for a large server, especially if you start getting one on each page, for each use.

But the real issue is that you’ve just set up a race condition. Imagine instead you did this:

 

   1 <h:form>
   2 <h:inputText value="#{blah.blah}">
   3 <f:ajax event="blur" listener="#{bean.somethingthatchangesstate}"/>
   4 </h:inputText>
   5 <h:commandButton/>
   6 </h:form>

Now we’ve got a real problem from that race condition – did the listener execute? Maybe. Maybe is never a good answer in software.

So – what to do?

Probably the best solution is also the simplest:

   1 <h:form>
   2 <h:inputText value="#{blah.blah}">
   3 <f:ajax event="blur" listener="#{bean.somethingthatchangesstate}"/>
   4 </h:inputText>
   5 <h:commandButton>
   6 <f:ajax render="@form">
   7 </h:commandButton>
   8 </h:form>

Switching to ajax for the commandButton will now provide a predictable call sequence.

One more issue: When the two connections are submitted simultaneously, an error alert may be produced. I just updated that error to say: "The Http Transport returned a 0 status code. This is usually the result of mixing ajax and full requests. This is usually undesired, for both performance and data integrity reasons." What happens if you want to do this? Well, the error alert only shows up under two conditions, both of which must be true – the Project Stage must be Development, and there must be no error listener set. So, if you’re really sure you want to mix ajax and full requests, despite what I said above, just set up an error listener for your ajax code – you’ll want to anyway for a production environment.

As always, if you have questions, please ask in the comments.

(This article originally published on my java.net blog on October 2, 2009.)

Written by Jim Driscoll

February 9, 2010 at 10:32 PM

Posted in ajax, JSF

Ajax tag events and listeners

leave a comment »

Today we’re going to talk about two features of JSF 2.0′s f:ajax tag: the event attribute and the listener attribute.

The use of both of these is really, really simple – so I’ll just briefly cover the basics, and then launch directly into the sample code.

The “event” attribute of the ajax tag indicates which event to use to trigger the ajax request. There are any number of possible events allowed: You can use the standard browser DOM events (like click, change, keyup, etc. You can also use two special event values – action and valueChange. These two special values correspond to the same events that happen on the server side in JSF. On the client side, action is typically mapped to click, while valueChange is mapped to change or click, depending on the component.

The “listener” attribute of an ajax tag is a method that is called on the server side every time the ajax function happens on the client side. For instance, you could use this attribute to specify a server side function to call every time the user pressed a key – Handy, eh?

Anyhow, without further ado, let’s see how this works in a page. We’re going to detect every time the user lifts a key (the keyup event) – when that happens, we’ll run an ajax command which updates a counter, and refreshes an output field.

Here’s the using page:

   1 <?xml version='1.0' encoding='UTF-8' ?> 
   2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.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 
   7     <h:head><title>Ajax Tag Event and Listener Demo</title></h:head>
   8     <h:body>
   9         <h:form id="form">
  10             <br/>
  11             Echo test: <h:outputText id="out" value="#{listenBean.hello}"/>
  12             <br/>
  13             String Length: <h:outputText id="count" value="#{listenBean.length}"/>
  14             <br/>
  15             <h:inputText id="in" value="#{listenBean.hello}" autocomplete="off">
  16                 <f:ajax event="keyup" render="out count eventcount" listener="#{listenBean.update}"/>
  17             </h:inputText>
  18             <br/>
  19             Event count: <h:outputText id="eventcount" value="#{listenBean.eventCount}"/>
  20         </h:form>
  21 
  22     </h:body>
  23 </html>

As I said, we tag the inputText (line 15) with an ajax tag (line 16). That ajax tag listens for the keyup event – when such an event occurs, we send an ajax request to the server. That ajax request will run a listener method (listenBean.update), apply the new string value from the inputText (listenBean.hello), and then render out (line 11), count (line 13), and eventcount (line 19).

The bean itself is nothing special: here’s the example below:

   1 import javax.faces.bean.ManagedBean;
   2 import javax.faces.bean.ViewScoped;
   3 import javax.faces.event.AjaxBehaviorEvent;
   4 
   5 @ManagedBean(name="listenBean")
   6 @ViewScoped
   7 public class ListenBean {
   8 
   9     private String hello = "Hello";
  10 
  11     private int length = hello.length();
  12 
  13     private int eventCount = 0;
  14 
  15     public String getHello() {
  16         return hello;
  17     }
  18 
  19     public void setHello(String hello) {
  20         this.hello = hello;
  21     }
  22 
  23     public int getLength() {
  24         return length;
  25     }
  26 
  27     public int getEventCount() {
  28         return eventCount;
  29     }
  30 
  31     public void update(AjaxBehaviorEvent event) {
  32         length = hello.length();
  33         eventCount++;
  34     }
  35 }

So – questions? Ask below.

(This article originally published on my java.net blog on September 26, 2009.)

Written by Jim Driscoll

February 9, 2010 at 10:29 PM

Posted in ajax, JSF

Bridging to Open Ajax

leave a comment »

The Open Ajax Alliance is a standards organization with the mission of ensuring interoperability within Web based Ajaxified applications. One of their standards relates to intercomponent communication – the ability to subscribe and publish messages which can then be picked up by code written by other authors.

Please note that if you don’t have an interest in Open Ajax, this post may not be especially illuminating – I’ve talked about the addOnEvent function before, even recently.

To write an Open Ajax application, you need to subscribe to events, much like in JSF 2, by registering functions which act as listeners. For instance, suppose we had a field in our page that looked like this:

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

And we wanted to use this textarea to write out certain events that we’d like to track. I could then have this code in a JavaScript file:

   1 var statusUpdate = function statusUpdate(name, data) {
   2     var statusArea = document.getElementById("statusArea");
   3     var text = statusArea.value;
   4     text = text + "Name: "+data.source.id;
   5     if (name === "jsf.event") {
   6         text = text +" Event: "+data.status+"\n";
   7     } else if (name === "jsf.error") {  
   8         text = text + " Error: "+data.status+"\n";
   9     }
  10     statusArea.value = text;
  11 };
  12 
  13 OpenAjax.hub.subscribe("jsf.event",statusUpdate);
  14 OpenAjax.hub.subscribe("jsf.error",statusUpdate);

In this case, we’re subscribing to two channels – jsf.event and jsf.error, and calling the statusUpdate function when a message arrives on those channels.

So, where do those messages come from? Unlike JSF, the OpenAjax hub has a publish function, in addition to a subscribe function. By associating that publish function with a call to jsf.ajax.addOnEvent and jsf.ajax.addOnError, we can bridge between the two event systems – like this:

   1 var openajaxbridge = {};
   2 
   3 openajaxbridge.eventUpdate = function eventUpdate(data) {
   4     OpenAjax.hub.publish("jsf.event", data);
   5 };
   6 
   7 openajaxbridge.errorUpdate = function errorUpdate(data) {
   8     OpenAjax.hub.publish("jsf.error",data);
   9 };
  10 
  11 jsf.ajax.addOnEvent(openajaxbridge.eventUpdate);
  12 jsf.ajax.addOnError(openajaxbridge.errorUpdate);

As I said, this is a somewhat specialized topic, but I thought it worth mentioning. The full code of the demo, including putting it into a component, is in Project Mojarra’s source base, under the jsf-demo/OpenAjaxBridge directory.

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

Written by Jim Driscoll

February 9, 2010 at 10:08 PM

Posted in ajax, JSF

Busy status indicator with JSF 2

leave a comment »

I’ve had a few requests on how to write a busy status indicator – you know, the little spinning ball that’s there while an Ajax call is active, and which goes away once the request is complete. So, I spent about two hours today, and did just that – including putting it into a component so it’s reusable. As usual, it involved no Java, and only a minimal amount of JavaScript.

First, I needed an animated gif for a spinning image – there were a number at http://mentalized.net/activity-indicators – I just picked one. They’re all in the public domain, and there are other sites which offer similar animated gif spinners.

After that, I tried to imagine what it would look like in the using page. Something like this seemed appropriate:

   1 <html xmlns="http://www.w3.org/1999/xhtml"
   2       xmlns:ui="http://java.sun.com/jsf/facelets"
   3       xmlns:h="http://java.sun.com/jsf/html"
   4       xmlns:f="http://java.sun.com/jsf/core"
   5       xmlns:ez="http://java.sun.com/jsf/composite/busystatus">
   6 <h:head>
   7     <title>Busy Busy</title>
   8 </h:head>
   9 <h:body>
  10     <h:form id="busyForm">
  11         <h:inputText id="in" value="#{string.string}">
  12             <f:ajax render="out"/>
  13         </h:inputText><ez:busystatus id="busy" for="busyForm:in" /><br/>
  14         <h:outputText id="out" value="#{string.string}"/><br/>
  15         <h:commandButton type="button" value="Click Me"/>
  16     </h:form>
  17 </h:body>
  18 </html>

On line 13, you see a component, busystatus, with a single attribute, “for”, which is pointing at the rendered ID of the component I want to monitor. Otherwise, it’s a straightforward JSF Ajax app – Ajaxify the “in” component, write to the the “out” component. I had to use the rendered ID (busyForm:in) rather than the JSF id (in), because there was no easy way to do ID resolution inside the component, but we’ve had to deal with that often enough at this point that the difference shouldn’t be too confusing.

We’ll also have make sure that the Ajax request lasts long enough to visibly trigger the indicator – that’s as simple as adding a Thread.sleep(2000); to the setString method of the bean referenced by #{string}.

With that out of the way, let’s write the component. Here’s the composite component implementation section (the interface section just refers to the “for” attribute, so there’s nothing to see there):

   1 <h:outputScript name="jsf.js" library="javax.faces" target="head"/>
   2 <h:outputScript name="busystatus/busystatus.js" target="head"/>
   3 <script type="text/javascript">
   4     busystatusdemo.init("#{cc.clientId}", "#{cc.attrs.for}");
   5 </script>
   6 <span id="#{cc.clientId}" style="display:none;">
   7    <h:graphicImage id="busyindicator" height="15" width="15" name="busystatus/spinner3-greenie.gif"/>
   8 </span>

Line 1 loads the jsf.js library, if necessary. We’ll need it in the next file for listening to events – note that it’ll get loaded anyway, from any f:ajax tag we use, but it’s good practice to make sure that it’s loaded before we try to reference it. Line 2 will load the JavaScript we’ve written for this component. We could have just put the script inline in the composite component itself, but then we’d bloat the size of the page unnecessarily if we used this component more than once in the page. What works best for performance is going to vary on case by case basis, but since we’re trying to create a generally reusable component, this is probably the best way to do it. Lines 3 thru 5 call the init function for this component, which we’ll use to associate the component ID with the for attribute: this is the same trick we use for almost every Ajax component on this blog, so again, this shouldn’t be surprising.
Lines 6 thru 8 define a span wrapping an image. The span is initially set to be invisible with a style attribute, and we’ll make it visible via JavaScript calls once the ajax request is active. The image itself is loading the spinning animated gif as a resource – and it’s in the same resource library as the component itself.

So, to recap what’s happening in this file: We load the required scripts, run an initialization function, and set up an invisible span holding the image we’ll display later. Now, let’s examine the last file for this component, the busystatus.js file that holds the functions that’ll be doing all the work on the page:

   1 if (!window["busystatusdemo"]) {
   2     var busystatusdemo = {};
   3 }
   4 busystatusdemo.onStatusChange = function onStatusChange(data) {
   5     var status = data.status;
   6     var componentID = busystatusdemo[data.source.id];
   7     if (!componentID) {  // if there's no request to listen for this one component, then leave
   8         return;
   9     }
  10     var element = document.getElementById(componentID);
  11     if (status === "begin") { // turn on busy indicator
  12         element.style.display = "inline";
  13     } else {  // turn off busy indicator, on either "complete" or "success"
  14         element.style.display = "none";
  15     }
  16 };
  17 
  18 jsf.ajax.addOnEvent(busystatusdemo.onStatusChange);
  19 
  20 busystatusdemo.init =  function init(componentID, forValue) {
  21     busystatusdemo[forValue] = componentID;
  22 };

Three sections here: Lines 1 thru 3 set up the namespace. Lines 20 thru 22 are the initialization function that creates a map between the component and the for attribute. Let’s go over lines 4 thru 18, though, since that’s doing the interesting bit…

On line 18, we’re adding an event listener – after this call, whenever an event occurs, the onStatusChange function will be called with a single parameter. When that function is called, on lines 6 thru 10, we retrieve the id of the component that generated the event, and use it to look up the associated “for” value, and exit the function if there’s no associated “for” value. Then, lines 11 thru 15, we check whether we’re beginning the Ajax call, or ending it. If beginning, we display the gif – if ending, we hide the gif.

So, that’s our very simple busy component. But please note that this isn’t really done. For instance, by revealing and hiding the gif, we’re actually altering the layout of the page – there’s traditionally two different ways to deal with this: you can either swap between the animated gif and a blank, transparent gif of the same size, or use CSS to hardcode in the size of a span, which wraps the component that’s having it’s display set to none. Either would work, and both are really out of scope for this blog – my only goal for this blog was to just show you how to use the event to trigger changes that updated a status indicator.

As usual, you can find the code for this blog in the Project Mojarra codebase, under the jsf-demo/ajax-components directory.

Questions? Please ask in the comments section, and I’ll do my best to answer them.

UPDATE: Ed Burns, in the comments, recommends http://www.ajaxload.info as a great place for all your spinning gif needs.

(This article originally published on my java.net blog on September 2, 2009.)

Written by Jim Driscoll

February 9, 2010 at 10:07 PM

Posted in ajax, JSF

Inline Scripts with Mojarra

leave a comment »

A few weeks ago, I blogged about ways to execute scripts on the client which you were writing out from the server via Ajax.  By popular demand, the latest build of Mojarra now allows execution of inline scripts.

So, instead of having to either bundle code into an <eval> tag, or using an event to execute it later, you can now simply say something like:

<script type="text/javascript">alert("Hello there");</script>

right inside the rendered html.

You can also say something like:

<script type="text/javascript" src="file.js"></script>

And the script will be loaded as well.

This feature will (probably) be the next revision of the specification, but you should be able to use this feature without fear of compatability issues going forward – the specifcation’s Expert Group has already expressed their approval of including this.

(This article originally published on my java.net blog on September 2, 2009.)

Written by Jim Driscoll

February 9, 2010 at 10:05 PM

Posted in ajax, JSF

Follow

Get every new post delivered to your Inbox.

Join 411 other followers