Sunday, September 18, 2011

Single class pure Java JSF application

In my previous blog entry, Authoring JSF pages in pure Java, it was explained how to set up a JSF based web application using nothing but pure Java. No XML based templating (Facelets) was required and the view was build purely programmatically.

I got one remark though that the example code did used expression language (EL) to patch some of the parts together. Although EL is really convenient, as it provides a way to point to a (nested) method on a scoped object, it's not regular type-safe Java.

Luckily, the Java component API of JSF doesn't only use EL based ValueExpressions and MethodExpressions, but also allows regular Java types to be set as listeners and values. This is demonstrated in the code below. While at it, I've done away with the separate backing bean for this example and let the same class that defines the page handle the action event.

The result is a pure Java, xml-less, EL-less, config-less, single class JSF application [phew]:

@Named
@FacesConfig
public class Intro implements Page, ActionListener {

    private HtmlOutputText message;
    
    @Override
    public void buildView(FacesContext context, UIViewRoot root) throws IOException {
        
        List rootChildren = root.getChildren();
        
        UIOutput output = new UIOutput();
        output.setValue("<html xmlns="http://www.w3.org/1999/xhtml">");                
        rootChildren.add(output);
        
        HtmlBody body = new HtmlBody();
        rootChildren.add(body);
        
        HtmlForm form = new HtmlForm();
        body.getChildren().add(form);
        
        message = new HtmlOutputText();
        form.getChildren().add(message);
        
        HtmlCommandButton actionButton = new HtmlCommandButton();
        actionButton.addActionListener(this);
        actionButton.setValue("Do action");
        form.getChildren().add(actionButton);
                
        output = new UIOutput();
        output.setValue("</html>");
        rootChildren.add(output);
    }
    
    @Override
    public void processAction(ActionEvent event) throws AbortProcessingException {
        message.setValue("hello, world");
    }    
}

To run this on Payara, only this class and the small (8,980 bytes) javavdl.jar library are required:

After requesting localhost:8080/demo/intro.jsf, a single button will be shown. The message "hello, world" will be displayed when this button is clicked.

Interesting to note perhaps is that the components themselves only exist for the duration of the request and after every post-back the component tree will be re-created. State set on the components during buildView will be marked as the so-called initial state and will typically not be taken into account by JSF's state saving mechanism. Since only the HtmlCommandButton in the example code references the Page instance after this buildView it will effectively have request scope.

The java based vdl is still rather simple, so it's still just a proof of concept. I've planned some enhancements that I'll work on soon if time permits (e.g. perhaps support for scopes other than request scope without using EL). Stay tuned!

Arjan Tijms

No comments:

Post a Comment