Last week I tried to upgrade my JSF 2 examples for JSF@Work to run with Jetty 8 for the full Java EE 6 experience. My first naive approach was to simply change the version of the Jetty Maven Plugin from 7.x to 8.x. Unfortunately, that did not work out so well and resulted in a nasty exception during JSF startup (MyFaces and Mojarra). So, in this post I will show you how to run JSF 2.x web apps with the Jetty Maven Plugin 8.
Starting a JSF 2 application with the Jetty Maven Plugin 8 does not work out of the box. With MyFaces you get the following exception (with Mojarra only the error message differs):
java.lang.IllegalStateException: No Factories configured for this Application
What happens here? MyFaces and Mojarra register a servlet context listener for the startup configuration via the TLD file of the JSF core taglib. So far this has worked without problems on most containers but it does no longer work on Jetty 8. The reason for this is, that Jetty 8 uses the Glassfish JSP implementation which requires the TLD files to be on the classpath of the container (see  for details). This is not the case if the application is started via the Jetty Maven Plugin and the above exception is thrown.
The easiest solution is to simply add the config listener to the
web.xml. This is the startup servlet context listener for MyFaces:
<listener> <listener-class> org.apache.myfaces.webapp.StartupServletContextListener </listener-class> </listener>
This is the startup servlet context listener for Mojarra:
<listener> <listener-class> com.sun.faces.config.ConfigureListener </listener-class> </listener>
As soon as the listener is configured in the
web.xml the application will start again. But having a closer look on this approach reveals some drawbacks:
web.xmlis changed for one specific application server.
- Listener class in the
web.xmlmust be changed if you switch between MyFaces and Mojarra.
A more sophisticated approach solving the above mentioned problems is to use additional override
web.xml files for Jetty. The only content of such a
web.xml is the listener for MyFaces or Mojarra as you can see in the following example (with the MyFaces listener):
<web-app ...> <listener> <listener-class> org.apache.myfaces.webapp.StartupServletContextListener </listener-class> </listener> </web-app>
Those override files can be placed in
src/main/jetty for instance. Then we only have to tell Jetty to use one of those files additionally to the application’s
web.xml. This is done with the config property
overrideDescriptor as you can see in the following snippet taken from the
<plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>8.1.5.v20120716</version> <configuration> <webAppConfig> <overrideDescriptor> src/main/jetty/override-myfaces-web.xml </overrideDescriptor> </webAppConfig> </configuration> </plugin>
The source code for the presented example can be found in the Github repository jsf-jetty-8.