Wednesday Oct 27, 2010

TOTD #147: Java Server Faces 2.0 Composite Components using NetBeans - DRY your code

The Java Server Faces 2.0 uses Facelets instead of JSP as the view declaration language. This allows "view" part of MVC to be completely written using XHTML and CSS only and all the business logic resides in the backing bean. This enables a cleaner separation of views with model and controller and thus follows the MVC design pattern in a more intuitive way. JSF 2 also defines how resources can be packaged, located, and rendered by JSF runtime within a web application.

Using these two features of Facelets and Resource Handling, JSF2 defines a composite component as a component that consists of one or more JSF components defined in a Facelet markup file that resides inside of a resource library. The composite component is defined in the defining page and used in the using page. The "defining page" defines the metadata (or parameters) using <cc:interface> and implementation using <cc:implementation> where "cc" is the prefix for "http://java.sun.com/jsf/composite" namespace. Future versions of the JSF 2 specification may relax the requirement to specify metadata as it can be derived from the implementation itself.

A composite component can be defined using JSF 1.2 as well but it requires a much deeper understanding of JSF lifecycle and also authoring multiple files. JSF2 really simplifies the authoring of composite components using just an XHTML file.

Code is king! This Tip Of The Day (TOTD) will explain how to convert an existing code fragment into a JSF2 composite component using NetBeans IDE.

Lets say a Facelet (index.xhtml) has the following code fragment:

<h:form>
    <h:panelGrid columns="3">
    <h:outputText value="Name:" />
    <h:inputText value="#{user.name}" id="name"/>
    <h:message for="name" style="color: red" />
    <h:outputText value="Password:" />
    <h:inputText value="#{user.password}" id="password"/>
    <h:message for="password" style="color: red" />
  </h:panelGrid>

  <h:commandButton actionListener="#{userService.register}"
                   id="loginButton" action="status" value="submit"/>
</h:form>


This fragment displays an HTML form with two text input boxes and a "submit" button. The two input boxes are bound to "user" bean and clicking on the button invokes "register" method of the "userService" bean.

Instead of repeating this code in multiple pages, its beneficial to convert this into a composite component and use the resulting tag instead of the complete fragment again. Why ?

  • Follows the DRY principle and allows to keep the code, that can be potentially be repeated at multiple places, in a single file.
  • It allows developers to author new components without any Java code or XML configuration.

How do you convert an existing code fragment to a composite component ? NetBeans makes it really easy.

In NetBeans IDE select the code fragment, right-click, "Refactor", "Convert to Composite Component..." as shown below:

In the next screen, change the filename to "loginPanel" and take every thing else as default as shown below:

and click on "Finish".

This will generate "web/resources/ezcomp/loginPanel.xhtml" and move the component definition to this file, aka "defining page" and looks like:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:cc="http://java.sun.com/jsf/composite"
      xmlns:h="http://java.sun.com/jsf/html">

 <!-- INTERFACE -->
 <cc:interface>
 </cc:interface>

 <!-- IMPLEMENTATION -->
 <cc:implementation>
   <h:form>
     <h:panelGrid columns="3">
       <h:outputText value="Name:" />
       <h:inputText value="#{user.name}" id="name"/>
       <h:message for="name" style="color: red" />
       <h:outputText value="Password:" />
       <h:inputText value="#{user.password}" id="password"/>
       <h:message for="password" style="color: red" />
     </h:panelGrid>

     <h:commandButton actionListener="#{userService.register}"
                      id="loginButton" action="status" value="submit"/>
   </h:form>
</cc:implementation>
</html>

<cc:interface> defines metadata that describe the characteristics of component, such as supported attributes, facets, and attach points for event listeners. <cc:implementation> contains the markup substituted for the composite component.

<cc:interface> is generated in the page but is empty and may be made optional in a subsequent release of the JSF specification.The "using page" will declare a new namespace as:

xmlns:ez="http://java.sun.com/jsf/composite/ezcomp"

and then replace the code fragment with:

<ez:loginPanel/>

The tag name for the new composite component is the same as the "defining page" file name. This enables "<ez:loginPanel/>" to be used instead of repeating that entire code fragment.

Now lets say that the code fragment need to pass different value expressions (instead of #{user.name}) and invoke a different method (instead of #{userService.register}) when submit button is clicked in different "using page"s. The "defining page" can then look like:

<!-- INTERFACE -->
<cc:interface>
  <cc:attribute name="name"/>
  <cc:attribute name="password"/>
  <cc:attribute name="actionListener"
      method-signature="void action(javax.faces.event.Event)"
      targets="ccForm:loginButton"/>
</cc:interface>

<!-- IMPLEMENTATION -->
<cc:implementation>
  <h:form id="ccForm">
  <h:panelGrid columns="3">
    <h:outputText value="Name:" />
    <h:inputText value="#{cc.attrs.name}" id="name"/>
    <h:message for="name" style="color: red" />
    <h:outputText value="Password:" />
    <h:inputText value="#{cc.attrs.password}" id="password"/>
    <h:message for="password" style="color: red" />
  </h:panelGrid>

  <h:commandButton id="loginButton"
                   action="status"
                   value="submit"/>
  </h:form>
</cc:implementation>

The changes are highlighted in bold and explained below:

  • All the parameters are explicitly specified in <cc:interface> for clarity. The third parameter has a "targets" attribute referrring to "ccForm:loginButton".
  • In <cc:implementation>
    • The <h:form> in has "id" attribute. This is required such that the button within the form can be explicitly referenced.
    • <h:inputText> is now using #{cc.attrs.xxx} instead of #{user.xxx}. #{cc.attrs} is a default EL expression that is available for composite component authors and provide access to attributes of the current composite component. In this case #{cc.attrs} has "name" and "password" defined as attributes.
    • "actionListener" is an attach point for event listener, defined as a "method-signature" and describes the signature of a method pointed to by the expression.
    • <h:commandButton> has "id" attribute so that it can be clearly identified within the <h:form>.

The "user", "password", and "actionListener" are then passed as required attributes in the "using page" as:

<ez:loginPanel
    name="#{user.name}"
    password="#{user.password}"
    actionListener="#{userService.register}"/>


Now the "using page" can pass different "backing beans" and business method to be invoked when "submit" button is invoked.

The complete source code for this TOTD can be downloaded here.

How are you using JSF 2 composite components ?

The entire source code used in this blog can be downloaded here.

JSF 2 implementation is bundled with GlassFish Server Open Source Edition, try it today!

I realized TOTD #135 already explains how to author composite components. Hey, but this TOTD provides new information on how to attach event listeners :-)

Technorati: totd javaee6 glassfish jsf2 composite component facelets

Thursday Jun 03, 2010

Jazoon 2010 Day 3 - Java EE 6 on Cloud, HTML 5 with JSF 2 and another run on Üetliberg

The Day 3 of Jazoon (Day 1 & 2) started with a great presentation on Gaia satellite and Data Processing by William O'Mullane. Gaia is a European Space Agency space mission that will be launched in Summer of 2012 to compile a catalog of approximately 1 billion stars. Most of their software is Java-based and have been fairly happy with the decision taken 10 years ago. They are very happy with the performance of Java and in certain cases its even 10x faster than C.

I gave a talk on "Running Java EE 6 applications in the Cloud". The talk explained flexibility, light-weight, extensibility, and ease-of-use of Java EE 6. It demonstrated a simple sample development and rapid deployment feature using NetBeans IDE. And then quickly jumped into how this application can be deployed on Amazon EC2, RightScale, Elastra, and Joyent infrastructure. I learned about the Simple Cloud API (Storage only) and Apache libcloud from Doug Tidwell's talk yesterday and so will try them as well.

I gave a tee-shirt from the Bay Area JUG Roundup to Rainer Grau - moderator of the conference and he was kind enough to change it for rest of the day. See his picture below.

The slides from my talk are available below:

More detailed steps to deploy your Java EE 6 application on each cloud management / provider mentioned above will be available in a later blog. Instant feedback via twitter is always much appreciated as shown in the case below:

The Spring 3.0 Themes and Trends talk was quite a dejavu because it was mostly a rehash of what is available in the Java EE 6 today. And I could not understand why would anybody use Spring (instead of Java EE) to use the goodness of the JSF and JPA technologies ?

Roger's talk on "Exploring HTML 5 with JSF 2" was very interesting and had a packed room, small but packed. He showed lots of HTML 5 samples and how Java Server Faces 2 can be used to include new tags like audio / video in a JSF composite component, Web Sockets and even Web Workers with JSF 2. His slides are available at:

Roger & I will work on publishing detailed steps on these demos in the coming days.

Spring Roo was a good one but it seems like that its basically trying to bring Ruby-on-Rails concepts like Dynamic Functions and Scaffold with some usual tooling tricks and heavy code generation to the Java programming language. One more framework, one more convention, one more programming style ... not sure if it fills any gap!

Dan & Aslak presented on Real Java EE Testing with Arquillian and this was mostly a demo-driven talk showing how different Java EE technologies can be easily tested using ShrinkWrap and Arquillian. And the cool thing is that they support deployment to GlassFish Embedded as well.

Here are some pictures from earlier today:

And the day concluded with yet another great run up Üetliberg, just a simple out & back but 1404 ft elevation gain in 4.59 miles. The elevation map is shown below:

More details about the run are given below:

Here are some pictures captured during the run:


It is just beautiful - definitely worth going at least once!

Last but not the least, Roger & I had a great dinner at au gratin - a great restaurant + adjoining bar on the first floor on Bahnhofplatz. They've got great food variety at a great location, reasonably priced (as per the Swiss standards ;-), and an American Football aficionado server by the name David. If you meet him, say our hello to him :-)

And here is the complete photo album:

This was my first Jazoon conference in the beautiful country of Switzerland and I thoroughly enjoyed it. I had some useful conversations and made some good contacts. I'd love to come back here again next year as well!

Next step Über Conf ...

Technorati: conf jazoon zurich javaee glassfish cloud amazon rightscale elastra joyent html5 jsf2 spring

Tuesday May 11, 2010

TOTD #135: JSF2 Composite Components using NetBeans IDE - lightweight Java EE 6

NetBeans IDE provide comprehensive feature set to build applications using Java Server Faces 2 (JSR 314). This Tip Of The Day (TOTD) explains how to create JSF composite components using wizards provided by the NetBeans IDE.

The JSF2 specification, section 3.6 defines composite components as:

A tree of "UIComponent" instances, rooted at a top level component, that can be thought of and used as a single component in a view. The component hierarchy of this subtree is described in the composite component defining page.

This definition is good from the specification perspective but can help with some layman explanation. Essentially, a composite component is what it says - a composition of two or more components such that it behaves like a single component. For example, consider four components in a panel grid where 2 components are "h:outputText" to display prompts and other 2 are "h:inputText" to receive input from the user. The composite components allow all of these components (1 panel grid + 2 "h:inputText" + 2 "h:outputText") packaged as a single component.

Resource Handling and Facelets, both features newly introduced in the JSF2 specification, makes the creation of composite component much easier. The Resource Handling defines a standard location for bundling resources in a web application and Facelets defines a cleaner templating language that enables composition. In technical terms:

A composite component is any Facelet markup file that resides inside of a resource library.

Lets create a simple Web application using JSF 2 that accepts a username/password and displays it in a new page. The application is first created using the traditional "h:inputText" and "h:outputText" elements and is then converted to use a composite component.

Before we dig into composite component creation using JSF2, here are the steps listed to create one using JSF 1.2:

  1. Implement UIComponent subclass
  2. Markup rendering code in Renderer
  3. Register your component and renderer in faces-config.xml
  4. Implement your JSP tag
  5. And the TLD

There is Java code involved, sub-classing from JSF classes, deployment descriptor editing in "faces-config.xml", declaring TLDs and then implementing the JSP tag. Creating a composite component in JSF 1.2 was quite a chore and spread all over. There are lots of files

With that background, lets see what it takes us to create a composite component using JSF2.

The CDI backing bean for the application looks like:

package server;

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

@Named("simplebean")
@RequestScoped
public class SimpleBean {
    String name;
    String password;

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

The "index.xhtml" Facelet markup file looks like:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html">
  <h:head>
    <title>Enter Name &amp; Password</title>
  </h:head>
  <h:body>
    <h1>Enter Name &amp; Password</h1>
    <h:form>
      <h:panelGrid columns="2">
        <h:outputText value="Name:"/>
        <h:inputText value="#{simplebean.name}" title="name" 
                     id="name" required="true"/>
        <h:outputText value="Password:"/>
        <h:inputText value="#{simplebean.password}" title="password" 
                     id="password" required="true"/>
      </h:panelGrid>
      <h:commandButton action="show" value="submit"/>
    </h:form>
  </h:body>
</html>


And the "show.xhtml" Facelet markup looks like:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html">
  <h:head>
    <title>Show Name &amp; Password</title>
  </h:head>
  <h:body>
    <h1>Show Name &amp; Password</h1>
    <h:panelGrid columns="2">
      <h:outputText value="Name:"/>
      <h:outputText value="#{simplebean.name}" />
      <h:outputText value="Password:"/>
      <h:outputText value="#{simplebean.password}" />
    </h:panelGrid>
  </h:body>
</html>



Now select the <panelGrid> fragment in "index.xhtml" as shown below:

Right-click and select "Convert To Composite Component ..." and specify the values as given in the wizard below:

Note, most of the values are default and only the "File Name:" is changed. After clicking on "Finish" in the wizard, the updated page looks like:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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:ez="http://java.sun.com/jsf/composite/ezcomp">
  <h:head>
    <title>Enter Name &amp; Password</title>
  </h:head>
  <h:body>
    <h1>Enter Name &amp; Password</h1>
    <h:form>
      <ez:username-password/>
      <h:commandButton action="show" value="submit"/>
    </h:form>
  </h:body>
</html>

The namspace/prefix "http://java.sun.com/jsf/composite/ezcomp" is added to the markup page. <ez:username-password> is the composite component used instead of those multiple components. The namespace prefix, "ez", and the tag name, "username-password", are chosen based upon the values entered in the wizard.

The JSF 2 specification, section 3.6.1.4 defines that:

The occurrence of the string “http://java.sun.com/jsf/composite/” in a Facelet XML namespace declaration means that whatever follows that last “/” is taken to be the name of a resource library.

The resource library location is relative to the Facelet markup file that is using it. So in our case, all the code is rightly encapsulated in the "resources/ezcomp/username-password.xhtml" file as:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml"
     xmlns:cc="http://java.sun.com/jsf/composite"
     xmlns:h="http://java.sun.com/jsf/html">

    <!-- INTERFACE -->
    <cc:interface>
    </cc:interface>

    <!-- IMPLEMENTATION -->
    <cc:implementation>
      <h:panelGrid columns="2">
        <h:outputText value="Name:"/>
        <h:inputText value="#{simplebean.name}" title="name"
                   id="name" required="true"/>
        <h:outputText value="Password:"/>
        <h:inputText value="#{simplebean.password}" title="password"
                   id="password" required="true"/>
      </h:panelGrid>
 </cc:implementation>
</html>

Notice, the composite component name matches the Facelet markup file name. The markup file lives in "resources/ezcomp" directory as indicated by the namespace value.

<cc:interface> defines metadata that describe the characteristics of component, such as supported attributes, facets, and attach points for event listeners. <cc:implementation> contains the markup substituted for the composite component.

The "index.xhtml" page is using the composite component and is conveniently called the using page. Similarly the "username-password.xhtml" page is defining the composite component and is conveniently called the defining page. In short, creating composite components in JSF2 requires the following steps:

  1. Move the required tags to a separate Facelet markup file, "defining page", in the "resources" directory
  2. Declare the namespace/prefix derived from "http://java.sun.com/jsf/composite" and the directory name
  3. Refer the composite component in the "using page".

Much simpler and cleaner than JSF 1.2. Are you using JSF 2 composite components ?

The entire source code used in this blog can be downloaded here.

JSF 2 implementation is bundled with GlassFish Server Open Source Edition, try it today!

Technorati: totd glassfish v3 netbeans jsf2 javaee composite components ajax

About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today