The Source for Java Technology Collaboration
User: Password:



Jim Driscoll's Blog

Jim Driscoll Jim Driscoll has been at Sun for nearly nine years, ever since he joined JavaSoft to work on the Java Web Server and the first version of Servlets. At various times, he has been the manager of the J2EE RI, the Java Web Services Developer Pack, and a host of Open Source, web and XML projects that Sun has either participated in or led. His current job title is Manager, Project GlassFish. He lives and works in the southern part of the San Francisco Bay area.



A tale of two components (JSF2)

Posted by driscoll on July 03, 2009 at 12:44 PM | Permalink | Comments (0)

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.

Automatic compression of jsf.js

Posted by driscoll on July 03, 2009 at 10:45 AM | Permalink | Comments (1)

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>


Learning JSF 2

Posted by driscoll on June 17, 2009 at 06:07 PM | Permalink | Comments (5)

Not too long ago, I heard someone complain that the JSF tutorial wasn't ready yet. Now, that's not surprising - the tutorial writing process (for that matter, the book writing process) doesn't actually start until the spec is more or less final, and the implementation is at least Beta (meaning feature complete).

But that raises the question: Suppose you're eager to get started. How do you learn about JSF 2 before all the user-friendly books have been written?

I suggest you go about it the way I do - here's the resources that you can use now, while waiting for the books that will come out.

Read online articles and blogs: This is probably the most obvious suggestion, if you're already here - just paging backward in this blog will get you some good information. But that really only gives you a very limited set of examples.

Read the PDL docs: Here's one that surprises me - most folks don't seem to know that every standard tag is documented in the PDL Docs. While the language of these docs can be a little overspecific and dry, of all of the standard JSF documetation, I find this the most useful.

Read the JSDocs: Not a surprising is that most folks don't realize that we have a standard set of documentation for the JavaScript API for JSF. Again, it's a bit overspecific (it's written that way, in part, because it serves as formal specs in addition to docs), but it does have a lot of good information.

There's also the JavaDocs and the Spec itself, but if often difficult to find something in there unless you know what you're looking for, so instead I recommend you...

Check out the demos: Project Mojarra has a bunch of demo programs, and many of them are really, really simple examples of things you can do with JSF 2. There's also a fair bit of cruft in there, waiting for us to clean it up, but it's probably worth your while. I recommend checking out any demo with "basic" or "ajax" in it's name, as a start. To do this, of course, you'll have to check out the Project Mojarra Source Code (check in the directory marked "jsf-demo"), but that's not such a high bar - it's not necessary to build it to get something out of the demos.

And of course, most importantly:
Ask questions: There's the mail alias, webtier@dev.glassfish.java.net - which requires subscription, but you'll want to see other people's questions anyway. I promise you, the entire dev team reads that alias. There's the JSF Forum - where a lot of really savvy users hang out, helping each other. There's an IRC channel too, ##jsf at irc.freenode.net - where you'll often find folks from all over the JSF world.

So, to sum up, if you're a bit adventurous and ready to start right now, there's a lot of things that'll get you going. And the books will be along shortly, never fear.

UI Latency

Posted by driscoll on June 08, 2009 at 10:10 AM | Permalink | Comments (2)

One of the talks I attended at JavaOne was Ben Galbraith speaking on UI design. While not a blockbuster talk, there was a lot of good information in there.

Perhaps the most surprising was the topic of UI latency. I'd always heard that 200ms was about the "twitch-time" number, where a UI would start to feel significantly sluggish - this was the number that used to be bandied about on gaming sites 10 years ago.

It had never occured to me to test this thesis though - and that's the difference between someone like me and someone like Ben.

Ben put up a series of buttons on a web page with programmed latencies in increments of 50ms. His findings? 100ms is noticeable, and 200ms is the line for "sluggish". So, while 200ms remains the cutoff for "bad", 100ms would seem to be the cutoff for "good". Oh great, my target time just got cut in half.

Ajaxian has a writeup of this portion of the talk, check it out.

And don't forget that you can easily test this yourself, with a little bit of onclick and setTimeout.



Slides to my JSF 2 components and Ajax BOF

Posted by driscoll on June 04, 2009 at 12:15 PM | Permalink | Comments (5)

Last night, Ryan Lubke and I gave a BOF on creating components with JSF 2. If you've been reading my blogs, none of this will be especially new, but I did think that you might appreciate the slides, which I've now uploaded and are available in OpenOffice 3 and PDF versions. The OpenOffice version has the slide notes, which you might find helpful. Still missing is the code that Ryan did last night, demonstrating, among other things, the use of the ajax tag's listener attribute - which is pretty neat. Ryan will probably blog on it shortly.

Another David Geary article on JSF 2

Posted by driscoll on June 02, 2009 at 09:58 PM | Permalink | Comments (0)

David Geary has released the second of his three part series on JSF 2. You can find it here.

He covers templating and composite components, and as usual, does a very readable and thorough job - check it out.

JavaOne Party Planner

Posted by driscoll on May 29, 2009 at 10:48 PM | Permalink | Comments (2)

I'm not sure how I got this job, but apparently I'm supposed to find all the JavaOne parties.

This year was harder, and it seems there will be very few opportunities to cage free drinks from eager PR people. Oh well, I intended to go to a lot of BOFs anyway.

So, here's the skinny on parties, feel free to add any I don't know about in the comments section, below:

Sunday

As part of the GlassFish Unconference, there will be a small, low key party at the Thirsty Bear. 7pm-10pm, with some drinks and some food. I went last year, and it was fun to talk with folks about my beloved GlassFish. RSVP is requested, and don't forget to go to the Unconference, party or no... It was a lot of fun last year, and it's free.

Monday:

As part of the CommunityOne West conference, there will be a party in Hall A from 7pm-9pm. Sponsored by OpenSolaris. Moscone catering isn't usually too bad. Couldn't find much other info about it, though.

Also - Pavilion Reception, Monday, 6:00 p.m. - 7:00 p.m. At the Pavilion. Presumably for all CommunityOne West attendees.

Tuesday:

Welcome Reception, Tuesday, 6:00 p.m. - 7:30 p.m. in the Pavilion. Free finger food and cold beverages. Usually a big crowd.

JCP Party - Intercontinental Hotel, 4th floor. 7-10 Registration required. This is a party for all those involved in the JCP, both as members and participants. Usually a fun party, with lots of free refreshments, and fingerfood.

Wednesday:

5-9pm, Caucho, Chevvy's, registration required.
No idea about this one, but if it's at Chevvy's there will be margaritas. Wouldn't you rather come see my BOF instead? OK, maybe not.

5-7pm, Java EE Sneak Peek, by invitation only. Invites available at the Java EE and GlassFish booth in the Sun pavillion. The website link promises food, drink, and spec leads... What JavaOne is all about, right? Sounds like geeky, low key fun.

Thursday:

6-8pm, JBoss, Jillian's, registration required, and online reg capped at 100. http://www.jboss.org/events/javaoneparty.html They've thrown good parties in the past - although I've heard mixed reviews on occasion. Probably they'll allow registration at their Pavillion booth after the online reg caps out, but no reference to that on their website.

7-9pm, After Dark, Yerba Beuna Gardens, cover band, cash bar. Some people still love this party, and I am still sorry I missed out on seeing the Mythbusters last year (or was that two years ago?).

Have fun at JavaOne - and again, if you know of any other parties, leave a comment below. And don't forget - the best part of the conference is the people you meet, so don't be shy - they don't know anyone either.

Update

Update: the afterdark party is now inside, with Free Drinks (limit 2 per person). Here's the text:

Dude, It Might Rain, So We're Taking It Inside
After Dark Bash Venue Change
The Marriott
4th and Mission
Thursday, June 4
7:00 p.m. – 9:00 p.m. (Doors open at 6:30 p.m.)

Enjoy an assortment of complimentary food and beverages (two drink tickets per person). Pick up your drink tickets Thursday at registration between 7:00 a.m. and 7:00 p.m. You must show your Conference or Pavilion Pass to be admitted to the party. Have fun!



Have you seen JSF lately? (Part 3)

Posted by driscoll on May 29, 2009 at 03:32 PM | Permalink | Comments (0)

Continuing our look at the improvements of the new JSF spec - see previous blogs here and here.

While JSPs are widely used and understood, their use in JSF has always been controversial. But love it or hate it, it's always been true that JSPs never quite fit in with JSF, and there were always some rough edges around where the two technologies fit together. All that's changed with JSF 2, since it uses the widely loved Facelets technology as it's primary page language. In fact, while you can still use JavaServer Pages for all of the pages written for JSF 1.2, to get the full use of JSF 2 features, you'll need to author pages in Facelets.

There's plenty of writeups for Facelets on the web already, as well as books or chapters of books on the topic, so I won't make this into a little miniature tutorial on Facelets, but it's probably worth hitting this one high point:

Templating is easy with Facelets

To create a template page, you code up a standard xhtml page with a html element that looks like this:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
Then, use that ui namespace to define regions in the page, using the <ui:insert> tag, like so:

<head>
  <title><ui:insert name="title">Default title</ui:insert></title>
</head>

If we put that into a file called template.xhtml, then we can call it with the following code, using the <ui:composition> tag.

<ui:composition template="template.xhtml">
  <ui:define name="title">I like templates</ui:define>
</ui:composition>

There are lots of subtleties here that I'm not covering, but you get the idea. Combine this with the ease of making new components via the composite component feature I mentioned earlier, and you can see that this is a pretty powerful way to handle serving web pages from composite parts.

One more note on Facelets: One book that comes highly recommended to me (though I've not read it myself), is Bruno Aranda's book. I'm told it covers the technology throughly.

So, far in this series I've covered Ajax support, component creation, templating with Facelets, and annotations. But the one question I always get is "what about Bookmarkable links?". Usually, the person asking is condensing a few issues into that one question, and it all comes down to GET vs POST.

After configuration files, perhaps the most common complaint about JSF is that everything is done via POST. This complaint is usually driven by a few points, some of which overlap - POST requests don't get cached (since they don't offer what's called idempotency, or the ability to get the same result from two identical requests). Also, POST requests cannot be bookmarked, and they often cause the browser to ask you awkward questions when you use the "back" button.

Now, JSF uses POST for a few reasons. For one, the limit on the size of GET requests (more than 2000 characters may fail in some situations - and those situations are mostly beyond your control). POST (with the generated view id's embedded by JSF) offers some minor security benefits as well, since it's more laborious to spoof requests (though a determined person can always get through). There's also the problem that the framework doesn't know when you intend a screen to be idempotent (i.e., repeatable) and when you don't. But, good news:

There's good support for GET in JSF 2

Ryan Lubke just published a really good description of how this works. I urge you to read through it to see the details, but the upshot of it is two new tags: <h:link> and <button>. You'll need to manually put the parameters that you want to pass onto these tags (remember that 2000 character limit? It hasn't gone away.), but once done, you'll have tags that redirect you from one page to another via GET instead of POST, with all the advantages of cacheing and a bookmarkable URL. But ensuring that your pages are idempotent is now up to you.

So, have you seen JSF lately?

Hopefully you've stayed with me this far, and you've seen that there's good reason to be excited about the new JSF 2. It'll be here sooner than you think, and there's no reason to not give it a try. You can get the latest beta from the Project Mojarra website, in the downloads section.

Have you seen JSF lately? (Part 2)

Posted by driscoll on May 28, 2009 at 12:30 PM | Permalink | Comments (0)

Continuing our look at JSF (see previous blog here), one of the biggest complaints about JSF is the Lifecycle. And it's not hard to understand why - here you are, just about to write a Hello World application, and the folks who wrote the documentation hit you with something that looks like this:

JSF Lifecycle

Wow. Looks complicated. But really, for many tasks, you don't need to know most of this, and that's more true with JSF 2 than ever. (I'll go over a cheat sheet of what you really need to know later.)

The main reason you as a developer would need to understand the Lifecycle is to develop your own components. And that's one place where JSF really used to fall short - for years, there were a very limited number of components, forcing you as often as not to write your own. And once you did, you were neck deep in lifecycle issues, making component writing difficult.

So, some good news:

There's lots of JSF components already available

There's several places you can go to get lists of components, but I like JSF Central's list. And unlike a lot of my other points about JSF, these component libraries are available today, usable in production immediately, without having to wait for the next release.

Lots of JSF component libraries support Ajax functionality

There's also lots of component libraries which already support Ajax today, and that support works just fine in JSF 2. The three most popular are probably Apache Trinidad, JBoss RichFaces, and ICEfaces. All of these frameworks are also diligently working on moving to JSF 2, as my colleague Roger Kitain recently blogged.

Writing components is now much, much easier

In fact, dare I say it? It's now easy. At least, for most common cases. JSF 2 has the idea of composite components, which is a templating approach to component creation. I outlined the basics in a blog some time ago, it's pretty simple, and doesn't require any knowledge of the lifecycle to implement - or even any knowledge of the underlying Java classes, for that matter. Just patch together a few existing components into an xhtml page - no more writing JSP tag handlers either.

As a quick example, here's how you could create a text field component that always has a yellow background:

<composite:interface>
    <composite:attribute name="value" required="false"/>
</composite:interface>

<composite:implementation>
    <h:outputText value="#{compositeComponent.attrs.value}"
        style="background-color: yellow"/>
</composite:implementation>

And using it is as simple as saying <ez:out value="Test Value"/> . It really doesn't get a lot easier than that.

What you need to know about the JSF lifecycle

So, if you don't need to know that complex lifecycle, what is it you do need to know? You need to know that when JSF first receives a page, it validates it - that can be either because you put a validator on a field, or because you said the field was required. Then, if all validations pass, it applies the new values into your backing beans. If validations fail, you don't get those values applied - the old page is sent back to the client, with an error message. Once those values are applied to the beans, any value change events you coded are set off, after which the whole response page is sent back to the client. Put this way, is the JSF lifecycle really so daunting? In practice, the only time I see folks get hung up is on the part where if validations fail, the values aren't set.

More in the next installment.



Have you seen JSF lately? (Part 1)

Posted by driscoll on May 27, 2009 at 06:40 PM | Permalink | Comments (0)

One of the most persistent annoyances in working on JSF is the pervasiveness of old information, usually from years ago, and often now inaccurate. Google ranks the JSF 1.1 tutorial over the JSF 1.2 tutorial... One Tweet I recently read referred to a Joe Ottinger blog from 2007 - over 2 years ago. Yet it was referenced as new information. Still another blog I recently read contained information and quotes from 2004. John Kerry was still a candidate for President (Heck, Howard Dean was still a candidate for President), folks still thought housing was a great investment, and Brittany was ripping up the charts with her new hit "Toxic". Ronald Reagan and Yasser Arafat were both still alive. That's a pretty long time ago.

So, to those people (and to the rest of you, as well), I'd simply like to ask: have you seen JSF lately?

The JSF 2.0 spec is going to final ballot as I write this, and we've been working on the implementation of that spec for over a year now. That implementation is now beta, and will be out as FCS before the end of the year. It's time to take a new look. If you don't, you're cheating yourself.

So, if you haven't looked at JSF lately, I'd like to use this series of blogs (three, I think) to look at things that folks used to complain about WRT JSF, and what the new JSF 2 standard does that addresses those complaints.

Here's the first one:

Configuration files.

I admit it, I never liked the idea of separating out configuration from implementation - either in the main line of J2EE, or in JSF. Sure, it's useful in some cases, but certainly not the common case. With the new Annotation support, the need for configuration files (mostly) disappears.

The new JSF specification practices the "DRY" principle (Don't Repeat Yourself). One application of this is for Managed Beans. If you have to take the time to write a Managed Bean java class, why should you have to take any additional action to tell the system, “hey, see this Java class here? This is a managed bean.”

So, instead of creating a configuration file to declare your managed bean, you can instead just use the @ManagedBean annotation at the top, and it's added to your application. Want it scoped to a session? Add @SessionScoped. (You can see the JavaDocs for these annotations on the Project Mojarra site, or as part of the spec download). Similarly, to navigate from one page to another, it used to be necessary to add a bunch of wordy and cryptic "navigation-rule" elements. No more. Now, a reference of action="page2" inside a button or a link will just take you to page2.xhtml, no muss, no fuss, no bother.

That's not to say that configuration files have gone away - you can still use them, such as for a large site with a complicated navigation map. Some people would prefer that the navigation be all in one spot for that use case. There's also some things you still must use configuration files for, such as taking a Bean class and creating two different named managed Beans from that class - adding the annotations to do that would have just made the wording awkward to handle such a corner case.

But for most applications, we think that you won't need very much in a configuration file, if anything at all.

And since that didn't take long, here's a second, about Ajax support:

One place where a component based architecture like JSF can really come in handy is when you want to abstract away some really tricky bits of code, and hide them from the rest of the page's architecture. If there was ever a great use case for that idea, it's Ajax.

Ajax support is fully integrated into JSF 2

I've already written quite a few blogs on Ajax support, as well as integrating it into the new component features, so I won't go into this aspect of JSF 2 too much. But just to hit the highlights, you can now Ajax enable a standard component simply by wrapping it in an <f:ajax> tag. All the variables in the page can thus be modified via this new Ajax tag, just as if you had done a full page submit.

For example: say you have a form that looks like this:

<h:form>
	<h:outputText id="out" value="#{bean.foo}"/>
		<h:commandButton id="button" value="Press me" 
				actionListener="#{bean.doSomething}">
			<f:ajax execute="@this" render="out"/>
		</h:commandButton>
</h:form>

Now, when you press the button, an ajax request is sent which executes the doSomething method on the server, and changes the value of the "out" text to match what's on the server. All without a single line of JavaScript written by the user.

More in the next installment.



A final look at the Switchlist JSF 2 component

Posted by driscoll on May 26, 2009 at 06:19 PM | Permalink | Comments (4)

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="#{listholder1}" target="#{switchlistController.listHolder1}"/>
            <f:setPropertyActionListener value="#{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="#{listholder1}" target="#{switchlistController.listHolder1}"/>
            <f:setPropertyActionListener value="#{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.

JSF 2 Beta 1 release

Posted by driscoll on May 26, 2009 at 04:07 PM | Permalink | Comments (0)

The Mojarra team are proud to announce the release of our Beta version of Mojarra 2.0, implementing the PFD version of the JavaServer Faces 2.0 spec.

You can find it on our downloads page, as well as in the GlassFish Update Center. And as always, be sure to check the release notes for more information.

IntelliJ Maia ships EAP, supports JSF2

Posted by driscoll on May 26, 2009 at 10:46 AM | Permalink | Comments (0)

As I mentioned in my previous blog, the guys over at IntelliJ are working hard on getting Java EE 6 support in, including JSF 2. It's now available as part of an Early Access Program, and is available for download. As a very early release, so expect bugs - but this is still exciting news.

Using an IDE to write a JSF 2.0 App

Posted by driscoll on May 18, 2009 at 09:40 AM | Permalink | Comments (10)

So, you're on the cutting edge, writing JSF 2.0 applications, but you just get tired of jkl; editing in vi... You can still do JSF 2.0 applications using your IDE, but the price is that you won't have some of the on the fly error checking (especially in your Facelets page).

First, a little about the status of various support efforts - unfortunately, tools support will lag for JSF 2.0, just as it has in other major releases.

I've checked on three different IDEs -

  • IntelliJ
  • IntelliJ looks to be doing some very interesting work on JSF 2.0 support, which is unfortunately not publicly available yet - it'll be in Maia, the codename for their next release. You can use the current rev of IntelliJ with JSF 2.0, but you'll get a death of a thousand red squiggles. The good news is that although Maia's release date isn't announced, it appears likely that some sort of early access will be available by JavaOne - but I don't know anything secret, I'm just reading their forums and blogs, so take that prediction for what it is - a guess. I'll blog more once they've made a public release.
  • NetBeans
  • NetBeans 6.7 won't have EE 6 support, unfortunately, but they do seem to be integrating what had been an unsupported Facelets plugin into their main line of code - Facelets support is available in their update center as a download. However, this is for Facelets support as a JSF 1.2 addon - it gives an error if you try to use it with JSF 2.0. So, it seems like we'll have to wait for NetBeans.next to really have good JSF 2.0 support - but you can use it now, since NetBeans relies on the libraries bundled in your app server for compilation - you just won't have the GUI sugar that you might want when developing your Facelets XHTML page. See below.
  • Eclipse
  • Facelets support was dropped from the Galileo release of Eclipse - it was bumped until the next release, which should happen at around the same time that the rest of Eclipse gets EE 6 support. This puts Eclipse at about the same place as NetBeans, leaving you with something that you can use to edit and compile, but missing code completion and any meaningful debugging support.

I'll run through using both Eclipse and NetBeans with JSF 2.0, but first, a word about what you'll get when you're done - you'll have a nice GUI editor that handles the JSF 2.0 Java classes just fine, but will treat the XHTML as simple XHTML, without knowing any of the Facelets content. So, it'll tell you if you've mismatched a tag, but if you misspell, for instance, h:commandButton as h:commandbuttn, it's up to the server to tell you that when you view the page. Better support will be forthcoming, as I mentioned above, but for now you'll have to be patient.

Also, I'm hardly an expert at either platform, so for those of you who are, comments and suggestions are always welcome.

Instructions for Using Eclipse with JSF 2.0

First, go download a version of Eclipse that bundles GlassFish, or some other server that supports JSF 2.0.

From that page:

The product distributions contain Eclipse IDE 3.4.1 Java EE IDE, preconfigured GlassFish Server v2.1 and GlassFish Server v3 Prelude and optionally a J2SE 6 1.6.0_12. The Mac OS installer is not available with JDK.

Install and launch it.

Alternatively, you can use your existing Eclipse 3.4 Ganymede installation and get the GlassFish plugin for Eclipse. Read these instructions to find out how.

To create the project:

File ... New ... Dynamic Web Project

Opens a Wizard.

Project Name: JSF 2.0 Test

Target Runtime: push "New" button, choose Glassfish V3 PROMOTED
Make sure that the "Create a new local Server" box is checked, and click "Next" (these instructions assume you'll be installing a new version of GlassFish. If you already have a version with JSF 2.0, you should be able to figure out which parts are different easily enough.)

Choose your VM (on my Mac, it was the default 1.6)
Enter the name of an empty directory where you want to install the promoted build of GlassFish v3. Click "Install Server". Accept the license at the pop-up, and click "Finish". The server will then install.
Click "Next".

The next page, you should be able to just accept all the defaults. Click "Finish". You've now configured your Target Runtime to be something that supports JSF 2.0.

Since the rest of the values that you need are all the defaults, you can go ahead and click "Finish" again". In particular, you don't need to select the "JSF" runtime configuration - since you won't really be using the faces-config.xml file, anyway - since for most uses, it isn't necessary for JSF 2.0.

Your Project is now set up.

You should know what to do next - create a JSF 2.0 app. You can delete the index.jsp page, and fill in with a bunch of xhtml files... The Eclipse IDE knows about the new JSF 2.0 APIs, since by default it uses the API jars bundled into the server. Here's an example of a project file structure that I did that worked, just so you can see what files you'll have to change.

Instructions for Using Netbeans with JSF 2.0

You'll need to download the latest NetBeans Nightly Build (no, Beta won't do, since that has a few showstopper bugs for our use).

You'll also need the latest release of GlassFish v3 nightly. (Remember, you're cutting edge, right?) If you're just going after JSF 2.0, though, you could always just use GlassFish v3 Prelude updated to the latest Mojarra release, as described in the release notes.

If you're using GlassFish v3, then you'll need to add the plugin to make that work.

Once all that's done, it's easy - just create a standard JSF project, using the v3 server that you downloaded, just like any other JSF project that you create. You'll need to delete the faces-config.xml file, and change the web.xml file a bit, but like in Eclipse, the server acts as the repository for the requisite APIs. I've attached a sample file to the blog so you can see an example to work from.

JSF 2: Ajax Events and Errors

Posted by driscoll on May 15, 2009 at 04:06 PM | Permalink | Comments (2)

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.

Redirecting from a JSF 2.0 Ajax Request

Posted by driscoll on May 14, 2009 at 07:04 PM | Permalink | Comments (3)

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.

New David Geary Article on JSF 2

Posted by driscoll on May 13, 2009 at 10:34 AM | Permalink | Comments (0)

Just wanted to let everyone know that there's a new article by the esteemed David Geary on JSF 2. Just wanted everyone to know about it - it's the first of the series, and it's really, really good.

July 2009
Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  


Search this blog:
  

Categories
Community: Glassfish
Community: Java Enterprise
J2EE
JavaOne
Linux
Open Source
Tools
Web Applications
Archives

July 2009
June 2009
May 2009
February 2009
January 2009
December 2008
November 2008
October 2008
August 2008
June 2008
May 2008
March 2008
February 2008
September 2006
July 2006
May 2006
December 2005
October 2005
July 2005
June 2005

Recent Entries

A tale of two components (JSF2)

Automatic compression of jsf.js

Learning JSF 2



Powered by
Movable Type 3.01D


 Feed java.net RSS Feeds