blog.smart-java.nl
Ordina J-Technologies – Java Blog

Archief ‘JavaServer Faces’ categorie




JSF 2.0 ClientBehavior: First impressions

Door: Jan-Kees van Andel, 19 March 2010

In my previous article, I wrote about my first real JSF 2.0 ClientBehavior, called ValidateBeanBehavior.

While programming, I’ve experienced some issues that, in my opinion, make the ClientBehavior less usable in many cases.

Events
A ClientBehavior is attached to a component, both on the server side and on the client side. On the client side, this simply means that an event listener is attached to an HTML element. The event listener then contains the scripts generated by the ClientBehavior.

For example, the generated JavaScript of ValidateBeanBehavior looks like this in the browser.

Do you see the onclick handler on my submit button? This is the ClientBehavior at work. I’ve attached the ClientBehavior to my submit button and you can see what it looks like in the snippet above.

Looks nice, not? No, it doesn’t. You shouldn’t use onclick for validations. Why not? Because the behavior of onclick differs between browsers with regards to form submits. For example, many users use ENTER to ‘implicitly submit’ the form. Different browsers behave differently on such implicit submits, either triggering the onclick of the default submit button (where default is also undefined) or nothing at all.

The current HTML specs are also quite vague about implicit submits. It says the following:

If a form contains more than one submit button, only the activated submit button is successful.

Sounds nice, but what does “activated” mean? When clicking a button, it’s obviously the clicked button, but what to do when pressing ENTER?

Different things may happen in different browsers. For example, in my current Firefox (3.5.8), IE8 and Chrome 4.1 browsers, the default button is the first button (first is determined as the first one in the source).

But in other, mainly older browsers, no click event may be raised. Or, it may raise a click event on the wrong button (the first one after the active input or the first one, based on tab order). This makes it a very unpredictable (and thus not very useful) mechanism.

The HTML5 spec is much clearer about implicit submission and it’s behavior. But, since many users won’t use a HTML5 browser for a while, we simply need a more reliable mechanism, like form.onsubmit. We’ve written our JavaScript validations on onsubmit for years and it simply works. But the standard JSF2 components don’t support it.

Initialization
Another issue with onclick is that it doesn’t provide any window.onload/document.ready support. It simply executes some JavaScript when the button is pressed and there is no way to initialize your JavaScript using a ClientBehavior.

For example, I would have liked to initialize my validateBean JS using the ClientBehavior. This would enable me to provide input masking support.
The mechanism for this needs to be initialized though. Some keyup/-down handlers need to be attached to the form fields and this needs to be done when the page is loaded.

ClientBehavior doesn’t support this. In the ValidateBeanBehavior, I added a @ResourceDependency for my scripts. I can put my initialization logic there, but why should I use a ClientBehavior when all I want to do is loading a JS file? I don’t know.

Default RenderKit
The default RenderKit, HTML_BASIC, attaches the event handlers inline using the “on[eventName]” attribute on the HTML tag. While this is easier for JSF implementers, I generally consider inline event handlers a bad practice. I prefer attaching them in the DOM L2 style: addEventListener (or attachEvent in IE). This allows multiple event handlers and if I really don’t care about this, I still dynamically add them using element.on[eventName]. I think this gives much better markup, because of the separation of markup and scripts.

But, 3th party components may do better here…

Supported components
All components that implement ClientBehaviorHolder may have one or more ClientBehaviors attached to them. Unfortunately, on UIForm, no event named “submit” is supported. And since submit is the most widely used event on forms, this is quite annoying, making behaviors not very useful for standard forms. After all, who wants to handle the dblclick event on a form?

Third party components may of course also implement ClientBehaviorHolder and take advantage of it.

So where is ClientBehavior useful?
Simply put, all client side event handlers you’d like to attach to EditableValueHolder or UICommand components that are triggered explicitly, for example by onchange or onclick events. I can imagine something like effects can be implemented nicely with ClientBehaviors. But OTOH, most effects in real world applications aren’t used standalone, but as a part of an Ajax transaction, so I don’t see much use there either.

The concept of ClientBehaviorHolder is generic and can be applied by any component, so I hope the ICEFaces, RichFaces and Trinidad folks take advantage of this mechanism. I think interoperability between libraries will increase with this.

But maybe I’m just negative because I’d like to completely control my JavaScript.




JSF 2.0 ClientBehavior: Bean Validation in JavaScript

Door: Jan-Kees van Andel, 17 March 2010

In the following article I’m going to show you my first “real world” ClientBehavior and my first impressions from a user’s perspective.

First, some theory. JSF has support for something called “attached objects”. This has been since the very beginning, with Converters and Validators.
Since JSF 2.0, Behaviors have been added to this list. A Behavior, when attached to a component, adds client side scripts to an object. For example, one can imagine a Behavior to do an Ajax request, load some data and show it on the page. This will be a common use case for behaviors. The Expert Group understood this and came up with a specialized AjaxBehavior, which is quite similar to the Ajax4jsf <:a4jsupport /> tag. it adds Ajax functionality to the existing component, without modifying it.

This is ClientBehavior in a nutshell. There are more subtile things to know, see this article by Andy Schwartz for a more thorough explanation of the subject.

From now on, I assume at least basic ClientBehavior knowledge and of course JSF knowledge.

The ValidateBean Behavior
With Java EE 6 we got Bean Validation. And I must admit, I like it a lot. It has a nice declarative language and one ubiquitous model for defining validations for your entire system, from database (generating Bean Validation-aware DDL with JPA 2.0) to UI (the JSF 2.0 BeanValidator, which I implemented for Apache MyFaces. That’s where my enthusiasm started).

But, one validation is missing in the spec (with good reasons of course), namely client side JavaScript validations, to improve usability and decrease server load.

Especially since JavaScript validations are often skipped because of maintenance reasons (validations implemented twice) and we now have a robust platform to implement generic validations, I tried to combine the two new technologies (ClientBehavior and Bean Validation) into one generic JavaScript validator.

The ClientBehavior implementation

This class has some interesting things. First, of course the annotations. @FacesBehavior simply registers the class as a ClientBehavior under the given name, just like how Managed Beans or Converters work. The second annotation defines a @ResourceDependency. A ResourceDependency simply says: “Hey JSF, I generate markup which depends on this file. Make sure it’s available”. And JSF 2.0 responds with: “Okay, I will”.

Also, you probably noticed my ClientBehavior to only understand buttons. That’s right, you need to attach it to a button and it takes care of wiring all field validations in the form.

It also looks for a messages component. This is used later to make sure the JS error messages are positioned the same as the by JSF generated messages. UIMessages applies to the entire view, so I don’t just look in the form. A high performance implementation may choose to start searching near the form, since most messages are positioned there, but that’s way out of scope of this article.

I know, I know, this is not the most elegant piece of code, but it nicely illustrates the point. I simply aggregates as much validation metadata as possible and writes it into one big JavaScript statement. Not that optimal, but high performance implementations may choose to dynamically generate a JS file with all metadata which only needs to be referenced from the inline JS code.

If you’d like to know how to obtain the ConstraintDescriptors (the four method calls in the above snippet), just look for the BeanValidator in the Apache MyFaces SVN. I reused the same code here.

The JavaScript
The JavaScript shown below is part of the static scripts that belong to the ValidateBeanBehavior. It contains the JavaScript code to execute the rules, as passed from the server and, if needed, show the validation errors.

It’s a lot of code, which, in essence, validates all input fields in the given form, according to the given validation rules and shows the user an error if needed. This error is positioned at the same spot as where the UIMessages would have been rendered in case of a server side error. This is a best guess though, because when the messages are not rendered (i.e. on the initial request), there is no marker in the page that I can use for positioning. A more sophisticated implementation could enrich all UIMessages in the page to always write some marker “div” with an ID to the client.

I’m going to skip the rest of the JavaScript. It’s just a bunch of validations and utilities, like utilities to convert Strings to and from Date Objects, based on a SimpleDateFormat pattern. This pattern is part of the generated JavaScript and is obtained by looking at the attached Converters.

Usage in a Facelet
To make the ClientBehavior a bit easier to use, here’s a Facelets taglib which defines a tag for the ClientBehavior (don’t forget to configure the taglib in web.xml or put it in the /META-INF of a JAR).

With the taglib in place, we can use the ClientBehavior, like this:

That’s not too much effort for a client side form validation right? And, these validations are always in-sync with the server side validations.

After a bit of cleanup, I’ll commit the code into the Apache MyFaces Sandbox, so you can download it from there when I’m done. :)




Using Unified Expression Language in Maven-Jetty-Plugin

Door: Jan-Kees van Andel, 27 February 2010

I like the maven-jetty-plugin. If I download an Open Source project, I usually first look for this baby, because it allows me to quickly run the code in a tested environment. This saves me from a lot of configuration, which would otherwise cause me to lose interest. This often doesn’t take long… :-)

Also, you can completely configure the server in your POM, centralizing configuration and making it thus easy to store server settings in version control. Also, the mvn-jetty-plugin benefits from your existing Maven project configuration, like dependencyManagement.

Some of my buddies at Apache even use the maven-jetty-plugin on a daily basis for their real work. I never got this far, mostly because I’m more familiar with Tomcat, but also because I didn’t really see it as a mature development tool. However, today I decided to give it a chance.

The first attempt
So, I created a simple webapp in my favorite IDE: IntelliJ IDEA and added a Maven2 POM to enable Maven2 support. All well so far.

This was the initial version of my POM:

All was fine, my test app was running, but I needed to enable Unified EL to test MyFaces BeanValidator.

Adding UEL libraries
So, I added a dependency to the UEL API and Impl in my POM, but there was an issue. Every web container already provides the old Expression Language in the jsp-api.jar. So I’m not allowed to package my own EL libraries.

However, I’m quite stubborn, so I tried anyway:

So, let’s give it a try:

mvn jetty:run-exploded

(MyFaces 2.0 requires exploded deployment in Jetty).

Result? BOOOM!

The fix, replacing libraries
The error is completely appropriate. You’re just not allowed to package your own version of the servlet libraries. That’s the job of the servlet container. Failing to do so will result in the error shown above.

So we need to fix this issue by somehow replacing the Jetty libraries or at least changing the way Jetty loads its jsp-api.jar. This is no trivial task however, since jetty is initialized by Maven and doesn’t have a fixed directory structure on disk.

So we need to have some way in Maven to configure the Jetty libraries.

First, Jetty doesn’t have an endorsed mechanism, so that’s a no-go.

But the fix is actually quite easy, just pass some dependencies into the jetty plugin in the POM.

The final POM looks like this:

As you can see, Maven takes care of the heavy lifting. You only need to specify your dependencies and they will override any dependencies with the same groupId, artifactId and type.

So, now I don’t have any reason not to use mvn-jetty-run to test my code!

Happy coding!




JSF 2.0: The most simple CDI integration use cases

Door: Jan-Kees van Andel, 31 January 2010

If you have (just like me) been following the Web Beans and Contexts and Dependency Injection (CDI) work, you might be thinking (also just like I did): “That CDI is heavily over-engineered”. My “moment of clarity” was a year ago, at DeVoxx 2008.

It was a talk by Pete Muir of JBoss. He was showing a really simple use case and tried to implement it using CDI. The talk was really technology driven and I hated it. Why? Because it wasn’t an improvement compared with the existing technologies. He wrote an application, containing several interfaces, classes (this is not bad) and custom annotations. If the goal was to show some kind of geniosity, it was a good talk. But if the goal was to show how this new technology would make our lives better… then sorry, he failed miserably.

More than a year further, there have been a lot of movements on the CDI front. And, as an Apache MyFaces developer, I’m of course very interested how to use CDI in a JSF 2.0 application. And as an Apache fanboy, I of course prefer Apache software, in this case MyFaces with OpenWebBeans and OpenJPA.

Configuration
Since OpenWebBeans is still under development, you need to do some additional steps to get it to work.

The following POM should get you up and running quickly in Tomcat:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.apache.myfaces</groupId>
    <artifactId>myfaces-example-ebanking</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <dependencies>
        <!-- Compile dependencies -->
        <dependency>
            <groupId>org.apache.myfaces.core</groupId>
            <artifactId>myfaces-api</artifactId>
            <version>${myfaces-version}</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.myfaces.core</groupId>
            <artifactId>myfaces-impl</artifactId>
            <version>${myfaces-version}</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.openjpa</groupId>
            <artifactId>openjpa-all</artifactId>
            <version>${openjpa-version}</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>commons-digester</groupId>
            <artifactId>commons-digester</artifactId>
            <version>2.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.openwebbeans</groupId>
            <artifactId>openwebbeans-impl</artifactId>
            <version>${openwebbeans.version}</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.openwebbeans</groupId>
            <artifactId>openwebbeans-jsf</artifactId>
            <version>${openwebbeans.version}</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-interceptor_1.1_spec</artifactId>
            <version>1.0.0-EA1-SNAPSHOT</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>jsr250-api</artifactId>
            <version>1.0</version>
            <scope>compile</scope>
        </dependency>

        <!-- Test dependencies -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
            <version>${junit-version}</version>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>Apache MyFaces beta</id>
            <name>Apache MyFaces beta</name>
            <url>http://people.apache.org/~lu4242/myfaces200beta</url>
        </repository>
    </repositories>

    <properties>
        <myfaces-version>2.0.0-beta</myfaces-version>
        <openwebbeans.version>1.0.0-SNAPSHOT</openwebbeans.version>
        <openjpa-version>2.0.0-M3</openjpa-version>
        <junit-version>4.7</junit-version>
    </properties>
</project>

Note some of the additional dependencies required to run in Tomcat, as opposed to a full blown appserver.

Also, at the moment you need to build OpenWebBeans from source manually. The geronimo-interceptor_1.1_spec dependency will be downloaded to your local Maven repository on a “mvn install”. OpenJPA is not needed for this simple use case, but I use it in my project.

Code
And then, the real code:

public class WebUtils {
    private static volatile String basePath;

    @Produces @Named public String getBasePath() {
        if (basePath == null) {
            basePath = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
        }
        return basePath;
    }
}

This class contains a so-called Producer Method. As the name suggests, it produces stuff. In this case, it produces a String with Dependent scope. This means the method will be invoked every time the variable is needed. EL expressions or injection are the most common cases for this.

I’m caching the return value, though it’s not necessary, since getting the context path is pretty cheap.

The view could look like this (snippet):

...
<link href="#{basePath}/style/default.css" rel="stylesheet" type="text/css" />
...

Another implementation could put the variable into the Application scope, like this:

public class WebUtils {
    @Produces @Named @ApplicationScoped public String getBasePath() {
        return FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
    }
}

As easy it might seem, the approaches shown above require some responsibility from the programmer though. With producer methods, it becomes really easy to mess things up. After all, you’re effectively creating globals. Tool support may help you here though. For example, the Dependency Analyzer in IntelliJ IDEA 9.0.1 already contains pretty decent support for JSF 2.0 and CDI. And, knowing the reputation of the JetBrains folks, I’m sure they come up with even more fancy stuff.

A more classic implementation
A more classic implementation could look like the following:

@Named
@ApplicationScoped
public class WebBean {
    private static volatile String basePath;

    public String getBasePath() {
        if (basePath == null) {
            basePath = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
        }
        return basePath;
    }
}

I’m not using producer methods anymore. The WebBean is now a CDI-managed bean.

The client code becomes slightly more verbose, but who cares? I’ll put the client code in a generic template anyway!:

...
<link href="#{webBean.basePath}/style/default.css" rel="stylesheet" type="text/css" />
...

Wrapping up
I haven’t even showed the complete tip of the iceberg. CDI offers several ways to write code and we’ve yet to find out the (anti) patterns.

I would like to point you to the OpenWebBeans documentation for more info, but unfortunately this is still under development. The good news is that JBoss Weld already has extensive documentation.




JSF 2.0: Maximum flexibility with System Events

Door: Jan-Kees van Andel, 24 January 2010

JSF 2.0 adds a lot of interesting features. Andy Schwartz provides an extensive overview on his blog.

On this blog, I’d like to elaborate a bit further on the interesting features JSF 2.0 has to offer.

JSF 2.0: System Events
JSF 2.0 comes with a useful feature, called System events. System events are predefined events that are published at predefined points in the lifecycle.
System events are either global or component system events.

Global system events
An example of a global system event is PostConstructApplicationEvent, which is published when all configuration is done. It can be seen as a JSF replacement for ServletContextListener.

Listener registration is done by invoking Application.subscribeToEvent(Class<? extends SystemEvent> type, SystemEventListener listener).

Component system events
Component system events only apply to the component to which the listener is attached.

An example of a component system event is PreRenderComponentEvent. This event is published to the appropriate component when it’s about to be rendered.

Listener registration is done by invoking UIComponent.subscribeToEvent(Class<? extends SystemEvent> type, ComponentSystemEventListener listener).

<f:event /> tag
The JSF 2.0 spec also defines the <f:event /> tag, which needs to be nested inside a component tag in the web page. This tag is used to make listener registration easier. Just nest the tag inside a component tag in your Facelet, specify the event to listen to and specify a MethodExpression to your listener method and everything works.

An example
Below is an example of an e-banking login page. It uses a challenge-response authentication mechanism, so it generates a “random” challenge when the page is loaded. Because users can navigate to the login page directly (GET-request), we can’t rely on an action method to be invoked first, so let’s fix this using system events.

First, a bit of history
I’ve always hated to write “the first” page in JSF. Since JSF short circuits the lifecycle in the case of a GET request, you don’t really have an appropriate hook for page initialization, making it difficult to create a dynamic landing page.

One could write “lazy getters”:

public class MyBackingBean {
    private List accounts;

    public List getAccounts() { // Yuck
        if (accounts == null) {
            // Do some expensive database query
            accounts = doSomeWork();
        }
        return accounts;
    }
}

It’s quite obvious this is extremely nasty. You don’t know when the getter is invoked (EL triggers the invocation), and that if-null check is also ugly. Btw. getters with logic are ugly anyway…

JSF 1.2 offered a slightly more elegant option with @PostConstruct:

public class MyBackingBean {
    private List accounts;

    @PostConstruct
    public void init() {
        accounts = doSomeWork();
    }

    public List getAccounts() { // Still not good
        return accounts;
    }
}

This is a bit better, but still not very good. The exact point of invocation within the lifecycle is still not obvious. But at least we now know the init() method won’t be invoked multiple times.

There are other ways to tackle this issue, for example, using a PhaseListener, or using a framework like Seam, but that has issues of its own.

Back to the event example
Below is a snippet of my login page.

<h:form>
  <dl>
    <dt><h:outputLabel value="Customer ID" for="customerId" /></dt>
    <dd><h:inputText id="customerId" value="#{loginBean.customerId}" required="true" /></dd>
    <dt><h:outputLabel value="Challenge" for="challenge" /></dt>
    <dd><h:outputText id="challenge" value="#{loginBean.challenge}">
      <f:event name="preRenderComponent" listener="#{loginBean.generateChallenge}" />
    </h:outputText></dd>
    <dt><h:outputLabel value="Response (always 123456)" for="response" /></dt>
    <dd><h:inputSecret id="response" value="#{loginBean.response}" required="true" /></dd>
    <dt> </dt>
    <dd><h:commandButton value="Login" action="#{loginBean.loginUsingTokenGenerator}" /></dd>
  </dl>
</h:form>

As you can see, the above snippet contains the challenge response login form. Line 7 is the interesting one. It registers a PreRenderComponentEvent listener method on the LoginBean.

The LoginBean is shown next (snippet…).

@Named
@SessionScoped
public class LoginBean implements Serializable {
    private Integer customerId;
    private Integer challenge;
    private Integer response;
    private @Inject LoginService loginService;
    private Customer customer;
    // Getters and setters

    public void generateChallenge(ComponentSystemEvent event) throws AbortProcessingException {
        this.challenge = loginService.generateChallenge();
    }

    public String loginUsingTokenGenerator() {
        customer = loginService.loginUsingTokenGenerator(customerId, challenge, response);
        if (customer == null) {
            FacesContext.getCurrentInstance().addMessage(null,
                        new FacesMessage(
                        "Username and/or password is incorrect or your account has been disabled"));
            return null;
        } else {
            return "/pages/homepage.xhtml?faces-redirect=true";
        }
    }
}

Don’t mind the annotations, they come from CDI (JSR-330 a.k.a. Contexts and Dependency Injection). The only thing to remember from these is that this class is a Session scoped managed bean which gets a LoginService injected. Note that I would also prefer ViewScoped, instead of SessionScoped.

Also, don’t mind the return values in loginUsingTokenGenerator. This is also a new feature in JSF 2.0, called Implicit Navigation.

Note the generateChallenge() method. The throws clause is not mandatory. The argument type must be ComponentSystemEvent though.

Wrapping up
As you can see, System events and the <f:event /> tag provide a convenient way to hook in custom logic on a per-component basis.

And, because we’re back to normal OO programming, instead of getter hacking, unit testing the LoginBean is easy as pie!

Pretty neat huh?! ;-)