Setting up a Facelets project in IDEA

From Shrubbery

Jump to: navigation, search


How to set up a Facelets web application in IDEA.

Contents

[edit] Download an implementations

In this example we'll use the MyFaces JSF implementation and the Sun Facelets implementation.

[edit] Set up JSF

First, you need to set up a web application with JSF support. This can be done in two ways:

  1. Using the module creation wizard and selecting JSF support.
    1. Open up Project Structure (<ctrl-alt-S> then '1'). Click add module.
    2. Select 'Web Module' in the Add Module screen and click next.
    3. In the last panel, check JavaServer Faces support.
    4. Select the JSF version and implementation on the next screen.
    5. Copy the JSF libraries into your project and then select them from the library screen.
    6. Select the location of your faces-config.xml file in the next screen.
  2. Do it yourself. This is my preferred method. The wizard is fine but one usually ends up playing around with what it does anyway.
    1. Create a web module using the wizard. Don't select JSF support.
    2. Create a project library for JSF support, for example myfaces. This library should contain all the jars in your JSF implementation.
    3. Add the faces configuration elements to WEB-INF/web.xml. Declare the Faces Servlet and the mappings for it. These will be modified later when adding Facelets support.
    4. Add an initial JSF configuration file in WEB-INF/faces-config.xml

Make sure the module dependencies for any web module that uses faces has the faces implementation project library as a dependency.

[edit] MyFaces libraries

Here is an example of the JAR files required for MyFaces 1.1.5:

  • commons-beanutils.1.7.0.jar
  • commons-codec-1.3.jar
  • commons-collections-3.1.jar
  • commons-digester-1.6.jar
  • commons-el-1.0.jar
  • commons-lang-2.1.jar
  • commons-logging-1.0.4.jar
  • jstl-1.1.0.jar
  • myfaces-api-1.1.5.jar
  • myfaces-impl-1.1.5.jar

It's also a good idea to get the myfaces-core sources, zip them up and add them to the project library.

[edit] MyFaces Face Servlet Mapping

Here is an example WEB-INF/web.xml snippet that declares the Faces Servlet and maps it to some URLS:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

    <!-- MyFaces -->
    <listener>
        <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
    </listener>

    <!-- Faces config -->
    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>client</param-value>
    </context-param>

    <context-param>
        <param-name>facelets.DEVELOPMENT</param-name>
        <param-value>true</param-value>
    </context-param>

    <!-- We're using facelets, so the suffix of the views is xhtml -->
    <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.xhtml</param-value>
    </context-param>

    <!-- Faces -->

    <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>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.faces</url-pattern>
    </servlet-mapping>
</web-app>

If you are using Seam then this might look slightly different:


    <!-- Seam -->
    <listener>
        <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
    </listener>

    <!-- MyFaces -->
    <listener>
        <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
    </listener>

    <!-- Faces config -->
    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>client</param-value>
    </context-param>

    <context-param>
        <param-name>facelets.DEVELOPMENT</param-name>
        <param-value>true</param-value>
    </context-param>

    <!-- We're using facelets, so the suffix of the views is xhtml -->
    <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.xhtml</param-value>
    </context-param>

    <!-- Faces -->
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- Faces Servlet Mapping -->
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.seam</url-pattern>
    </servlet-mapping>

The IDEA module wizard will set this up for you if you took that approach.

[edit] The initial faces-config.xml

To start out with, there's nothing defined in WEB-INF/faces-config.xml, but the file needs to be there.

<?xml version='1.0' encoding='UTF-8'?>
<faces-config 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_1_2.xsd"
              version="1.2">
  
</faces-config>

[edit] Add Facelets

  1. Create a project library called 'el' which includes:
    • el-api.jar
    • el-ri.jar
    These jars are in the 'lib' directory in the facelets distribution.
  2. Create a project library called 'facelets' which includes:
    • jsf-facelets.jar
    This jar is in the root directory of the facelets distribution. It's also a good idea to zip up the 'src/java' directory in the facelets distribution and add it to the project library. I usually copy the jars into a 'lib' directory under the main project directory so that I can use relative paths, making the project relatively self contained (except for the reference to Tomcat so I can run it from inside IDEA).
  3. Add the 'el' and 'facelets' project libraries as dependencies in the web module or modules. The Packaging method should be set to 'Copy files to' and the Path Relative to Deployment Root should be /WEB-INF/lib.
  4. Set the context parameters up in WEB-INF/web.xml:
        <context-param>
            <param-name>facelets.REFRESH_PERIOD</param-name>
            <param-value>2</param-value>
        </context-param>
    
        <context-param>
            <param-name>facelets.DEVELOPMENT</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>
    	
        <context-param>
    	<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
    	<param-value>.xhtml</param-value>
        </context-param>
    
  5. Add the facelets view handler to WEB-INF/faces-config.xml. A very simple WEB-INF/faces-config.xml might look like this:
    <?xml version="1.0" encoding="ISO-8859-1" ?>
    <!DOCTYPE faces-config PUBLIC
     "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
     "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
    <faces-config>
        <application>
          <view-handler>
            com.sun.facelets.FaceletViewHandler
          </view-handler>
        </application>
    </faces-config>
    

[edit] Add Jakarta Standard Taglibs to make IDEA happy

IDEA doesn't like having no taglib definition for the JSTL tags, but you can easily fix this by creating a project level library called 'standard' and adding standard.jar to it.

[edit] Try it out

Make an XHTML file called hello.xhtml in the web resource directory, start Tomcat and then go to http://localhost:8080/hello.faces. Notice that the url ends with .faces. This is because we configured the faces servlet to respond to this suffix.

[edit] Packaging

The resulting WAR package should look something like this:

 \-myapp.war
    +-META-INF
    |  \-context.xml
    +-WEB-INF
    |  +-lib
    |  |  +-commons-beanutils-1.7.0.jar
    |  |  +-commons-codec-1.3.jar
    |  |  +-commons-collections-3.1.jar
    |  |  +-commons-digester-1.6.jar
    |  |  +-commons-el-1.0.jar
    |  |  +-commons-lang-2.1.jar
    |  |  +-commons-logging-1.0.4.jar
    |  |  +-el-api.jar
    |  |  +-el-ri.jar
    |  |  +-jsf-facelets.jar
    |  |  +-jstl-1.1.0.jar
    |  |  +-myfaces-api-1.1.5.jar
    |  |  +-myfaces-core-1.1.5-src.zip
    |  |  +-myfaces-impl-1.1.5.jar
    |  |  \-standard.jar
    |  +-faces-config.xml
    |  \-web.xml
    \-hello.xhtml

NOTE: This won't work well inside JBoss AS because it already has MyFaces deployed (in the "default" config anyway). In JBoss you need a slightly different packaging.

TODO: List the JBoss AS packaging here.

[edit] Facelets File Template

IDEA's file templates can make it easier to create Facelets pages. For example, you can create a File Template by copying the built in XHTML template and modifying it to have all the typical taglibs already declared:

<?xml version="1.0" encoding="UTF-8"?>
<!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" xml:lang="en" lang="en"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:c="http://java.sun.com/jstl/core">
  <head>
    <title></title>
  </head>
  <body>

  </body>
</html>

[edit] Troubleshooting

[edit] xmlns:c="http://java.sun.com/jstl/core" shows up in red

This means that IDEA couldn't find the old-style .tld descriptor for the JSTL core library. Make sure that you have standard.jar (the jakarta-taglibs-standard library) in your project. If you take a look at standard.jar, you'll see that it contains META-INF/c-1_0.tld which is what IDEA is looking for.

[edit] See Also

Personal tools