August 20, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

JSF 2.0: Creating Composite Components

  • March 8, 2010
  • By Sangeetha S, Nitin KL, Ananya S
  • Send Email »
  • More Articles »

Creating Composite Components in JSF 2.0

Now, for a better understanding of how to create a composite component in JSF 2.0, consider a simple demo example: an online quiz application that allows a registered user to answer five simple questions that test his or her general knowledge. Towards the end of the quiz, the application displays the score. Because the user can take the quiz only after a successful login, he or she must first register (see Figure 1 for a screenshot of the registration form).


Figure 1. Online Quiz Registration Form:
The user can take the quiz only after he or she must registers.

The following are the necessary features for the registration form:

  1. The email entered should be validated against a standard format.
  2. Values entered in the Password and Confirm Password fields should be the same.
  3. The date entered should be in mm/dd/yy format.
  4. When a user clicks the Register button, a business method should be invoked that completes the registration process.

Because these requirements are common across most registration forms, you can create a composite component that reflects this behavior.

First, you need to create a resource library named comp. Within comp, you create a Facelets file named register.xhtml, which will contain the necessary code for the composite component. The location of this file will be /resources/comp/register.xhml.

Here is the general structure of a composite component Facelets file:

<!-- XHTML DOCTYPE Declaration -->
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:composite="http://java.sun.com/jsf/composite">
    <!—Interface that defines the user contract of the component-->
    <composite:interface>
...      
    </composite:interface>
    <!-- Implementation that specifies the actual markup-->
    <composite:implementation>
...      
    </composite:implementation>
</html></p>


The tags used to define a composite component are defined in the http://java.sun.com/jsf/composite namespace identified by the prefix composite. Each composite component has to provide a usage contract so that the users will know what to provide and what to expect. This is specified using the <composite:interface> tag. The actual markup that implements the component's user contract is specified using the <composite:implementation> tag.

The user contract of the registration component (shown below) allows the component user to provide customized labels for the input fields. These can be passed as values of predefined attributes, which are declared by using <composite:attribute> defined as a child element of <composite:interface>. For example, you have defined an attribute named regButtonText that defines the label for a Register button. The component user must provide this attribute's value. The label for other attributes, such as regPrompt, emailPrompt, and userNamePrompt, are optional and have been given default values.

When the user clicks the Register button, a managed bean method has to be invoked. The bean and the method are specified by the component user using the managedBean and regAction attributes. Notice the declaration of the regAction method that defines the signature of the bean method to be invoked.

<!-- Interface that defines the user contract of the component -->
  <composite:interface>
      <composite:attribute name="regButtonText" required="true"/>
      <composite:attribute name="regPrompt" default="Please fill registration details" />
        <composite:attribute name="emailPrompt" default="Email" />
        <composite:attribute name="userNamePrompt" default="Username"/>
        <composite:attribute name="passwordPrompt" default="Password"/>
        <composite:attribute name="confirmPasswordPrompt" default="Confirm Password"/>
        <composite:attribute name="dobPrompt" default="Date of Birth in mm/dd/yy format"/>
        <composite:attribute name="regAction" method-signature="java.lang.String register()" required="true"/>
        <composite:attribute name="managedBean" required="true"/>
</composite:interface>


The next step is to implement the composite component using appropriate markup in the <composite:implementation> element. In this case, the implementation consists of a single form with different input elements for accepting the email Id, username, password and date of birth of the user. To access the value of a component attribute you use the following syntax:

#{cc.attrs.attr_name}


Where attr_name is the name of the attribute.

Also notice the use of the <f:validateRegex> tag to validate the value in the email field. This new tag in JSF 2.0 allows the value of input component to be validated against a regular expression. Also, the date of birth needs to be converted to a Date object using the <f:convertDateTime> tag.

<composite:implementation>
   <h:form id="form" prependId="false">
        <div class="prompt">
           #{cc.attrs.regPrompt}
        </div>
        <h:panelGrid columns="2">
         <h:outputText value="#{cc.attrs.emailPrompt}"/>
         <h:inputText id="email" value="#{cc.attrs.managedBean.email}" required="true">
    <f:validateRegex pattern="[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[a-zA-Z0-9]+" />
           </h:inputText>
 
         <h:outputText value="#{cc.attrs.userNamePrompt}"/>
          <h:inputText id="name" value="#{cc.attrs.managedBean.userName}" required="true"/>
 
          <h:outputText value="#{cc.attrs.passwordPrompt}"/>
          <h:inputSecret id="password" value="#{cc.attrs.managedBean.password}" required="true"/>
 
          <h:outputText value="#{cc.attrs.confirmPasswordPrompt}"/>
          <h:inputSecret id="confirmPassword" value="#{cc.attrs.managedBean.confirmPassword}" required="true"/>
 
           <h:outputText value="#{cc.attrs.dobPrompt}"/>
   <h:inputText id="dob" value="#{cc.attrs.managedBean.dob}" required="true">
            <f:convertDateTime dateStyle="short"/>
          </h:inputText>
     </h:panelGrid>
        <p>
          <h:commandButton id="regButton"
    value="#{cc.attrs.regButtonText}" action="#{cc.attrs.regAction}" onclick="return checkPwd(this.form)"/>
       </p>
      </h:form>
   <script type="text/javascript">
      <!—Javascript code to validate that values in password and confirmPasssword field are same -->
    </script>
      <div>
        <h3>Please note that all fields are mandatory</h3>
      </div>
      <div class="error" style="padding-top:10px;">
        <h:messages layout="list" />
      </div>
</composite:implementation>


To ensure that the password and confirmPassword fields have the same value, you use the JavaScript method shown below:

function checkPwd(form){
     var pwd1 = document.getElementById("#{cc.clientId}"+":"+"password")
     var pwd2 = document.getElementById("#{cc.clientId}"+ ":"+"confirmPassword")
 
     if(pwd1.value != pwd2.value){
                    alert("Passwords Do Not Match ")
                    pwd1.value=""
                    pwd2.value=""                    
                    return false
     } else {
                    form.submit();
                    return true;
     }
}


Notice that the ID of the individual components that make up the composite component will be prefixed with the composite component's ID, which is determined at runtime. So, the actual ID of the password element is determined as "#{cc.clientId}"+":"+"password" where ":" is the ID separator. Also note that the prepend attribute of the form element is set to false. This ensures that the ID of the form-form- is not prepended to the form elements' IDs.

The register composite component is used in the Facelets file regform.xhtml. Declare a special namespace declaration that denotes the use of a composite component. To use any composite component in a Facelets file, you have to define a special namespace: http://java.sun.com/jsf/composite/res_lib, where res_lib is the name of the resource library containing the composite component file. In this case, the resource library is named comp.

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


Once this is done, you can refer to the component as a Facelets tag, which is the name of the composite component file itself.

<comp:register regButtonText="Register" managedBean="#{regBean}"   regAction="#{regBean.register}"/>


Here, comp is the prefix attached to the special namespace declaration, and register is the name of the registration composite component file. You have to pass values for all the mandatory attributes: regButtonText, managedBean, and regAction.

As this simple demo exercise has shown, the process of creating composite components has been greatly simplified by using resources, Facelets, and a simple naming convention.

Conclusion

In this article, we discussed the new composite components feature in JSF 2.0. Using this feature, you can create simple, reusable JSF UI components without needing to manipulate any Java code or XML configuration files.

Stay tuned as we will explore more notable new features in JSF 2.0 in upcoming articles.

Acknowledgements

The authors would like to sincerely thank Mr. Subrahmanya (SV, VP, ECOM Research Group, E&R) for his ideas, guidance, support and constant encouragement and Ms. Yuvarani Meiyappan (Lead, E&R) for kindly reviewing this article and for her valuable comments.

About the Authors

Sangeetha S. works as a Senior Technical Architect at the E-Commerce Research Labs at Infosys Technologies. She has over 10 years of experience in design and development of Java and Java EE applications. She has co-authored a book on 'J2EE Architecture' and also has written articles for online Java publications.

Nitin KL works at the E-Commerce Research Labs at Infosys Technologies. He is involved in design and development of Java EE applications using Hibernate, iBATIS, and JPA.

Ananya S. works at the E-Commerce Research Labs at Infosys Technologies. She is involved in design and development of Java EE applications using Hibernate, iBATIS, and JPA.





Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel