JSF 2.0 with Maven 2 plugins for Glassfish v3, Jetty and Tomcat





In this post I'm going to demonstrate how JSF 2.0 "Hello World" application could be developed with the Maven 2 plugins for Jetty, Tomcat and Glassfish v3. The application consists of two pages and request scoped managed bean. The first page ( hello.xhtml ) asks the user "What's your name?", validates the input , then the second page ( response.xhtml ) greets the user with "Hi". The two pages share common layout defined in template.xhtml and request scoped managed bean HelloWorld.java exposed under name "hi". The titles of the pages are set with UL expression #{hi.greetFrom('greeting passed as parameter')}. The template loads its css and also one image file with the new ResourceHandler API.

Prerequisites:
* Basic knowladge of Java and Maven 2.
* Installed Maven 2 ( http://maven.apache.org ). The sample was tested with version 2.2.1

Quick start:
The source can be downloaded from here.

or could be checkout with subversion from:
http://sandcode.googlecode.com/svn/trunk/jsf2/helloworld

Run the sample with one of the following commands :

* mvn package tomcat:run-war
* mvn package jetty:run-war
* mvn package -Pglassfish


In your browser type the URL : http://localhost:8080/helloworld


Some details :

In the pom.xml file there are defined two profiles.


1. The first profile <id>default</id> is active by default and is needed for running the application with servlet container like tomcat or jetty.

The needed dependencies are :

<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>[2.0.1,)</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>[2.0.1,)</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>el-impl</artifactId>
<version>2.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>


The Tomcat plugin is defined by :

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>tomcat-maven-plugin</artifactId>
<configuration>
<path>/${project.build.finalName}</path>
<!-- Embedded port -->
<port>8080</port>
</configuration>
</plugin>

Details about the Tomcat plugin you can find at :
http://mojo.codehaus.org/tomcat-maven-plugin/index.html


The Jetty plugin is defined by :

<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<configuration>
<!-- Delete this block to have Jetty run default port (8080) -->
<connectors>
<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
<port>8080</port>
</connector>
</connectors>
<!-- force friendly name instead of artifact name + version -->
<contextPath>${project.build.finalName}</contextPath>
<!-- This parameter will auto-deploy modified classes. -->
<!-- You can save changes in a file or class and refresh your browser to view the changes. -->
<scanIntervalSeconds>3</scanIntervalSeconds>
</configuration>
</plugin>

Details about the Jetty plugin you can find at :
http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin
http://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin

2. The second profile <id>glassfish</id> is needed for running the application with JEE compatible server. In our case I'm using embedded Glassfish v3.
The only needed dependency is :


<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>


And the GLassfish plugin is defined by :


<plugin>
<groupId>org.glassfish</groupId>
<artifactId>maven-embedded-glassfish-plugin</artifactId>
<version>3.0</version>
<configuration>
<app>${project.build.directory}/${build.finalName}.war</app>
<port>8080</port>
<contextRoot>${build.finalName}</contextRoot>
<autoDelete>true</autoDelete>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>


that plugin is binded to the 'package' phase of maven for convenience. It could be executed also with :

mvn -Pglassfish embedded-glassfish:run

Details about the glassfish plugin you can find at :

http://docs.sun.com/app/docs/doc/821-1208/gijhs?a=view
http://docs.sun.com/app/docs/coll/1343.9 - section "Sun GlassFish Enterprise Server v3 Embedded Server Guide"


Interesing part of the web.xml is the following context parameter :


<context-param>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>


It is needed by JSF when running under tomcat or jetty, so that faces could load the UL v2.2, which is needed for passing parameters in the EL expressions in the xhtmls.
Also when running under plain servlet container the following dependency is needed:


<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>el-impl</artifactId>
<version>2.2</version>
<scope>runtime</scope>
</dependency>

Example of passing parameters (from hello.xhtml):


<ui:define name="top">
#{hi.greetFrom('initial page')}
</ui:define>


Where 'greetFrom' method is defined in HelloWorld.java :


@ManagedBean(name = "hi")
@RequestScoped
public class HelloWorld {
...

public String greetFrom(String pageName) {
return "Hello World ! ( " + pageName + " )";
}

...
}


In JSF 2.0 one of the most powerful features is the PDL (Page Description Language), and especially the possibility for encapsulating common fragmets of a page in 'templates'.

In the sample you can see the usage of the template.xhtml :


<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>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="#{resource['css/default.css']}" rel="stylesheet" type="text/css" />
<link href="#{resource['css/cssLayout.css']}" rel="stylesheet" type="text/css" />
<title>Hello World (facelets template)</title>
</h:head>

<h:body>

<div id="top" class="top">
<div class="left"><h:graphicImage url="#{resource['delta.png']}" /></div>
<div class="right"><h2><ui:insert name="top">Top</ui:insert></h2></div>
<div style="clear:both"></div>
</div>

<div id="content" class="center_content">
<ui:insert name="content">Content</ui:insert>
</div>

</h:body>

</html>


in hello.xhtml :


<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
template="./template.xhtml">

<ui:define name="top">
#{hi.greetFrom('initial page')}
</ui:define>

<ui:define name="content">
<h2>What's your name?</h2>
<h:form id="helloForm" >
<h:inputText id="username" value="#{hi.name}" required="true"/>

<h:commandButton id="submit" action="response" value="Submit"/><br/>
<h:message for="username" styleClass="error"/>
</h:form>
</ui:define>

</ui:composition>


and in response.xhtml:


<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
template="./template.xhtml">

<ui:define name="top">
#{hi.greetFrom('response page')}
</ui:define>

<ui:define name="content">
<h:form id="responseform">
<h2>Hi, #{hi.name} !</h2>
<h:commandButton id="back" value="Back" action="hello" />
</h:form>
</ui:define>

</ui:composition>


More about the new features of JSF 2.0 you can read here :

http://andyschwartz.wordpress.com/2009/07/31/whats-new-in-jsf-2/

Comments

  1. An embedded Glassfish plugin for Maven...finally. I didn't know it existed. This should be publicized more.

    ReplyDelete
  2. If you are using GF v3, you could also use the Web Profile dependency. This makes it easier.


    javax
    javaee-web-api
    provided
    6.0

    ReplyDelete
  3. Your project doesn't run in "plain" Tomcat 6 for two things:

    1. Add dependency to JSTL 1.2
    2. The new el-api and el-impl conflicts with Tomcat. Must modify the Tomcat instance, replace the old EL libraries with new version (2.2) from glassfish

    ReplyDelete
  4. When I finally get this running, the textbox under "What's your name?" shows:

    "null person size=0"

    weird... or is it intentional?

    ReplyDelete
  5. This is very interesting - thanks a lot! I just checked out from SVN, and Glassfish and Jetty runs, but "mvn tomcat:run" fails with

    org.apache.jasper.JasperException: The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application
    org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:51)
    org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:409)
    org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:116)
    org.apache.jasper.compiler.TagLibraryInfoImpl.generateTLDLocation(TagLibraryInfoImpl.java:315)
    org.apache.jasper.compiler.TagLibraryInfoImpl.(TagLibraryInfoImpl.java:148)

    ReplyDelete

Popular posts from this blog

JSF 2.0 with Spring 3 and Spring Security 3 on Google Application Engine

Extreme productivity for Primefaces