Setting up a JSF Maven project in NetBeans (including working autocompletion for JSP/JSF)

Posted on April 6, 2009

0


Today’s rich IDEs make a lot of tasks easier…usually. With Java and its IDEs you often end up spending more time than you anticipated to just set up a project, especially when dealing with the complexities of J2EE: there are multiple versions of the specifications 1.3,1.4,5.0), each one with multiple implementations by different vendors plus extensions (richfaces, struts, seam, spring..). You have also to choose the container (tomcat, glassfish, jboss…). Last but not least, you can also pick different building tools (abt, maven…). And of course, we expect IDEs to happily support any combination of the above choices.
One combination that was not working for me was the following:

  • NetBeans 6.5 IDE
  • Glassfish or JBoss
  • Maven
  • WebApp Archetype for Maven

First of all, you need the Maven support plugin installed in NetBeans. If you don’t know how to do that, be sure to check the NetBeans Maven Best Practices Installing section.

I created a new project using the Maven WebApp archetype.
The first Problem I encountered was that in JSP pages autocompletion was not being recognized.

A simple page like this (index.jsp)

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>

<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>

would get an error:

Servlet API classes are not in the classpath, some scriplets editing features are disabled.

This happens because the NetBeans maven template doesn’t automatically add the J2EE libraries to your classpath. You have to add those manually.
Use the Maven Repository Browser (Window|Other|Maven Repository Browser), click on the ‘search’ icon and search for javax.servet. Add as dependency ‘servlet-api’ (right click on the version of your choice and choose “add as dependency to”, then pick your project from the list). Also add ‘jsp-api’.

Now the IDE complains about the taglibs.

<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>

Now, here there are 2 issues at work. First one should be obvious given the previous one: we didn’t add the j2EE libraries to the maven project. The second is a little more subtle: we want to use JSF but if you go to the project properties, under “Run”, no matter what’s your application server, NetBeans won’t let you change the J2EE version.
To change it, you have to edit web.xml.
Change the webapp tag in this way. The default one from the maven template looks like this:

<web-app>
  <display-name>Archetype Created Web Application</display-name>
</web-app>

Change it to the following. It sets the right webapp version (2.5) and configures JSF.

<?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>com.sun.faces.verifyObjects</param-name>
        <param-value>false</param-value>
    </context-param>
    <context-param>
        <param-name>com.sun.faces.validateXml</param-name>
        <param-value>true</param-value>
    </context-param>
    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>client</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>

Also don’t forget to add the necessary libraries in maven. Look for ‘javax.faces’ in the maven repository browser and add ‘faces-api’ and ‘faces-impl’. The taglib is actually in faces-impl but faces-api is also needed. Now going back to your index.jsp, all the errors should be gone (it sometimes takes a few seconds to disappear – I usually add and remove a space to force recompilation of the page).

Now your pom.xml should look something like this:

<?xml version="1.0" encoding="UTF-8"?>
<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.my.test</groupId>
    <artifactId>testmavenjsf</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>testmavenjsf Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.faces</groupId>
            <artifactId>jsf-api</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.faces</groupId>
            <artifactId>jsf-impl</artifactId>
            <version>1.2-b19</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>testmavenjsf</finalName>
    </build>
    <properties>
        <netbeans.hint.deploy.server>gfv3</netbeans.hint.deploy.server>
    </properties>
</project>

Now, there’s one more thing we need to do. We don’t actually need the libraries to be bundled in the war since the container is going to provide them.

To do this, we have to change the scope of the libraries. Add

            <scope>provided</scope>

To all the libraries you just added manually to Maven.

        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>     
         </dependency>

This tells Maven that the libraries are needed to compile, but neither them nor their dependencies should not be added to the war.

Now you can start writing your actual code. The JSP editor will work fine, including autocompletion.

Comments

comments

Tagged:
Posted in: programming