JSF 2.1 project using Eclipse and Maven 2
I’ve used Maven in my previous job and although it’s not perfect, it can be useful. So, I was reading around on Experts Exchange the other day for un-answered RichFaces questions to refresh my knowledge after not having done any work for 2 months now (not sure whether that’s good or bad ;-)) and saw one question that I thought I’d answer. I created a basic Maven project in Eclipse and added the necessary gubbins for RichFaces, but the thing refused to deploy to Tomcat… I then decided to scrap that project and go for the latest stuff, which was a lot further on than what I’ve used before. It turns out that JSF has moved on from 1.2 to 2.1!
So here is my guide to getting a JSF 2.1 project with Maven running in Eclipse. As I add more things to my project like Spring, Hibernate and perhaps RichFaces I shall edit this post and add link(s) to the new posts at the end.
If you haven’t already got Eclipse and the Maven plugin that goes in Eclipse, now would be a good time to get and install them. Also install Tomcat and add a tomcat server in Eclipse.
Ok, start by creating a new Maven project.
Select “Create a simple project (skip archetype selection)” as we don’t want all the extra stuff that an archetype would add.
Choose the location of the project. I’ve chosen to put the project in my default workspace.
Set the Group Id, Artifact Id, Name and change the Packaging type to war.
What you should now have is the following project structure:
This project that we’ve just created will not deploy to tomcat though as it’s not set as a “Dynamic Web Module” facet… And to top it off, Eclipse doesn’t show the project facets until we make a change to the .project file…
So, open the .project file. There should be two build commands and two natures: org.eclipse.jdt.core.javabuilder, org.maven.ide.eclipse.maven2Builder and org.eclipse.jdt.core.javanature, org.maven.ide.eclipse.maven2Nature. Replace the following lines of code shown in the following image with:
<buildSpec> <buildCommand> <name>org.eclipse.wst.jsdt.core.javascriptValidator</name> <arguments> </arguments> </buildCommand> <buildCommand> <name>org.eclipse.wst.common.project.facet.core.builder</name> <arguments> </arguments> </buildCommand> <buildCommand> <name>org.eclipse.jdt.core.javabuilder</name> <arguments> </arguments> </buildCommand> <buildCommand> <name>org.eclipse.wst.validation.validationbuilder</name> <arguments> </arguments> </buildCommand> <buildCommand> <name>org.maven.ide.eclipse.maven2Builder</name> <arguments> </arguments> </buildCommand> </buildSpec> <natures> <nature>org.eclipse.jem.workbench.JavaEMFNature</nature> <nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature> <nature>org.eclipse.jdt.core.javanature</nature> <nature>org.maven.ide.eclipse.maven2Nature</nature> <nature>org.eclipse.wst.common.project.facet.core.nature</nature> <nature>org.eclipse.wst.jsdt.core.jsNature</nature> </natures>
Save the file and now when you right click on the project and select properties you should have a Project Facets option.
First of all though go to the Java Compiler option, tick “Use default compliance settings” and change “Compiler compliance level” to 1.6 (unless you specifically need a lower Java level?!)
Click apply. It will pop up a dialog box asking to build using the new level straight away. Click yes.
Go to the Java Build Path option and select the “Order and Export” tab. Tick the “Maven Dependencies” box.
Go to the Project Facets option. Tick Dynamic Web Module and make sure the version is 2.4+. Tick Java and make sure the version is 6.0+.
Click ok and it will add those requirements to the project. The project structure will now look like the following:
Delete the folder webapp which is under src/main. All web content needs to go in the WebContent folder instead.
Open file web.xml and select everything. Paste the following code over the top.
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>jsf2testproject</display-name> <welcome-file-list> <welcome-file>index.xhtml</welcome-file> </welcome-file-list> <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> <context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Development</param-value> </context-param> </web-app>
Open the file pom.xml and select the pom.xml tab. Below the name insert the following:
<repositories> <repository> <id>maven2-repository.dev.java.net</id> <name>Java.net Repository for Maven</name> <url>http://download.java.net/maven/2</url> <snapshots> <enabled>false</enabled> </snapshots> </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>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> </dependencies>
Create a folder structure in src/main/java that matches the Group Id that was entered when creating the project. E.g. in this example the folder structure will be src/main/java/uk/co/vsf. I’ve created an additional folder called presentation that I’ve placed a file in called HelloPB.java. In that file is the following:
package uk.co.vsf.presentation; import javax.faces.bean.ManagedBean; import javax.faces.bean.RequestScoped; @ManagedBean @RequestScoped public class HelloPB { private String name = ""; public String getName() { return name; } public void setName(final String name) { this.name = name; } /** * Say hello + name that was entered. * * @return */ public String getHello() { if ( name == null || name.length() < 1 ) { return null; } return "Hello " + name; } }
In the folder WebContent, create a new file index.xhtml. Put the following in to that file:
<!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"> <h:head> <title>JSF Demo</title> </h:head> <h:body> <h:outputScript name="jsf.js" library="javax.faces" target="body"> </h:outputScript> <h1>JSF 2 Demo</h1> <h:form> <h:inputText id="name" value="#{helloPB.name}"> <f:ajax render="helloTextOutput" /> </h:inputText> <h:commandButton value="Say Hi via Ajax"> <f:ajax execute="name" render="helloTextOutput" /> </h:commandButton> <h:outputText id="helloTextOutput" value="#{helloPB.hello}" /> </h:form> </h:body> </html>
That was the last new file we need, but the project will still not work correctly as when deployed it will not contain the jars that we added in the pom.xml file. If you navigate to where the jar files should be in the deployed app, as seen in the image, you’ll notice they haven’t been included. If we deploy it right now, this is the error message that will appear in the log:
SEVERE: Error loading WebappClassLoader context: /jsf2testproject delegate: false repositories: /WEB-INF/classes/ ----------> Parent Classloader: org.apache.catalina.loader.StandardClassLoader@1b90b39 javax.faces.webapp.FacesServlet java.lang.ClassNotFoundException: javax.faces.webapp.FacesServlet
We will now need to alter a few files so that the jar files are deployed with the application.
So now open the file org.eclipse.wst.common.component which is in the .settings folder. Delete the lines:
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/java" /> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/resources" />
Replace them with:
<dependent-module deploy-path="/WEB-INF/lib"> <dependency-type>uses</dependency-type> </dependent-module>
Open .classpath and replace the line:
<classpathentry exported="true" kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"> <attributes> <attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/> </attributes> </classpathentry>
Now when you deploy the application and navigate to the webpage which in my case is http://localhost:8080/jsf2testproject you should see the following:
So there we have it; a project that is setup ready for use. There may well be an easier way to configure the project, but this is the way that’s worked for me and there are no extra files that I don’t need.
Related Posts
None yet
Please enable the Disqus feature in order to add comments