I'm trying to setup a small example application FooTest
that uses CXF JAX-RS and JSF. I started with the CXF part, implemented a simple service (works) and a small html page called home.html (I can access it in my browser). The relevant code is as follows:
web.xml
<servlet>
<servlet-name>RestServlet</servlet-name>
<servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class>
<init-param>
<param-name>jaxrs.serviceClasses</param-name>
<param-value>com.test.FooService</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>RestServlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
FooService.java
@Path("/rest")
public class FooService {
@Path("/foo")
@GET
@Produces("application/json; charset=UTF-8")
public String getFoo() {
// returns json
}
}
Now I can call http://localhost:8080/FooTest/rest/foo
and http://localhost:8080/FooTest/home.html
. However when I start defining and mapping the FacesServlet
to *.html
and try to access home.html
I get a NullPointerException
.
New web.xml
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
... CXF stuff ...
Leads to
Apr 25, 2013 6:08:17 AM org.apache.catalina.core.ApplicationDispatcher invoke
SEVERE: Servlet.service() for servlet Faces Servlet threw exception
java.lang.NullPointerException
at org.apache.myfaces.shared.context.flash.FlashImpl.isKeepMessages(FlashImpl.java:388)
at org.apache.myfaces.shared.context.flash.FlashImpl._saveMessages(FlashImpl.java:665)
at org.apache.myfaces.shared.context.flash.FlashImpl.doPostPhaseActions(FlashImpl.java:269)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:254)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:749)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:487)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:412)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:339)
at org.apache.myfaces.context.servlet.ServletExternalContextImpl.dispatch(ServletExternalContextImpl.java:369)
at org.apache.myfaces.view.jsp.JspViewDeclarationLanguage.buildView(JspViewDeclarationLanguage.java:99)
at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:78)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:241)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
... infinite loop from FacesServlet:199 on ...
How can I fix this?
The application runs on the JAX-RS version of TomEE 1.5.2.
src/main/webapp/WEB-INF/faces-config.xml
<?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_2_1.xsd"
version="2.1">
</faces-config>
(Thanks to David Blevins for clarification and pointing me to a useful example)
Remove the CXF configuration part, it is not required. Rename home.html
to home.xhtml
, since .xhtml
is the javax.faces.DEFAULT_SUFFIX
for JSF pages. Keep the FacesServlet
mapping if you want to access your JSF pages using the .html
extension. This is sufficient:
<?xml version="1.0" encoding="UTF-8"?>
<web-app ... >
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
</web-app>
Not sure whether this should be a comment or an answer, but you shouldn't setup CXFNonSpringJaxrsServlet
and FacesServlet
in your web.xml, all that stuff is there and ready to go. The goal with TomEE is you can skip the server-building and proceed directly to app-building.
CXF is fully integrated into Tomcat in TomEE to the point where even WS-Security works on Tomcat Realms. You just start using it by adding @ApplicationPath
annotated components or EJBs annotated with @Path
and they will be picked up and deployed automatically.
MyFaces is good to go and fully integrated with CDI so even things like @ConversationScoped
work out of the box. You just need your faces-config.xml
or some @ManagedBean
classes.