Authoring JSF pages in pure Java

12 September 2011, by: Development

JSF is well known as a server side web framework to build a web application’s UI with the help of components. For the overwhelming majority of users those components are represented by the tags one uses to compose a page, be it via JSP or Facelets.

The following is a typical example of a page authored with Facelets:

  1. <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html">    
  2.     <h:body>   
  3.        #{backingBean.hello}   
  4.         <h:form>      
  5.             <h:inputText value="#{backingBean.name}" />                    
  6.             <h:commandButton value="Say Hello" action="#{backingBean.sayHello}" />
  7.         </h:form>        
  8.     </h:body>
  9. </html>

This may give the impression that JSF components *are* the tags shown above, and thus that JSF is necessarily about tags and XML. That is however not true.

JSF has always had a clear separation between the technology used to author pages (the so-called view description language) and the actual API to create components and compose them together into a component tree. This API is a Java API that even in the very first days of JSF had no knowledge whatsoever about JSP or tags. The strict separation allowed alternative view declaration languages like Facelets to be created and eventually be promoted to the default VDL, without needing to change the underlying JSF core framework.

Other view declaration languages have been created as well. One notable example is a concept based on JavaFX, in which a JSF page would look like this:

  1. var x = 0;
  2. var bindVal = "Hello";
  3.  
  4. function init(){
  5.    FxPage{
  6.       content : [
  7.          FxForm{
  8.                 content : [
  9.                     FxOutputLabel{
  10.                         value : bind bindVal
  11.                     },
  12.                     FxCommandButton{
  13.                         value : "Button"
  14.                         actionListener : function() : String{
  15.                             bindVal = "Hello {x++}";
  16.                             return null;
  17.                         }
  18.                     }
  19.                 ]
  20.             }
  21.         ]
  22.     }
  23. }

See: JavaFX as JSF VDL (View Description Language)?

As it appears, the API to create components and compose a component tree is pretty accessible by itself. It could theoretically be used directly to author pages instead of solely being used as an API for VDL implementations. The problem however is that it’s not clear how to actually start doing that. One trick is to use dynamic tree manipulation and add components in a PreRenderView event on an otherwise empty page.

Another way is to create a minimal VDL implementation. As a proof of concept, that’s what I did. With such a thing it’s possible to create a JSF application completely in Java. No Facelets or JSP files, and following Minimal 3-tier Java EE app, without any XML config, no web.xml or faces-config.xml is required either. There doesn’t even have to be a WEB-INF or WebContent directory in the project.

The following shows a JSF page being defined in pure Java:

  1. public class Intro implements Page {
  2.  
  3.     @Override
  4.     public void buildView(FacesContext context, UIViewRoot root) throws IOException {
  5.  
  6.         ELContext elContext = context.getELContext();
  7.         ExpressionFactory expressionFactory = context.getApplication().getExpressionFactory();
  8.  
  9.         List<UIComponent> rootChildren = root.getChildren();
  10.  
  11.         UIOutput output = new UIOutput();
  12.         output.setValue("&lt;html xmlns="http://www.w3.org/1999/xhtml">");                
  13.         rootChildren.add(output);
  14.  
  15.         HtmlBody body = new HtmlBody();
  16.         rootChildren.add(body);
  17.  
  18.         HtmlForm form = new HtmlForm();
  19.         body.getChildren().add(form);
  20.  
  21.         ValueExpression messageProperty = expressionFactory.createValueExpression(elContext, "#{myBean.message}", String.class);
  22.  
  23.         HtmlOutputText message = new HtmlOutputText();
  24.         message.setValueExpression("value", messageProperty);
  25.         form.getChildren().add(message);
  26.  
  27.         MethodExpression helloMethod = expressionFactory.createMethodExpression(elContext, "#{myBean.action}", Void.class, new Class[0]);
  28.  
  29.         HtmlCommandButton hiCommand = new HtmlCommandButton();
  30.         hiCommand.setActionExpression(helloMethod);
  31.         hiCommand.setValue("Say hello");
  32.         form.getChildren().add(hiCommand);
  33.  
  34.         MethodExpression navigateMethod = expressionFactory.createMethodExpression(elContext, "#{myBean.navigate}", String.class, new Class[0]);
  35.  
  36.         HtmlCommandButton navigateCommand = new HtmlCommandButton();
  37.         navigateCommand.setActionExpression(navigateMethod);
  38.         navigateCommand.setValue("Do navigation");
  39.         form.getChildren().add(navigateCommand);
  40.  
  41.         output = new UIOutput();
  42.         output.setValue("&lt;/html>");
  43.         rootChildren.add(output);
  44.     }    
  45. }

This will be rendered as follows:

The code shows how components are created simply by using the new operator and a tree is created by just inserting the child components in the children collections of their parents. Action listeners are registered on action source components by setting a method expression that points to the scoped backing bean “myBean”, which is defined as follows:

  1. @ManagedBean
  2. public class MyBean {
  3.  
  4.     private String message;
  5.  
  6.     public void action() {
  7.         message = "Hi!";
  8.     }
  9.  
  10.     public String navigate() {
  11.         return redirectOutcome(OtherPage.class);
  12.     }
  13.  
  14.     public String getMessage() {
  15.         return message;
  16.     }    
  17. }

Note that the bean features a navigation method that uses the class type of the target page to determine the navigation outcome.

By putting stuff in base classes or utility methods, page implementations can be simplified. For instance, the following shows the page where the user is navigated to after pushing the button on the first page. It inherits from a base class that already defines the html and outer body part, and only implements the body content:

  1. public class OtherPage extends BodyTemplate {
  2.  
  3.     @Override
  4.     public void buildBody(FacesContext context, HtmlBody body) {    
  5.         HtmlOutputText output = new HtmlOutputText();
  6.         output.setValue("This is a new page.");
  7.         body.getChildren().add(output);        
  8.     }
  9. }

This page is rather simple and is rendered as:

As shown by the screen shots, if the project is called javavdl the initial page can be requested by requesting http://localhost/javavdl/intro.jsf, which is fully implemented using the Intro.java class given above. After clicking the navigate button, the user will be redirected to http://localhost/javavdl/test/otherPage.jsf, which is fully implemented by OtherPage.java. For this simple proof of concept, classes implementing pages have to reside in the package resources.javavdl.pages. Sub-packages in that package become paths relative to the deployment root of the application. E.g. /test/otherPage.jsf is implemented by resources.javavdl.pages.test.OtherPage.

The following is a picture of my workspace, showing that there is absolutely not a single xml file:

If this were used for real, the “src” package would probably be in a jar, and the application would consist of nothing more than this jar and the four classes shown in the demo package.

The current setup is really just a proof of concept. I personally think a declarative approach like Facelets is actually clearer, although some people actually do seem to like a purely programmatic approach to building a UI.

If people want to tinker with this, I’ve shared my Eclipse project where I implemented this here: http://code.google.com/p/javavdl (it currently depends on the Glassfish WTP server adapter being installed).

Arjan Tijms

11 comments to “Authoring JSF pages in pure Java”

  1. Martin Ericksonn says:

    I found it a little difficult to follow the code examples, especially the “impl” files or whatever they are.

    Could you please provide a Visual Basic example? That would make things a bit easier to understand I am sure.

  2. JavaPins says:

    Authoring JSF pages in pure Java | J-Development…

    Thank you for submitting this cool story – Trackback from JavaPins…

  3. Geoff says:

    You could try using the double brace pattern to structure the Java code, this would make it more like the JSF version. Unfortunately the JSF API forces you through getChildren to add rather than providing an explicit addChild() method, which makes this approach more clunky than normally necessary.

  4. arjan tijms says:

    >I found it a little difficult to follow the code examples, especially the “impl” files or whatever they are.

    You don’t have to look at the “impl” files if you would just be using Java to create pages. This is kinda like you don’t need to look at how Facelets is implemented just to use Facelets.

    >Could you please provide a Visual Basic example?

    Haha, sorry, I don’t know VB ;)

  5. arjan tijms says:

    >You could try using the double brace pattern to structure the Java code, this would make it more like the JSF version.

    Funny that you mention that, I actually used this a lot in Swing and SWT. Besides grouping, it also gives various child trees a unique scope relative to sibling trees.

    >Unfortunately the JSF API forces you through getChildren to add rather than providing an explicit addChild() method, which makes this approach more clunky than normally necessary.

    Indeed, I felt the same way. There are some more of these things. If a component could receive its main value directly via the constructor, it would make the code again less verbose. E.g. new HtmlOutputText(“This is some text”);

    Still, given that the API was most likely created purely for VDL implementations, I found it surprisingly useable (relatively spoken thus).

  6. Ian says:

    nice article mate!

    wrt to the simplified components, it’s Java so you can always subclass them and provide that convenience constructor, can’t you?

  7. Tab sweep – GZip for GlassFish, Scala and JavaEE 6, JavaOne Diversity, JavaZone Videos, … says:

    [...] also from JavaZone) • All JavaZone 2011 videos (“Couch Mode” included) • Authoring JSF pages in pure Java (Arjan) • Focus On NetBeans @ JavaOne 2011 (NetBeans) Content Regenerated from [...]

  8. Single class pure Java JSF application | J-Development says:

    [...] Home » Blog » Single class pure Java JSF application « Authoring JSF pages in pure Java [...]

  9. What’s new in JSF 2.2? | J-Development says:

    [...] as a Java instance via user code. So when building a component tree programmatically (see e.g. Authoring JSF pages in pure Java), incorporating those composite components was challenging to say the [...]

  10. Anonymous says:

    Is there a way to inject the managed bean instance in a typesafe way into the Page instance? I ‘d rather not access the bean via EL.

  11. arjan tijms says:

    Is there a way to inject the managed bean instance in a typesafe way into the Page instance?

    Not yet. It was something I had planned, but I never came around to advancing this initial prototype. For an example that doesn’t use EL, see the follow-up post:

    http://jdevelopment.nl/single-class-pure-java-jsf-application/

    Note that even though Page is declared as a managed bean, it isn’t actually created via the managed bean facility yet and injection in it will thus not work at the moment.

Type your comment below:


+ six = 15

css.php best counter