Programming
13 May 2012 7 Comments

Hello World with JSF 2.0, Glassfish 3, Maven, SVN and Eclipse

Introduction

Serious Java Web application development requires a lot of different applications. In addition to a JDK, an IDE and an application server you may need a Web application framework, a build system and some form of version control. Unsurprisingly, getting set up for development can be quite the task.

In this post we’ll take a look at setting up a Web application project from start to finish. The software we will use is:

Application Download
Java EE 6 SDK with JDK 7 U3 www.oracle.com
Maven 3.0.4 maven.apache.org
Glassfish Server Open Source Edition 3.1.2 glassfish.java.net
JSF 2.0 Libraries included with Glassfish.
Eclipse 3.7 www.eclipse.org

What Are We Building?

Different applications come in different forms.

  • A Windows application written in C++ may be compiled to a .exe file.
  • Runnable Java GUI applications often come in a JAR (Java ARchive).
  • Java Web applications are packaged in WAR and EAR files.

We are building a Web application, so the product of building our project will be a WAR file. The Glassfish application server extracts a WAR file and runs the application inside it. The WAR file also contains a deployment descriptor, web.xml that describes how the application server should run the WAR.

The structure of a WAR file looks like this (source):

Project Setup with Maven Archetypes

Now that we know what we are building, it is time to start setting up the project. The directory/file structure of the project we are creating is very different from the structure of the WAR file. Our build tool, Maven, makes the ‘translation’ between the project structure and the WAR structure. It takes care of compiling and packaging up the files in the project into a valid WAR file that is ready for deployment.

We don’t have to start completely from scratch with the project. Maven can download pre-made, barebones projects called archetypes. Archetypes are nothing more than a bunch of files and folders that are packaged up and given a name.

There are currently 588 archetypes, 21 of which contain “jsf” in their name. Most of these archetypes are quite heavyweight: they come with pretty big pom.xml files. Instead of using these, we will start off with a very basic non-jsf archetype, and add only the things we really need.

First we will download the archetype maven-archetype-webapp with the mvn archetype:generate command. Be be sure to choose a fitting groupId and artifactId:

>mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom >>>
...
[INFO] Generating project in Interactive mode
Define value for property 'groupId': : mygroup.com
Define value for property 'artifactId': : myprojectname
Define value for property 'version':  1.0-SNAPSHOT: :
Define value for property 'package':  mygroup.com: :
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

This creates a very simple Mavenized Web application project in a directory named myprojectname. The contents of this folder are:

Note
Usually, archetypes contain a pom.xml file, meaning they are Maven projects. But this does not have to be the case. In theory, an archetype can be any set of files and folders.

The default pom.xml file is very simple, containing only one dependency. The packaging type is set to war, which is what we need.

 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">
  >4.0.0>
  >mygroup.com>
  >myprojectname>
  >war>
  >1.0-SNAPSHOT>
  >myprojectname Maven Webapp>
  >http://maven.apache.org>
  >
    >
      >junit>
      >junit>
      >3.8.1>
      >test>
    >
  >
  >
    >myprojectname>
  >
>

Adding Dependencies To POM

Our project will use JSF 2.0 web framework, and run on the Glassfish application server. JSF is part of the standard Java EE platform, which means it’s built-in to any compliant Java EE application server, such as Oracle’s WebLogic, GlassFish Open Source Edition, or JBoss AS. But it can also be used as a standalone library in servlet containers such as Tomcat and Jetty.

In order to be able use JSF (the javax.faces package) in our source code we must add a dependency for it in the pom.xml. Add this dependency for the entire Java EE 6 API (including JSF and CDI):

>
    >javax>
    >javaee-api>
    >6.0>
    >provided>
>

The provided scope means that Maven assumes the dependency is provided by the application server at run-time. Maven will only add the JAR to the classpath for compilation and testing phases, but it will not be included in the WAR file. This is what we want, because Glassfish 3 contains a full Java EE implementation including JSF 2.0.

Configuring the Deployment Descriptor

A deployment descriptor describes how a Web application should be deployed. In the past, using a web.xml file in the WEB-INF directory was required. However, with the new features in the Servlet 3.0 specification in Java EE 6 it has become possible to use annotations instead of XML configuration files such as web.xml. It doesn’t mean the web.xml is now obsolete, but its size can be reduced. Information specified in the deployment descriptor takes precedence over the information specified through Annotations.

Part of the deployment descriptor are servlet mappings that describe which URLs are passed to the Faces Servlet. Some application servers (including GlassFish) automatically provide a servlet mapping for the /faces/*, *.faces, and *.jsf patterns. The *.jsf pattern means that a request to http://localhost/myprojectname/index.jsf is passed to the Faces Servlet. By default, the Faces Servlet then looks for a file but with a .jsp

Discard the outdated web.xml that came with the archetype, and replace it with this web.xml:

 version="1.0" encoding="ISO-8859-1"?>
 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_3_0.xsd"
      version="3.0">
>
    >Faces Servlet>
    >javax.faces.webapp.FacesServlet>
>
>
    >Faces Servlet>
    >*.xhtml>
>
>
    >javax.faces.DEFAULT_SUFFIX>
    >.xhtml>
>
>

This instructs the application server to pass .xhtml requests to the Faces Servlet, and to let the Faces Servlet look for .xhtml files on the filesystem.

Adding a Bean

A bean is a Java class that is managed by the JSF framework, and can be referenced from JSF pages using the bean name. It is a historical accident that there are two separate mechanisms, CDI beans and JSF managed beans, for beans that can be used in JSF pages. The consensus for Java EE 6 seems to be CDI beans, so we will use that method.

In previous JSF versions, each bean had to be declared in a faces-config.xml file. Thankfully we now have annotations, which makes this file obsolete in most cases. Create a new source file at /src/main/java/com/mygroup/Hello.java.

package com.mygroup;
 
import javax.inject.Named;
 
@Named
public class HelloBean
{
    public String getGreeting() 
    {
        return "Hello World!";
    }
}

The @Named annotation means the class is a CDI bean. One thing we need to do now is tell the server that this project is a module containing CDI beans. To do this, we add an empty file called beans.xml to the project at /src/main/webapp/WEB-INF/beans.xml.

Note
Make sure you have created the beans.xml file, or the project will not work. It may seem silly that an empty file is so important, but there are convincing reasons for this behavior. They are described here.

Adding a JSF Page

We have defined in the web.xml file that our views use the .xhtml extension. So we remove the /src/main/webapp/index.jsp file that came with the archetype, and create a new file /src/main/webapp/index.xhtml.


        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
 xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
 
>
  >My JSF Page>
>
>
    

>

Bean Test> value="HelloBean says: #{helloBean.greeting}" /> > >
  • Since this is a JSF page, we can use h:, f: and ui: tags. These tags will be processed by the Faces Servlet.
  • The EL statement #{helloBean.greeting} is evaluated when the page is requested. This should call the getGreeting() method of the HelloBean class.

The completed project should look like this:

Deploying Manually In Glassfish 3

OK, now we should have a working JSF/Maven project. Let's try to deploy and run it manually before we import it into Eclipse.

Package the project into a WAR file with the mvn package command:

>mvn package
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

This builds the project into a WAR file at /target/myprojectname.war.

Next, we start up a Glassfish 3 server with the asadmin start-domain command.

asadmin start-domain --verbose domain1

Now copy the WAR file to the autodeploy directory of your domain directory, e.g. glassfish/domains/domain1/autodeploy. You will see some output from the asadmin process, which can help identify any problems with the project. Let's assume that things didn't blow up in your face and the deployment was succesful, and you see something like this:

[#|2012-05-12T23:40:30.620+0200|INFO|glassfish3.1.2
|[AutoDeploy] Successfully autodeployed : C:\glassfish3\glassfish\domains\domain1\autodeploy\myprojectname.war.|#]

Now open a browser and open the page, e.g. at http://localhost:8080/myprojectname/index.xhtml. You should see "HelloBean says: Hello World".

Importing Into Eclipse

Now that we have a working JSF/Maven project, it is time to import the project into Eclipse.

Note
Although many guides on the internet (wrongly) recommend it, you should not use the mvn eclipse:eclipse command to create the Eclipse project. This plugin can only generate WTP projects for very old Eclipse versions (WTP 2.0 is the maximum). Instead, use the m2eclipse plugin as described in this section.

Set Java version in POM to 1.6

It is a good idea to tie the project to a specific JDK version, to ensure the build stays the same when a newer JDK version is used. We do this by adding some parameters for the maven-compiler-plugin to our pom. Since we are developing for Java EE 6, we will specify version 1.6. Change the section to this:

  >
    >
      >
        >maven-compiler-plugin>
        >
          >1.6>
          >1.6>
        >
      >
    >
    >myprojectname>
  >

Install Eclipse Plugins

For JSF development you need the Java EE version of Eclipse, for this guide Eclipse Indigo SR2 was used. After installing Eclipse we need to add three plugins through Help -> Eclipse Marketplace.

  • Subclipse: This plugin provides SVN integration.
  • Maven Integration for Eclipse (a.k.a. m2eclipse): This plugin adds basic Maven support to Eclipse. Obviously.
  • Maven Integration for Eclipse WTP (a.k.a. m2e-wtp): This plugin integrates m2eclipse with the Web Tools Project, which handles Web application specific stuff in Eclipse.

Import the Project

Go to File -> Import, and choose Existing Maven Projects. Browse to the directory where the pom.xml is located, and click Finish. The project should now be imported, and initialized.

If we look at the Project Facets (under Project -> Properties) we see that the Java version has been correctly set to 1.6, and the Dynamic Web Module is set to support Servlet 3.0.

Installing Glassfish Support

Eclipse does not come with pre-installed Glassfish server support, but fortunately this can be added with a few clicks.

  1. Open the Servers view through Window -> Show View -> Others.
  2. Right-click in the Servers view and select New -> Server.
  3. Click "Download additional server adapters" in the top-right and install the "Oracle Glassfish Server Tools" module.

Deploying to Glassfish

Create a new Glassfish server instance through the Servers view. We choose the latest available Glassfish edition, in my case it was Glassfish 3.1.2. Then we are prompted for the installation directory of the server. We can either select the path of an existing Glassfish installation, or choose an empty directory and click "Install Server" to make Eclipse download a fresh installation for us.

Now we can add a project to the Glassfish server by right-clicking it and choosing Add and Remove...:

Start the server, and your project will be served by Glassfish!

Add Project to SVN

As a final step we can upload the project to an SVN repository, so we can work on it with others and keep a history of the code. A detailed description of the process can be found in another post on this blog. Be sure to the add target directory to svn:ignore by rightclicking it and selecting Team -> Add to svn ignore...

In order for other developers to immediately have a working project, we will need to upload all other project files, including .project, .classpath and the .settings directory. Of course the other developers will also need to have the same plugins installed.

7 Responses to “Hello World with JSF 2.0, Glassfish 3, Maven, SVN and Eclipse”

  1. kungcc 16 June 2012 at 9:10 pm #

    This was the best guide ever! Many thanks, you saved me a lot of work! =)

    • tboerman 17 June 2012 at 1:31 am #

      Glad you found it useful ;)

  2. MikeL 26 July 2012 at 1:59 am #

    Exactly what I was looking for. Now to add Spring3 and Hibernate4 to this… One question I have has to deal with ProjectFacets.png. Mine had JavaServer Faces 2.0 checked where yours does not. I also attempted to change it to 2.1 and eclipse won’t allow it. Any ideas?

  3. julius 5 August 2012 at 8:42 am #

    testing this on a uptodate ubuntu 12.04 with java 1.6 i get:

    mvn package
    [INFO] Scanning for projects…
    [INFO] ————————————————————————
    [INFO] Building myprojectname Maven Webapp
    [INFO] task-segment: [package]
    [INFO] ————————————————————————
    [INFO] [resources:resources {execution: default-resources}]
    [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
    [INFO] Copying 0 resource
    [INFO] [compiler:compile {execution: default-compile}]
    [INFO] Compiling 1 source file to /home/julius/jsftest/myprojectname/target/classes
    [INFO] ————————————————————————
    [ERROR] BUILD FAILURE
    [INFO] ————————————————————————
    [INFO] Compilation failure
    /home/julius/jsftest/myprojectname/src/main/java/com/mygroup/Hello.java:[5,1] annotations are not supported in -source 1.3
    (use -source 5 or higher to enable annotations)
    @Named

    [INFO] ————————————————————————
    [INFO] For more information, run Maven with the -e switch
    [INFO] ————————————————————————
    [INFO] Total time: 2 seconds
    [INFO] Finished at: Sun Aug 05 10:42:28 CEST 2012
    [INFO] Final Memory: 10M/89M

  4. Nebar 19 September 2012 at 2:30 pm #

    Excelente tutorial,muy buena explicación, no se mecaniza , entendible. Muchas gracias.

  5. Emmanuel 6 November 2012 at 12:36 am #

    I had the same issue than julius, then, from the blog of mkyong:
    http://www.mkyong.com/jsf2/jsf-2-0-hello-world-example/

    i add this between … and work!

    org.apache.maven.plugins
    maven-compiler-plugin
    2.3.1

    1.6
    1.6