Skip navigation
ANNOUNCEMENT: community.oracle.com is currently Read only due to planned upgrade until 29-Sep-2020 9:30 AM Pacific Time. Any changes made during Read only mode will be lost and will need to be re-entered when the application is back read/write.

Composite components are a great feature of JSF 2.0. The canonical example is a login component with fields for the username and password:

<mylib:login name="#{user.name}"
      password="#{user.password}"
      loginAction="#{user.login}"/>

http://www.ibm.com/developerworks/java/library/j-jsf2fu3/login.jpg

This has been well explained elsewhere. But here is what always baffled me. I want to have a composite date component, with three menus for day, month, and year.

But I want it to have a single value of typejava.util.Date, so I can use it like this:

<mylib:date value="#{user.birthDay}"/>

and not

<mylib:date day="#{user.birthDate}" month="#{user.birthMonth}" year="#{user.birthYear}"/>

Why do I care?

  • My classes aren't all made up of strings and numbers. I use objects when I can. My User class has a propertybirthDay of type java.util.Date. I don't want to write boring code to take dates apart and put them back together.
  • I want to use bean validation for the date property, with a @Past or@Future annotation.

I asked around and people told me that this couldn't be done with composite components—I'd have to write an actual custom component.

But, as I discovered, it is not so. With a small dose of knowledge of the JSF lifecycle, and the poorly documented technique of backing components, this is actually pretty easy. Here goes.

When you make a composite component, it is normally turned into a UINamingContainer that contains the child components in the implementation. But you can also force a different component to be used, provided

  • it implements the NamingContainer marker interface
  • its “family” is"javax.faces.NamingContainer" (don't ask...)

The easiest way of using your own component is to make a class whose name is libraryName.compositeComponentName, such asmylib.date. (It's a bit weird to have a lowercase class name, but that's the price to pay for “convention over configuration”.)

package mylib;
public class date extends UIInput implements NamingContainer { 
    public String getFamily() { return "javax.faces.NamingContainer"; }
    ...
}

Note that I extend UIInput and notUINamingContainer. In the world of JSF,UIInput is an “editable value holder”, a class that holds a value of an arbitrary type (not necessarily numbers or strings), and to which you can attach validators.

The JSF lifecycle starts out like this:

  • The HTTP request (doesn't actually have to be HTTP—in JSF, everything is pluggable) delivers name/value pairs
  • Each component can pick from the request what it wants in thedecode method and sets its submitted value
  • The submitted value is converted to the desired type (integer, date, whatever), becoming the converted value
  • If the converted value passes validation, it becomes thevalue of the component

For a composite component, the submitted value is a combination of the submitted values of the children. You could combine them by putting them into a map, but I simply say that the submitted value is the composite component:

public class date extends UIInput implements NamingContainer { 
    ...
    public Object getSubmittedValue() { return this; }
    ...
}

(If you don't override this method, the submitted value isnull, and that gets into a murky corner of processing that you want to avoid.)

The conversion from a bunch of values to a date happens ingetConvertedValue:

public class date extends UIInput implements NamingContainer { 
    ...
    protected Object getConvertedValue(FacesContext context, Object newSubmittedValue) {
        UIInput dayComponent = (UIInput) findComponent("day");
        UIInput monthComponent = (UIInput) findComponent("month");
        UIInput yearComponent = (UIInput) findComponent("year");
        int day = (Integer) dayComponent.getValue();
        int month = (Integer) monthComponent.getValue();
        int year = (Integer) yearComponent.getValue();
        if (isValidDate(day, month, year)) // helper method that checks for month lengths, leap years
           return new Date(year - 1900, month - 1, day);
        else 
           throw new ConverterException(new FacesMessage(...));
    }
    ...
}

This is very similar to the usual conversion action, except that I combine the values from multiple child components. (I attached ajavax.faces.Integer converter to each of the children so I don't have to convert the submitted strings to integers myself.)

That takes care of processing the input. On the rendering side, I just populate the children before rendering them:

public class date extends UIInput implements NamingContainer { 
    ...
    public void encodeBegin(FacesContext context) throws IOException {
        Date date = (Date) getValue();
        UIInput dayComponent = (UIInput) findComponent("day");
        UIInput monthComponent = (UIInput) findComponent("month");
        UIInput yearComponent = (UIInput) findComponent("year");
        dayComponent.setValue(date.getDate());
        monthComponent.setValue(date.getMonth() + 1);
        yearComponent.setValue(date.getYear() + 1900);
        super.encodeBegin(context);
    }
}

That's all. The same recipe works for any composite component that collects input for a complex data type.

Here is the code of a sample application that works out of the box in GlassFish 3 (but not in Tomcat). Note that the sample application uses the composite component as an input for java.util.Date. It works with bean validation without any effort on the developer's part.

The moral of this is:

  • The much maligned JSF lifecycle is actually pretty good. The decode/convert/validate order is what you need anyway, so why not have the framework manage it for you?
  • The much maligned generality of JSF is pretty good too. They could have said “With HTTP, what comes in is strings, so why not just work with strings?” But here we take advantage that the source and target of the conversion can be any type.
  • The declarative composite components that everyone raves about are great, but sometimes you've got to be able to add code. This blog shows you how to do it.

One nice thing about JSF 2.0 is that they have taken good ideas from elsewhere, such as the “project stage” concept from Rails. If you set the project stage to ”development”, you get detailed error and warning messages. If you set it to “production”, you get more aggressive caching. Better diagnostics or better performance? The choice is yours, and that is good.

There has been a bit of confusion about the default setting of the project stage. In the expert group's mailing list (which is open but sadly not yet archived—don't get me going...), I argued that the default should be “development”. After all, I am a developer :-)

Seriously, one of the legitimate criticisms of JSF has been that it had a bad out-of-box experience. Make one wrong move, and you get the stack trace from hell. If the default for the project stage is development, you get a nice web page with useful diagnostics (and can still look at the stack trace if you need it). It turns out that several members of the expert group thought that this was the agreed-upon default, but the spec says otherwise. Hopefully this can be fixed in a spec update.

It turns out that Ed Burns, the expert group lead, had fought a tireless fight to get other Java EE expert groups interested in supporting this concept. Yours truly couldn't have agreed more:

CH>  Absolutely. This is something that I have requested for years. An app
CH>  server is a development platform, not just a deployment platform.

Unfortunately, the servlet 3.0 expert group wasn't too keen on it, but us mere mortals may never know why. Ed responded:

Oh do I wish I could share the JSR-315 EG traffic on this topic with
you.  Perhaps you should be on the servlet EG.

No, I should not be on the servlet EG. I should just be able toread their discussions so that I can learn why they are right and I am wrong. To Ed's great credit, he worked hard to make JSR 314 discussions open, and I think it is about time that other JSRs get a clue. Come on—it's servlets, not secret skullduggery about patents and trade secrets...

In the meantime, I'll argue again that the Java EE platform is both a developer platform and a deployment platform, and hopefully some of you can support me in the blog comments.

Right now, expectations for a Java EE app server (or servlet runner) are pretty low. Of course, it needs to run a perfectly formed app, but it is ok to go in a corner and sulk if there is any error.

Can you imagine if the Java compiler worked that way? If you have no syntax error, you get a bunch of .class files. Otherwise, you get a stack trace. Or the JVM? If you have any runtime error, you'd just get a core dump. Oh wait, we've been there. With C++.

So, the point is that developers have the legitimate expectation that the platform makes every effort to pinpoint every error, giving the file name and line number when humanly possible. That's what the compiler does. That's what the JVM stack trace does. That's what Facelets does in JSF 2.

Sadly, if you have an error in a session bean or one of the (still too many) deployment artifacts, you get some mumbo-jumbo that is deeply nested somewhere in the logs. There is no mechanism for bringing these messages to the developer. NetBeans makes a valiant effort at scraping the logs, and sometimes it even succeeds. But when I talked to app server implementors, their response was uniformly “We don't want to slow down the app server”.

That's where the genius of the project stage comes in. Once you realize that the app server has two roles, it becomes ok to slow it down in the development stage and to coddle the developer. The JSF folks found that once they had this concept, they were eager to put it to use. Caching gets in the way of hot deployment—turn it off during development. In the development stage, a <h:messages/> element is automatically added to every page—a brilliant move because it lessens the frustration of a “stuck page”.

So, what's the harm of having an app server setting for the project stage? Initially, it might not get much love. But over time, app server implementors may well realize that they can do all sorts of things to make the developers' lot less dreary, and, looking at JSF, it is likely that they will rise to the challenge.

JSF 2 introduces an EL variable flash. Anything you set persists for one post-redirect-get cycle. (In contrast, anything in the request scope is gone after a redirect.) A typical use of the flash is for messages. A managed bean method might put a message in the flash,

ExternalContext.getFlash().put("warning", "Your password is about to expire");

Then the message can be displayed on the next page as

#{flash.warning}

That's handy—the message survives one redirect, and then it is gone.

But it also points to a weakness of the flash. It doesn't really fit into the managed bean model. Normally, I would put a message in a managed bean object, without using the JSF API. Then I'd use it as#{myPage.warning}. In the published uses of the flash, you always see unsightly code in which data are shoveled in or out of the flash.

Of course, I'd want the myPage bean to go away soon, and do so automatically. Maybe a CDI FlashScopeis in order, so that I can do

@Named @FlashScoped public class MyPage

There is a discussion about this on the Seam 3 board.

Similar to Rails, the JSF 2 flash allows you to keep an entry for another cycle, by using

#{flash.keep.key}

This way, you can carry data along a page flow. You can have a data entry page with

<h:inputTextArea value="#{flash.description}"/>

followed by a confirmation page with

#{flash.keep.description}

followed by another page that shovels the description into its final destination.

(When I first saw this, I stared at it for a long time, not being able to figure out from the documentation what was going on. I finally looked at the source and found that the getValue method has special handling for flash.keep. There is also special handling for flash.now, which apparently is just a synonym for requestScope, perhaps to make Rails developers feel at home?)

My head started hurting when I traced the behavior. It just doesn't feel like the JSF way. It seems to be so much easier to use CDI and have a

@Named @ConversationScoped Widget

with a description property. Then I can use#{widget.description} and end the conversation when I no longer need the widget.

Not only is is mentally simpler, it also works better. If you use flash, and your user opens two browser windows, the two windows interfere with another in ways that make my head hurt even more.

(NB. This morning, my wife checked our daughter's appointment on the Kaiser web site, and I mentally gasped when she opened another browser tab to check her own appointment at the same time, because, as she told me when I asked, the site is so slow. I wasn't sure if it was going to work, but it did. The site uses Struts, not JSF :-))

Another good option for a page flow is to turn inputs into view parameters of a request-scoped bean.

<f:metadata>
   <f:viewParam name="description" value="#{widget.description}"/>
</f:metadata>
 ...
<h:commandButton action="next?faces-redirect=true&includeViewParams=true"/>

(Don't ask why it is faces-redirect butincludeViewParams...)

This is all very politically correct, with REST and PRG, and it is also easy to reason about the behavior of your app. Multiple browser windows work fine.

Which is better? The REST way is easy to understand. You post to the confirmation page, and then post the same data again to the final page. There is no server-side state, and that makes it easy to test each page in isolation. But it is pretty tedious if your page contains lots of inputs. CDI takes the opposite approach and embraces server-side state as something that is your friend, provided of course that it is properly managed.

http://weblogs.java.net/blog/cayhorstmann/archive/winchester.jpeg

It is nice to know that JSF 2 supports two good ways of managing data in a page flow, both of which seem better than using the flash and are definitely worth learning. Is it worth figuring out the innermost and undocumented secrets of theflash? Maybe not? JSF has more nooks and crannies than the Winchester Mystery House, and I think the most effective way of using it is to stay away as many of them as I can.

A few weeks ago, Ed Burns posted a link to a blog on the JSF expert group mailing list, commenting “A nice one, but it doesn't mention JSF 2”. Ever the curmudgeon, I pointed out that it wasn't so nice that the blog's sample code used the JSF API in beans when it wasn't necessary—as does in fact a lot of sample code, even in the official Sun tutorials. Ed's response: “Cay, a blog comment by such an eminent citizen as yourself would certainly be noticed.” So, here is the curmudgeonly eminence's advice on how to stay away from the JSF API.

To set the stage, recall the basic mechanism by which JSF links the visual presentation with the application logic. JSF pages are composed of component tags that contain expressions in the oh-so-blandly named Expression Language (EL). For example,

<h:inputSecret value="{userBean.password}"/>

The class of the userBean object must have getters and setters for the password property:

@Named public class UserBean {
   public String getPassword() { ... }
   public void setPassword(String newValue) { ... }
   ...
}

Here, the property has the type String, and that is good. There is no coupling between the UserBean class and the JSF API. You can compile and run unit tests ofUserBean without having JSF around. You can even (gasp) switch to another view technology.

So, where do programmers go wrong? Mainly in these four areas:

  1. SelectItem
  2. Data tables
  3. UIComponent
  4. The @ManagedBean annotation

SelectItem

When you show a list of choices, by using radio buttons, checkboxes, listboxes, or dropdown menus, you need to provide a list of (label, value) pairs. Since Java lacks a pair type, the JSF API provides a class SelectItem that lets you specify an item's label, value, and a few other properties that aren't so useful. Your bean provides a read-only property of typeCollection<SelectItem> for the JSF component:

<h:selectOneRadio value="#{orderBean.topping}>
   <f:selectItems value="#{orderBean.toppingItems}"/>
</h:selectOneRadio>

@Named public class OrderBean {
   Collection<SelectItem> getToppingItems() { ... }
   ...
}

But to compile this OrderBean, you need the JSF API.

This coupling is easy to avoid. You can use aMap<String, Object> containing the labels and values. (Use a TreeMap if you want the labels in alphabetical order, a LinkedHashMap if you need some other order.)

With JSF 2.0, you can do even better. Expose aCollection<ToppingItem> and use a tag such as the following:

<f:selectItems value="#{orderBean.toppingItems}" 
   var="topping"
   itemLabel="#{topping.name}" 
   itemValue="#{topping.id}" />

You design the ToppingItem class in any way you like. The sample above assumes that the class hasgetName and getId methods.

Data Tables

You can bind a JSF data table to aCollection<RowData>, where RowDatais any type of your choice, or you can use theDataModel class in the JSF API. Why do people use aDataModel when it would be so much easier to just use a standard collection? There seems to be one compelling reason—locating the currently selected row in an action.

But you don't need the DataModel class for that. In JSF 1.2, you can use sPAL, which is admittedly a bit of a pain. JSF 2.0 is much better. Simply pass the row as a parameter to your action method.

<h:dataTable value="#{myData.rows}" var="row">
   <h:column>
      <h:commandLink action="#{myData.doSomething(row)}"/>
   </h:column>
  ...
</h:dataTable>

@Named public class MyData {
   public String doSomething(RowData row) {
      do something with row
      return ...;
   }
}

UIComponent

Some design tools (remember Java Studio Creator?) put all JSF components of a form into a bean, sometimes called the form's “backing bean”. This leads to very messy code, and it encourages application logic programmers to call all sorts of inappropriate UIComponentmethods. The UIComponent API is difficult for experts to understand, and it really should not be exposed to application programmers.

One reason you may have for poking around inUIComponent objects is multi-component validation. In that case, get busy and write a custom validator so that you can isolate this hokus-pokus from the rest of your application logic. In JSF 2.0, writing a custom validator isn't as bad as it used to be because the tag handling is so much simpler.

@ManagedBean

So, you managed to get all your beans disentangled from the JSF API, you can test them independently, and you are happy. Then you find that JSF 2.0 has another feature that is just too good to pass up: bean annotations that free you from the tedium offaces-config.xml. No more

<managed-bean>
  <managed-bean-name>user</managed-bean-name>
  <managed-bean-class>com.corejsf.UserBean</managed-bean-class>
  <managed-bean-scope>request</managed-bean-scope>
</managed-bean>

You just use an annotation:

@ManagedBean(name="user")
@RequestScoped
public class UserBean

Except, now you tied your bean once again to the JSF API. The annotations are defined in the javax.faces.beanpackage.

The solution is not to go back to the tedium offaces-config.xml, but instead to use CDI:

@Named("user")
@RequestScoped
public class UserBean

Ok, so why is this better? First off, @Named is a part of JSR 330, which is tiny and easily integrated in other tools. Of course, @RequestScoped is injavax.enterprise.context, which your test framework would need to support. CDI was built around the assumption that you will wire your beans together in different ways for testing and deployment, and it is just a matter of time before test frameworks buy into that. Or, if you are in a hurry and need to roll your own right now, it makes much more sense to invest in CDI than in JSF support.

 

Conclusion

One of the key ideas behind JSF is the separation of the visual presentation and the application logic. Admittedly, older versions of JSF have not always made this separation easy or intuitive, but JSF 2.0 changes that. With JSF 2.0, you should be able to write your bean classes without using the JSF API, leaving that API for authoring components. And, if you use composite components, you may never need to see the JSF API at all!