Monday 17 December 2012

How to create a JSF 2 component

Java Server Pages (JSF) is an extensible JEE web framework.  In this blog post I will demonstrate how to create a simple JSF component.

When developing a JSF component one of the technical aim is to make it as simple and obvious as possible for a developer to use it.  A user of our component shouldn't have to worry about handling call backs, updating state etc.  With this in mind lets begin:


Step 1) Create the java component:  


public class TextToUpperComponent {

  private String input;
  private String output;

  public void convert() {
    output = input.toUpperCase();
  }

  + getters and setters
}

This contains the state and the call back method ( convert() ) to handle button presses.

Step 2) Create the JSF Manatged Bean:.

@ManagedBean
public class MyBean {

  private TextToUpperComponent a = new TextToUpperComponent();
  private TextToUpperComponent b = new TextToUpperComponent();
  private TextToUpperComponent c = new TextToUpperComponent();

  + getters and setters
}

What we've done here, is to make the TextToUpperComponent component a property of the ManagedBean (3 times).   Other listeners/callbacks can be defined to inspect these properties and apply business logic as required.


Step 3)  Define the component -  webapp/resources/texttoupper.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:composite="http://java.sun.com/jsf/composite"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">

  <composite:interface>
    <composite:attribute name="title" />
    <composite:attribute name="jcomponent" />
  </composite:interface>

  <composite:implementation>
    <h:form id="myform">
      <h:panelGrid>
        <h:outputLabel value="#{cc.attrs.title}: " for="word" />
        <h:inputText id="word" value="#{cc.attrs.jcomponent.input}" />
        <h:outputText value="#{cc.attrs.jcomponent.output}" />
        <h:commandButton value="To Upper">
          <f:ajax listener="#{cc.attrs.jcomponent.convert()}" execute="myform" render="myform"/>
        </h:commandButton>
        <br/>
      </h:panelGrid>
    </h:form>
  </composite:implementation>
</html>


As we're placing it under webapp/resources/coder36, the component namespace will be: xmlns:c="http://java.sun.com/jsf/composite/coder36".

A point to note is that once the JSF page is rendered, the components are completely independent of each other, so there is no need to worry about clashing id's etc.


Step 4)  Create index.xhtml Page

Don't forget to include the namespace: 


<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:p="http://primefaces.org/ui"
      xmlns:h="http://java.sun.com/jsf/html"      
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:c="http://java.sun.com/jsf/composite/coder36"
      xmlns:ui="http://java.sun.com/jsf/facelets"> 

 <h:head></h:head> 
 <h:body>
   <c:texttoupper jcomponent="#{myBean.a}" title="First"/>      
   <c:texttoupper jcomponent="#{myBean.b}" title="Second"/>
   <c:texttoupper jcomponent="#{myBean.c}" title="Third"/>
 </h:body> 
</html>


And that's it!  With very little effort we have created a simple reusable JSF component and demonstrated how to integrate it.