Thursday, May 24, 2012

JSF - Navigation

Let us see how to go from one page to another in JSF 2.0.

Note: JSF 1.2 had a different way of doing things

Let us create two new pages.

In your /src/main/webapp, create a file called international_greets.xhtml, like this:

 <!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"  
      xmlns:f="http://java.sun.com/jsf/core"  
      xmlns:ui="http://java.sun.com/jsf/facelets"  
      xmlns:rich="http://richfaces.org/rich">  
       <ui:composition template="/templates/template.xhtml">  
           <ui:define name="title">International Greets</ui:define>  
           <ui:define name="content">  
                <p>  
                English: Hello World!  
                <br/>  
                French: Bonjour tout le Monde!  
                <br/>  
                Italian: Buongiorno a Tutti!  
                <br/>  
                Spanish: Hola Mundo!  
                <br/>  
                Swahili: Jambo!  
                </p>  
           </ui:define>  
   </ui:composition>  
 </html>  


In your /src/main/webapp, create a file called american_greets.xhtml, like this:

 <!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"  
      xmlns:f="http://java.sun.com/jsf/core"  
      xmlns:ui="http://java.sun.com/jsf/facelets"  
      xmlns:rich="http://richfaces.org/rich">  
       <ui:composition template="/templates/template.xhtml">  
           <ui:define name="title">American Greets</ui:define>  
           <ui:define name="content">  
                <p>  
                Regular: Hi!  
                <br/>  
                Friendly: Whatsup!  
                <br/>  
                Extra Friendly: Hey, How are you doing!  
                </p>  
           </ui:define>  
   </ui:composition>  
 </html>  


Let us update our HelloBean.java to contain two new methods, which return the above pages by name.
Like this:
 package org.confucius;  
 import javax.faces.bean.ManagedBean;  
 import javax.faces.bean.SessionScoped;  
 @ManagedBean(name="helloBean")  
 @SessionScoped  
 public class HelloBean {  
      private String greeting;  
      public HelloBean(){  
           this.greeting = "Hello World JSF!";  
      }  
      public String getGreeting() {  
           return this.greeting;  
      }  
      public void setGreeting(String greeting) {  
           this.greeting = greeting;  
      }  
      public String getInternationalGreets() {  
           return "international_greets";  
      }  
      public String getAmericanGreets() {  
           return "american_greets";  
      }  
 }  

 Now, let us update out greet.xhtml to contain two buttons, which call the above methods.
 <!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"  
      xmlns:f="http://java.sun.com/jsf/core"  
      xmlns:ui="http://java.sun.com/jsf/facelets"  
      xmlns:rich="http://richfaces.org/rich">  
       <ui:composition template="/templates/template.xhtml">  
           <ui:define name="title">JSF</ui:define>  
           <ui:define name="content">  
                <h1>#{helloBean.greeting}</h1>  
                <h:form>  
                     <h:commandButton value="Show International Greets" type="submit" action="#{helloBean.getInternationalGreets}" />  
                     <h:commandButton value="Show American Greets" type="submit" action="#{helloBean.getAmericanGreets}" />  
                </h:form>  
           </ui:define>  
   </ui:composition>  
 </html>  

Note that the Buttons have to be enclosed in a Form, otherwise they won't take effect.
This is a very common source of bugs!

If you rebuild and redeploy HelloWorldJSF, you will see the new buttons, which, when clicked direct you to the new pages.

JSF automatically assumes that the return values of the methods are names of pages, extension (.faces) is not required

Important Note:
Sometimes we use the full method name in the EL, like #{helloBean.getAmericanGreets}, while other times we leave out the 'get' part, like #{helloBean.greeting}. Why?

This is because when specified as an action, EL looks for a method with the exact name. When used outside an action specification, EL assumes it is a property field of the bean, and looks for the 'get' method.

Wednesday, May 23, 2012

JSF - Richfaces

Let us use a Richfaces component - Collapsible Panel to create some "special effects" in our UI.

Update your template.xhtml to envelope the content inside a Collapsible Panel, like this:
 <!DOCTYPE html>  
 <html xmlns="http://www.w3.org/1999/xhtml"  
      xmlns:h="http://java.sun.com/jsf/html"  
      xmlns:f="http://java.sun.com/jsf/core"  
      xmlns:ui="http://java.sun.com/jsf/facelets"  
      xmlns:rich="http://richfaces.org/rich">  
   
      <h:head>  
           <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
           <title><ui:insert name="title">Default Title</ui:insert></title>  
      </h:head>  
   
      <h:body>  
           <h3>Basic Java Series</h3>  
           <rich:collapsiblePanel header="RichFaces Greeter" switchType="client">  
                <ui:insert name="content">Default content</ui:insert>  
           </rich:collapsiblePanel>       
           <p>Visit us at www.projectconfucius.org</p>  
      </h:body>  
 </html>  
   

Notice that we are including the richfaces tag library.

The "switchType" attribute specifies that the collapsibility should be managed in the browser, with no AJAX calls to the server. This makes the client respond faster, and the "View State" of the component is saved on the client side.

Let us also update our web.xml to choose a "skin" for richfaces - this customizes the look-and-feel of Richfaces components.

Your web.xml will not look like this:
 <?xml version="1.0" encoding="UTF-8"?>  
 <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
   
   <context-param>  
     <param-name>org.richfaces.skin</param-name>  
     <param-value>blueSky</param-value>  
   </context-param>    
   
   <servlet>  
     <servlet-name>Faces Servlet</servlet-name>  
     <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>  
     <load-on-startup>1</load-on-startup>  
   </servlet>  
   
   <servlet-mapping>  
     <servlet-name>Faces Servlet</servlet-name>  
     <url-pattern>*.faces</url-pattern>  
   </servlet-mapping>  
   
   <welcome-file-list>  
     <welcome-file>greet.faces</welcome-file>  
   </welcome-file-list>  
   
 </web-app>  
   

If you rebuild and redeploy HelloWorldJSF, you will see  Richfaces Collapsible Panel, with a sky blue header, which collapses if you click on it.

JSF - Facelets

Facelets is a 'templating' technology for JSF - it allows us to:
  • Write XHTML files
  • Use JSF EL expressions to call methods on JSF Beans
  • Divide and Rule - compose pages from smaller XHTML pages
  • Use JSF Rich components 
We already saw the first two, now lets see how to compose pages from smaller XHTML pages.

This feature is very similar to Apache Tiles framework that we saw earlier in this post.

Let us suppose that we will need to create several pages with the same layout, but different content.

In your /src/main/webapp folder, create a folder 'template'

In /src/main/wepapp/template, create a file template.xhtml, like this:
 <!DOCTYPE html>  
 <html xmlns="http://www.w3.org/1999/xhtml"  
      xmlns:h="http://java.sun.com/jsf/html"  
      xmlns:f="http://java.sun.com/jsf/core"  
      xmlns:ui="http://java.sun.com/jsf/facelets">  
   
      <h:head>  
           <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
           <title><ui:insert name="title">Default Title</ui:insert></title>  
      </h:head>  
   
      <h:body>  
           <h3>Basic Java Series</h3>  
           <ui:insert name="content">Default content</ui:insert>  
           <p>Visit us at www.projectconfucius.org</p>  
      </h:body>  
 </html>  
   

Notice that we have included the facelets tag library, under the name space 'ui'.

All our pages can use this template which automatically generates a header ("Basic Java Series") and footer ("Visit us..").

Each page can define its own title and content. We use the ui:insert tag to specify points at which a child XHTML page can insert its own content.

Let us update greet.xhtml to use this template, like this:
 <!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"  
      xmlns:f="http://java.sun.com/jsf/core"  
      xmlns:ui="http://java.sun.com/jsf/facelets">  
   
       <ui:composition template="/templates/template.xhtml">  
   
           <ui:define name="title">JSF</ui:define>  
   
           <ui:define name="content">  
                <h1>#{helloBean.greeting}</h1>  
           </ui:define>  
   
   </ui:composition>  
 </html>  

We are using the ui:define tag to insert a title and content into the template.

If you now build and deploy HelloWorldJSF, and point your browser to:
http://localhost:8080/HelloWorldJSF/

you will see "Hello World, JSF!"  printed between the header and footer.
Notice also that the page title is now "JSF".

JSF - Bean Declaration

JSF allows you to declare your class as a Bean, then call its methods from the XHTML.

Under /src/main, create a Source Folder called 'java'
(R-click on /src/main, select New-->Other, then select Java-->Source Folder)

In /src/main/java, create a class HelloBean.java in a package org.confucius
(R-click on /src/main/java, select New-->Other, then select Java-->Class)

The class looks like this:
 package org.confucius;  
   
 import javax.faces.bean.ManagedBean;  
 import javax.faces.bean.SessionScoped;  
   
 @ManagedBean(name="helloBean")  
 @SessionScoped  
 public class HelloBean {  
      private String greeting;  
   
      public HelloBean(){  
           this.greeting = "Hello World JSF!";  
      }  
        
      public String getGreeting() {  
           return this.greeting;  
      }  
   
      public void setGreeting(String greeting) {  
           this.greeting = greeting;  
      }  
 }  
   

Note the annotations that declare this class to be a JSF Bean named "helloBean".

We will describe annotations in detail in an upcoming post. For now, note that annotations are like inline-configurations. Any framework can define its unique set of annotations. For the Java compiler, the annotations are like comments - it more or less ignores them. But it lets the framework know of the annotations and the framework can take whatever action it needs to take. In this case, JSF framework will look at the annotations and create a bean with the name 'helloBean' and make it session-scoped.


This bean is Session-scoped which means that its state will be maintained for the duration of the HTTP session.

We can now access the methods of this Bean from our XHTMLs.

Update greet.xhtml like this:
 <!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"  
      xmlns:f="http://java.sun.com/jsf/core">  
   
   <h:body>  
           <h1>#{helloBean.greeting}</h1>  
      </h:body>  
 </html>  

This style of using #{expression} for calling a Bean's method is called JSF EL (Expression Language).
Facelets view handler will do the needful to convert the EL expression to appropriate content. 

If you rebuild and deploy HelloWorldJSF and point your browser to:
http://localhost:8080/HelloWorldJSF/

You will see "Hello World, JSF!" displayed.

JSF Hello World - Setup

Let us setup a JSF project using Maven.

Note that there are several open source projects which make JSF component libraries - like Trinidad, Tobago, Tomahawk, Openfaces, IceFaces.

In this project we will use JBoss Richfaces, which is one of the most popular ones and has a pretty big set of components.

In Eclipse, go to File --> New Project --> Maven Project

Use the maven-archetype-webapp

Specify:
Group Id: org.confucius
Artfact Id: HelloWorldJSF
Package: org.confucius

Once the project is created, we will update the pom.xml to include all the necessary JSF and Richfaces libraries.

So your pom.xml will now look like this:
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">  
       <modelVersion>4.0.0</modelVersion>  
       <groupId>org.confucius</groupId>  
       <artifactId>HelloWorldJSF</artifactId>  
       <packaging>war</packaging>  
       <version>0.0.1-SNAPSHOT</version>  
          
   <build>  
     <finalName>HelloWorldJSF</finalName>  
   </build>  
   
        <dependencyManagement>  
     <dependencies>  
       <dependency>  
         <groupId>org.richfaces</groupId>  
         <artifactId>richfaces-bom</artifactId>  
         <version>4.2.2.Final</version>  
         <scope>import</scope>  
         <type>pom</type>  
       </dependency>  
     </dependencies>  
   </dependencyManagement>  
   
   <dependencies>  
     <dependency>  
       <groupId>org.richfaces.ui</groupId>  
       <artifactId>richfaces-components-ui</artifactId>  
     </dependency>  
     <dependency>  
       <groupId>org.richfaces.core</groupId>  
       <artifactId>richfaces-core-impl</artifactId>  
     </dependency>  
     <dependency>  
       <groupId>javax.faces</groupId>  
       <artifactId>javax.faces-api</artifactId>  
       <scope>provided</scope>  
     </dependency>  
     <dependency>  
       <groupId>org.glassfish</groupId>  
       <artifactId>javax.faces</artifactId>  
       <scope>compile</scope>  
     </dependency>  
     <dependency>  
       <groupId>javax.servlet</groupId>  
       <artifactId>javax.servlet-api</artifactId>  
       <scope>provided</scope>  
     </dependency>  
     <dependency>  
       <groupId>javax.servlet.jsp</groupId>  
       <artifactId>jsp-api</artifactId>  
       <scope>provided</scope>  
     </dependency>  
     <dependency>  
       <groupId>javax.el</groupId>  
       <artifactId>el-api</artifactId>  
       <scope>provided</scope>  
     </dependency>  
     <dependency>  
       <groupId>javax.servlet.jsp.jstl</groupId>  
       <artifactId>jstl-api</artifactId>  
     </dependency>     
     <dependency>  
       <groupId>net.sf.ehcache</groupId>  
       <artifactId>ehcache</artifactId>  
     </dependency>  
   </dependencies>  
    
 </project> 

Notice that we are using a BOM (Bill of Materials), which is a Maven construct for projects that are version sensitive. BOMs specify the versions of its dependencies.

Explanation:
A specific version of RichFaces requires certain specific version of its dependencies. Mismatch in dependency versions can cause issues. For this reason, Richfaces defines a BOM which defines the versions of its dependencies. Therefore, in our POM, we do not need to specify the dependency versions.

Next, we need to update our web.xml to use JSF.

Your web.xml will now look like this:
 <?xml version="1.0" encoding="UTF-8"?>  
 <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
   
   <servlet>  
     <servlet-name>Faces Servlet</servlet-name>  
     <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>  
     <load-on-startup>1</load-on-startup>  
   </servlet>  
   
   <servlet-mapping>  
     <servlet-name>Faces Servlet</servlet-name>  
     <url-pattern>*.faces</url-pattern>  
   </servlet-mapping>  
   
   <welcome-file-list>  
     <welcome-file>greet.faces</welcome-file>  
   </welcome-file-list>  
   
 </web-app>  
   

We direct all URLs which end in *.faces to be handled by JSF servlet.

Also, note that we have defined greet.faces as our welcome file.

However, we will never create a file called greet.faces - we will create one called greet.xhtml.

Whenever JSF sees a request for a file called foo.faces, it actually picks up foo.xhtml, sends it to the Facelets view handler which renders foo.html, which is sent back to the browser.

In your /src/main/webapp folder, create a file greet.xhtml, like this:
 <!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"  
      xmlns:f="http://java.sun.com/jsf/core">  
   
   <h:body>  
           <h1>Hello World!</h1>  
      </h:body>  
 </html>  

Note that an XHTML file looks just like a HTML file.

Note also that we have included two JSF tag libraries - HTML and Core. These tag libraries gives enhanced functionality over regular HTML tags.

Our JSF project is now setup.

If you build and deploy the project, and browse to
http://localhost:8080/HelloWorldJSF/

You will see "Hello World!" displayed.

JSF - Java Server Faces

JSF, a Sun standard View Technology., solves the Rich UI problem in the following ways:

1. JSF separates the "Rich component" developers from UI developers.

The Rich component developers deal with all the javascript and make the components cross-browser compatible. They provide a custom tag library which allows UI developers to use the components.

2. JSF provides a templating technology called Facelets.

Facelets files are .xhtml files which look just like regular HTML files. UI developers can use the custom tags provided by the Rich component developers to put components in their pages.

At run time, Facelets renders the final HTML page which is seen on the browser, replacing the custom tags with appropriate HTML tags and java scripts (as specified by the Rich component developers).

3. JSF provides a Bean container, so that any Java class on the server can be declared to be a JSF bean. And a rich component can call methods on the JSF Bean.

Internally, JSF generates all the necessary AJAX calls to make the communication between browser and server possible.

4. JSF allows page navigation to be declared in an XML file (faces-config.xml)

At run time, JSF will read the navigation file and display the appropriate pages to the user.

5. JSF maintains the state of the Beans and also of the View.

No effort is needed on part of the application developer.

View Technologies & Rich User Interfaces

The original Web UI was envisioned as hypertext, cross referencing, static web pages (sometimes called Web 1.0).

But things quickly progressed beyond that to give highly interactive, dynamically generated web pages with cool animation effects (sometimes called Web 2.0).

The technology which enabled this transition is javascript, which was a simple scripting language originally developed for small dynamic web page modifications, but people pushed it to its limits and beyond.

Such web interfaces are often called "Rich UI" and "Rich Application" because they display all kinds of special effects like collapsible Window Panels, Drag-n-Drop lists, interactive Charts, Dynamic Trees, Color themes, etc.

The components which display such complex dynamic effects are called "Rich components", and sometimes "Widgets".

Developing a Rich UI comes with a new set of challenges:

1. Developing complex javascript is not easy. It requires a lot of experience, it is not easy to debug and can result in unexpected behaviors in different browsers.

2. Rich components typically need to use AJAX to communicate with servers, which makes things more tricky.

3. In addition to application state, there is an additional need to maintain state of the Rich components (sometimes called View state)

4. There is always the browser "back" button which messes the view.

5. Finding an easy, seamless way for rich components to interact smoothly with Java objects on the application server is not trivial.

6. In the absence of ordinary hyperlinks, defining navigation between pages becomes a job in itself.

All these challenges led to the development of new frameworks for developing the front-end. These are often called "View Technologies".


In the coming posts, we will look at 3 of the most prominent view technologies:

 * JSF - Java Server Faces, is a Sun standard, and more widely used.

* Apache Tapestry, is the easiest to use and more elegant than JSF.

* GWT - Google Web Toolkit, is the most scalable.