Sunday, January 13, 2013

How to create a new JSF 2.1 project and deploy it in JBoss 7 AS

In this post I want  to document the process that needs to be done for creating JSF 2.1 project that supports servlet 3.x .
Also I will briefly explain how to install JBoss 7 AS and deploy the app.

Minimum requirements: JDK 6, maven 3,eclipse IDE, m2e plugin installed in eclipse

Creating a JSF 2.1 project

From your terminal, navigate to your workspace and execute the following command(change the name of the package and project with your own)
 mvn archetype:generate -DinteractiveMode=n -DarchetypeArtifactId=maven-archetype-webapp -Dversion=0.0.1-SNAPSHOT -DgroupId=com.yourpackagename -DartifactId=your_project_name  

Import the project in your eclipse IDE


Include the source folder src/test/resources 
This step maybe is not needed(depending the version of eclipse you are using), but my eclipse(STS-Juno) does not show some of the source folders when importing a maven project.
If you are experiencing this issue also, the way to solve it is:

right click on project->Build Path->New Source Folder...

This will make eclipse show all the required source folders. This is how it should look like:
In the pom.xml we need to add the JSF 2.1 dependencies and also the maven-compiler-plugin.
It should 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>com.yourpackagename</groupId>  
      <artifactId>your_project_name</artifactId>  
      <packaging>war</packaging>  
      <version>0.0.1-SNAPSHOT</version>  
      <name>your_project_name Maven Webapp</name>  
      <url>http://maven.apache.org</url>  
      <repositories>  
           <repository>  
                <id>maven2-repository.dev.java.net</id>  
                <name>Java.net Repository for Maven</name>  
                <url>http://download.java.net/maven/2</url>  
           </repository>  
      </repositories>  
      <dependencies>  
           <dependency>  
                <groupId>com.sun.faces</groupId>  
                <artifactId>jsf-api</artifactId>  
                <version>2.1.0-b03</version>  
                <scope>compile</scope>  
           </dependency>  
           <dependency>  
                <groupId>com.sun.faces</groupId>  
                <artifactId>jsf-impl</artifactId>  
                <version>2.1.0-b03</version>  
                <scope>compile</scope>  
           </dependency>  
           <dependency>  
                <groupId>javax.servlet</groupId>  
                <artifactId>jstl</artifactId>  
                <version>1.2</version>  
           </dependency>  
           <dependency>  
                <groupId>junit</groupId>  
                <artifactId>junit</artifactId>  
                <version>3.8.1</version>  
                <scope>test</scope>  
           </dependency>  
      </dependencies>  
      <build>  
           <plugins>  
                <plugin>  
                     <groupId>org.apache.maven.plugins</groupId>  
                     <artifactId>maven-compiler-plugin</artifactId>  
                     <version>2.3.2</version>  
                     <configuration>  
                          <source>1.6</source>  
                          <target>1.6</target>  
                          <encoding>UTF-8</encoding>  
                     </configuration>  
                </plugin>  
           </plugins>  
      </build>  
 </project>  

At this point if you did press ctrl+s you will notice that eclipse displays an error.
The reason is that the project does not contain yet all that is mentioned in the pom.xml. To synchronize what you should do is:

right click on project->Maven->Update Project...

The next thing we will do is configure the web.xml file to include the the Faces Servlet and also to make it compatible with Servlet 3.0 The web.xml file can be found under the WEB-INF/ folder


This is how the web.xml should look like:

 <?xml version="1.0" encoding="UTF-8"?>  
 <web-app 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">  
      <display-name>Archetype Created Web Application</display-name>  
      <context-param>  
           <param-name>javax.faces.PROJECT_STAGE</param-name>  
           <param-value>Development</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>*.xhtml</url-pattern>  
      </servlet-mapping>  
      <welcome-file-list>  
           <welcome-file>home.xhtml</welcome-file>  
      </welcome-file-list>  
 </web-app>  

I don't want to explain all the details in this file, the most important thing is that it should be using version 3.0(The maven-compiler-plugin that we are using in our pom.xml is capable of parsing this). Also notice that the faces servlet is included, this is mandatory in order JSF to work,but the load-on-start-up tag is optional.

The next thing I will do is include the file faces-config.xml(optional) This is not mandatory since JSF 2.0 because with the use of annotations our managed beans will be automatically be loaded and there is no need to specify them in the deployment descriptor.
But the reason why I am doing so is: some web containers such as tomcat or jetty depending on the version, might not load our managed beans based on the annotations, so the faces-config.xml it is still required.
I discovered this,once while using an embedded tomcat 6 provided by maven when using mvn tomcat:run So this is how your faces-config.xml should look like if you decide to create it:

 <?xml version="1.0" encoding="UTF-8"?>  
 <!-- This file is not required if you don't need any extra configuration. -->  
 <faces-config version="2.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-facesconfig_2_1.xsd">  
   <!-- Write your navigation rules here. -->  
   <application>  
             <locale-config>  
       <default-locale>en</default-locale>  
       <supported-locale>en</supported-locale>  
     </locale-config>  
   </application>  
 </faces-config>  

Before exiting the WEB-INF folder we will add just one more thing.
A folder called classes, with an empty file called beans.xml.
If we want to use CDI beans in our JSF project, this will be mandatory
At this point this is how the WEB-INF folder should look like:

This is all the configuration we needed to do in order to work with JSF.

NowI will just create a managed beand that returns some value to the page to prove that everything is well configurated.

 package com.yourpackagename;  
 import javax.faces.bean.ManagedBean;  
 @ManagedBean  
 public class Hello {  
      public String getMessage() {  
           return "www.javing.blogspot.com";  
      }  
 }  

Notice that in the web.xml the welcome page is called home.xhtml, so lets create that page in the webapp directory. (You can delete the index.jsp that was there by default)

 <!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:f="http://java.sun.com/jsf/core"  
      xmlns:h="http://java.sun.com/jsf/html"  
      xmlns:p="http://primefaces.org/ui">  
 <h:head>  
      <title>www.javing.blogspot.com</title>  
 </h:head>  
 <h:body>  
                <h:outputText value="#{hello.message}"/>  
 </h:body>  
 </html>  

Installing and deploying in JBoss7 AS
I suppose you know that you can download JBoss 7 AS for free from www.jboss.org, I just forgot the exact link to the download section, but it should not be to complicated to find. The one I am using is the linux distribution of jboss-as-7.1.1.Final.
So once you downloaded it, place the folder wherever you want, and set the environment variables.

This is how I did setup the environment variables for my user in the file ~/.profile (ubuntu 12.10):

 export PATH="/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:$  
 export JAVA_HOME=/usr/lib/jvm/jdk1.6.0_38  
 export M2_HOME=/usr/local/apache-maven-3.0.4  
 export M2=$M2_HOME/bin  
 export JBOSS_HOME=/home/djordje/jboss-as-7.1.1.Final  
 export PATH=$M2:$PATH:$JAVA_HOME/bin:$JBOSS_HOME/bin  
 export UNITY_LOW_GFX_MODE=1  

So now that your JBoss is installed correctly you can deploy the app we created before.
To do so, navigate to the project in the workspace and type the following command:

 /your_project_name$ mvn package  

That will generate a .war file in your target folder:

It is important to rename it correctly before deploying it.
This is how it should look like:


Now that we have the project packaged and ready to deploy, move that file into the deployments folder of the application server:


Now you have to start the application server, to start JBoss 7 in standalone mode.
Navigate to jboss-as-7.1.1.Final/bin/ and execute the script ./standalone.sh
You should see a message in the console that says: Deployed "your_project_name.war"

The last step is to navigate to the application typing this into the browser:

http://localhost:8080/your_project_name/home.xhtml








3 comments:

  1. JBoss 7.1.1. already comes shipped with a jsf implementation (to be found under modules/com/sun/jsf-impl/main), so deploying an application with an included jsf implementation jar confuses the JBoss class loader.

    The solution is simply to omit the jsf implementation dependency in pom.xml

    ReplyDelete
  2. JBoss 7.1.1. already comes shipped with a jsf implementation (to be found under modules/com/sun/jsf-impl/main), so deploying an application with an included jsf implementation jar confuses the JBoss class loader.

    The solution is simply to omit the jsf implementation dependency in pom.xml - See more at: http://javing.blogspot.co.at/2013/01/how-to-create-new-jsf-21-project-and.html?showComment=1454236020518#c23372297271110514


    For details, see

    https://alex4java.wordpress.com/2016/01/31/jsf-2-2-maven-project-in-eclipse-with-prime-faces/

    ReplyDelete

Share with your friends