Jim Driscoll's Blog

Notes on Technology and the Web

Archive for February 2010

HTML5 Semantic Tags

with one comment

Over the weekend, I was reading Mark Pilgrim’s great book on HTML5 – and when I got to the part about the semantic tags, I thought it might be worth a quick mention.

In case you’ve missed out on HTML5 in general (and don’t want to take the time to read that book I linked above), the idea behind semantic tags is that many sites use div blocks to mark out the same kinds of content, over and over. Content like headers, footers, and nav bars. Changing straight <div> tags to tags like <header>, <footer>, and <nav> is granting these tags semantic meaning, hence the name – semantic tags.

Semantic tags are a great idea. They offer a lot advantages over plain vanilla divs, especially for screen readers… but support in IE is pretty broken… The essential problem is this: unlike all other major browsers, IE doesn’t know how to style unknown tags. So the following code won’t work:

 

<style>
    .border {
        border: solid black;
    }
</style>
...
<section class="border">test3</section>

Ah, I hear the more informed folks in the audience say, there exists a library to fix this problem: the HTML5 Shiv. You can use it like so:

 

<!--[if IE]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->

This simple script will allow styles to be placed on unknown tags in IE… So, that’s a good start, but there are a few problems with it. For one thing, it relies on JavaScript, so if JavaScript is disabled, your styling will fail catastrophically. Similarly, applying print styles may not work, since JavaScript won’t necessarily be run as part of the print process (note: I haven’t tested this fully, but that’s sure what it looks like in brief testing). There are reports that nesting seems to mess stuff up applying styles correctly, but my testing hasn’t found anything broken in this way that isn’t already broken in IE’s CSS support.

Of course, there is a way around even that: If you are running JSF or some other server side processing on your backend, you could do User Agent detection, and emit <div>’s to IE and the semantic tags to all other browsers. Then, by styling the tags solely with classes and ID’s, it should be possible to make something that gets around the client side issues. Here’s a section from a component that does just that.

 

@FacesComponent(value = "navtag")
public class NavTag extends UIComponentBase {
    
    @Override
    public void encodeBegin(FacesContext context) throws IOException {
        boolean isIE = false;
        UIComponent component = getCurrentComponent(context);
        String style = (String) component.getAttributes().get("style");
        String styleClass = (String) component.getAttributes().get("styleClass");
        ResponseWriter responseWriter = context.getResponseWriter();
        String ua = context.getExternalContext().getRequestHeaderMap().get("User-Agent");
        if (ua != null && ua.contains("MSIE") && !ua.contains("Opera")) {
            isIE = true;
        }
        if (isIE) {
            responseWriter.startElement("div", null);
        } else {
            responseWriter.startElement("nav", null);
        }
        responseWriter.writeAttribute("id", getClientId(context), "id");
        responseWriter.writeAttribute("name", getClientId(context), "clientId");
        if (styleClass != null) {
            responseWriter.writeAttribute("class", styleClass, "styleClass");
        }
        if (style != null) {
            responseWriter.writeAttribute("style", style, "style");
        }
    }

Should JSF add these tags to JSF 2.1? I’d love to hear your comments, below…

Written by jamesgdriscoll

February 9, 2010 at 11:23 PM

Posted in HTML5, JSF

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 jamesgdriscoll

February 9, 2010 at 11:21 PM

Posted in ajax, JSF

IE, Memory Management, and You

leave a comment »

In a recent blog, commenters took me to task for a perceived IE 6 memory leak. It wasn’t actually there (they were wrong), but in attempting to prove myself right, I found a couple of memory leaks under IE in JSF’s Ajax support. Since I just spent a week learning how all this functioned, I thought I’d set it down so that others could learn from my efforts.

Now, none of the information that I’ll present here is new – it’s been discussed among Ajax programmers for at least the last 4 years. If you’re a web guru, it’s likely that you’re not going to learn anything new here (thought I’d welcome any additional information and corrections). But at least a couple of the points I’ll illustrate below are either poorly communicated or misunderstood. I’ll include a number of links at the end of this article. There are also very significant differences between IE 8 (which mostly works), IE 7 (which is bad), and IE 6 (which is just awful). I’ll try to point out the differences as they matter for each.

Tools

First – use the right tool for the job: In order to spot leaks, you’ll need to download a tool that can detect them. By all accounts, sIEve is the way to go. It uses IE itself, and introspects to get it’s data. The UI is pretty primitive, but I can’t recommend it enough – it’s truely invaluable. Since it uses IE for it’s work, you’ll need to run it on a machine that has IE6 installed – presumably in a VM. You’ll also want to have it running on a machine that has IE 7 and IE 8 as well, just to be sure. XP fits nicely on a VM that runs on my Mac, and this is how I use it.

Cyclic Leak

Now that that’s out of the way, it’s time to talk about the very worst of the memory leaks in IE – the dreaded cyclic reference, which the commenters thought that I’d committed. Under certain conditions, IE 6 will “leak” DOM nodes, retaining them, and the javascript objects that point to them, until the browser is either shut down, or crashes entirely due to lack of memory. Ugh! To understand how this happens, you really only need to know two things:

  1. IE 6 (and 7!) reportedly has very primitive garbage collection using reference counting
  2. There are two memory spaces in IE, one for JavaScript, and the other for the DOM, and they don’t communicate well.

What could go wrong? Well, lots. The commenters thought that the rule was: A leak will occur if any reference is made in JavaScript to an element that isn’t eventually set to null. That’s close, but not quite correct. The real rule is: A leak will occur if the JavaScript code contains any reference to the DOM that isn’t released in some way, either by going out of scope or being explicitly unset.

When IE 6 sees a JavaScript variable that is pointing to something in the DOM (typically, an element or node), it will record that reference, and not collect it – even when you surf over to a new page. And the DOM won’t be collected, since there’s a reference to it from JavaScript. These two objects, and all the stuff that references them, will stick around until shutdown. In IE 7, the geniuses at Microsoft saw the bug, and said “Hey, I know how to fix that, let’s garbage collect everything when we leave the page.”. Nice improvement, but it still doesn’t fix the bug, since if you’re developing a page that is designed to be used for a long period of time (like many page-as-application apps are now), it’ll still crash the browser. Apparently, they saw the error of their ways eventually, since this behavior is no longer present in IE8. (All this is confirmed by my testing with sIEve.)

So, in the example that had in my previous blog, there was no memory leak, because the variable that pointed to the element eventually went out of scope. So – how to you create variables that don’t go out of scope? The easiest way is to put them in an object – this was the leak that I eventually found in JSF. The fix there was to null out the object manually. But there’s another, more insidious way to create an object – create a closure. That creates a function object implicitly under the window object, and that will never go out of scope. But the key thing to remember is that you need to be aware of when things go out of scope when coding in IE, and act accordingly.

But wait! There’s more

If that was the only problem, life would have been fairly easy for me the last week. But that’s not the only bug that the Web Wizards of Redmond chose to deliver to their unsuspecting consumers. There’s another bug in IE (again, only in IE 6 and 7 – IE 8 appears to have fixed it per my testing), which also leaks DOM nodes that aren’t cleaned up until you leave the page. Apparently, when the IE DOM receives a call from the removeChild or replaceChild functions, it doesn’t actually, err, remove the nodes. It just leaves them there, hanging around the DOM like party guests that don’t have the sense to leave after the host has started handing out coats. While these nodes will eventually be cleaned up when the user leaves the page, this still causes problems for page-as-app programs, as in the cyclic leak for IE 7, above. While the removeChild call is fairly notorious for this, I had to find out about replaceChild with my own testing (though I did find a few obscure references once I went looking for it).

That means that instead of saying node.parentNode.replaceChild(newNode, node), you instead should say something like: node.parentNode.insertBefore(newNode, node); deleteNode(node); (with an appropriate if statement for isIE(), and a deleteNode function that doesn’t use removeChild). And instead of saying node.parentNode.removeChild(node); you instead are reduced to coding something like: node.outerHTML = ”; (again, with browser check). Except that when you combine that with IE’s horrible problems with manipulating tables, it may fail. So instead, you’re probably better off with something like this:

 
                var temp = document.createElement('div');
                try {
                    temp.appendChild(node.parentNode.removeChild(node));
                    temp.innerHTML = ""; // Prevent leak in IE
                } catch (e) {
                    // at least we tried
                }
                deleteNode(temp);


Again, possibly with an isIE() check.

Hopefully you found this description of IE’s Memory “Management” useful. Here’s a few of the links that I used for research, that I found the most helpful.

As always, I look forward to any comments. Especially about this topic – I’m far from expert in this area.

UPDATE: John Resig just posted about a very interesting looking tool. Haven’t checked it out yet, but if it’s got him excited…

(This article originally published on my java.net blog on November 13, 2009.)

Written by jamesgdriscoll

February 9, 2010 at 11:19 PM

Posted in JavaScript, web

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 jamesgdriscoll

February 9, 2010 at 11:18 PM

Posted in ajax, JSF

Slides for JSF 2 up on Slideshare

leave a comment »

I’ve posted the slides for the talk that Andy Schwartz and I did at Oracle Open World up on Slideshare.

Check ’em out.

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

Written by jamesgdriscoll

February 9, 2010 at 11:14 PM

Posted in JSF

An (almost) comprehensive list of Web Components

leave a comment »

In talking with Andy Schwartz before our recent talk together at Oracle Open World, Andy mentioned that he’d like to see some new components make it in to JSF 2.1.

I’d like to see that too – but what new components? To aid the discussion, I thought it might be handy to make up a list of components that I think would be handy for JSF – but please, don’t take this as an endorsement of any particular component for inclusion into the spec. At best, I can see us adding only a handful, perhaps 3 or so. Still, once started, this kind of project becomes it’s own end – so I decided it might be good to publish such a list. Many of these components already exist in some form or another for JSF, or as a JavaScript Widget that could be wrapped in a JSF component – so most of them are available today.

Basic Html

Most of the basic HTML components are already well covered, but there would seem to be a little room for a few very basic components

  • File Upload
  • This is pretty basic – and Servlet 3.0 just added it.

  • Formatted i18n data
  • These can currently be done with converters and validators, but is there a better way?

    • Date entry/display
    • Time entry/display
    • Currency entry/display
  • Flat Tree
  • A very basic hierarchical data visualization component that has no JavaScript required.

  • Static Progress Status
  • A bar which indicates percent complete, a static version of the Ajax version below

  • SingleRowSelect
  • A radio button that works with a table.

  • HTML5
  • There’s new stuff coming up – should we start to care? IE is, as usual, the lone holdout.

Navigation

Components for navigating from one page to another.

  • Breadcrumb Trail
  • Almost standard on many sites now, a horizontal list, often limited to three deep, that allows you to backtrack through your history without the back button.

  • Navigation List
  • A fairly straightforward list of links that navigate to different pages in the site. Often put in a Navbar on the left of the page.

  • Navigation Tree
  • Like a Navigation List, but with hierarchical categories

Security

Components that deal with identity and authorization.

  • Java EE Login
  • This one would seem to be a no brainer, but it’s actually a bit hard to get right.

  • Logout
  • If you log in, you should be able to log out.

  • Register
  • Probably not possible in a fully reusable way, since Java EE doesn’t specify a standard registration API.

  • Forgotten Password/Username
  • Same problem as Register

  • Capcha
  • This would be very useful, but probably not amenable to standardization, since the robots keep getting smarter.

Simple Rich UI

  • Framebuster
  • The war between the framers and the framebusters means that this will be obsolete almost immedately on release, but it might be worthwhile to try.

  • Tabbed Pane
  • Basic Web component or rich component, depending on whether you use DHTML. Since DHTML is probably easier for the end user, it’s my preference to have it in this list.

  • Spinner
  • Increment an integer value by a set amount at the press of a button, or manually enter a number. Implemented as a demo in Mojarra 2.0.

  • Slider
  • Analog slider to choose a numeric value, or manually enter a value.

  • Calendar
  • Need to also include options to pick a date, or only a month, or even only pick a year. May be hard to do reusably, since styling matters so much. Wrapped a YUI Calendar widget as a component as a demo in Mojarra 2.0.

  • TimeSpinner
  • A special case of a spinner, for picking a time.

  • ColorPicker
  • A very special case, but easy to implement.

  • ModalWindow
  • Alert box.

  • ModalDialog
  • Alert box, with two or more buttons.

  • Popup Menu
  • FloatingWindow
  • A detached embedded window, that you can move around within the HTML frame or window that contains it. After a brief burst of popularity, I’ve seen usage drop off.

  • Tag Cloud
  • I’m frankly not convinced of the usefulness of this particular visualization, but many designers seem to love it.

  • TabularData
  • A table that’s modeled on a database set, rather than being explicitly bound to the HTML table. Would include sorting, at a minimum, and also probably reorder of rows. Maybe even filtering?

  • Menubar
  • Drop down menu bar. Many HI people hate them on the web.

  • CommandBar (icon button)
  • Essentially, a horizontal strip of buttons.

Filthy Rich UI

Really elaborate graphical components. Harder to do as a standard, since styling becomes so important.

  • Carosel
  • Like Apple’s cover flow, flip through a set of images to select one.

  • Accordian
  • Just because I’ve never seen it implemented well doesn’t mean it’s useless.

  • EditText (in place edit)
  • Easy to do, but hard to get right, I’ve implemented it as a demo in Mojarra 2.0.

  • Shuttle (Switch List)
  • Fairly common, I’ve implemented it as a demo in Mojarra 2.0.

  • ComboBox
  • Essentially a static version of the AutoSuggest component, below.

  • Collapsible Tree
  • Tomahawk has had a tree for years.

  • RichTextEdit
  • Several good JavaScript widgets exist for this functionality.

  • RSSReader
  • Update a page automaticially with the latest blog posts. Far more useful than you might first think, since many programs (like hudson, for instance) now export data as RSS.

  • Slideshow
  • A fairly complex JavaScript widget.

  • Lightbox
  • An incredibly complex JavaScript widget for organizing images.

  • Charting
  • Incredibly complex, and incredibly useful, this is probably best done as a completely separate software product. Some JavaScript widgets already exist, and some JSF components already support this…

Behaviors

Things that are probably best implemented as behaviors.

  • Tooltip
  • Probably almost trival to implement.

  • DragAndDrop
  • The opposite of trivial to implement, it could still be incredibly useful. Some support in various JSF component sets already.

  • Clientside Validation
  • A customer request since year 2000.

Ajax

  • AutoSuggest
  • The “shopping cart” of the Ajax world. Note that Andy is working on a demo that implements this as a behavior. Supported as a component in some JSF component sets.

  • Poll
  • Besides periodic updates, also handy for keeping sessions alive, and avoiding many cases of view expiration. Less necessary if we implement Comet, but probably still useful as simpler solution.

  • Map
  • Relying on an external service means that this is probably not suitable for standardization.

  • Progress Indicator
  • Progress of a server operation

  • Busy Status Indicator
  • Essentially a binary version of Progress Status

More?

I’m sure I’ve left some out – suggest more in the comments…

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

Written by jamesgdriscoll

February 9, 2010 at 11:13 PM

Posted in web

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 jamesgdriscoll

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 jamesgdriscoll

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 jamesgdriscoll

February 9, 2010 at 10:32 PM

Posted in ajax, JSF

JSF 2.0 Reminder: Project Stage

leave a comment »

Just a reminder that while you are developing a JSF 2.0 project, you really, really, really should enable the Development Project Stage. Doing this enables better error messages, including in the client side JavaScript, at the cost of some performance.

Enabling this is as simple as putting the below into your web.xml:

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

When going into production, simply change the project stage to Production, like so:

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

This will turn off some error messages, and emphasize performance.

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

Written by jamesgdriscoll

February 9, 2010 at 10:32 PM

Posted in JSF