1

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?

Update - More config info

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>

Update - Solution

(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>
Jack
  • 1,881
  • 24
  • 29

1 Answers1

1

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.

David Blevins
  • 19,178
  • 3
  • 53
  • 68
  • Oh. I was just starting to hate CXF for its messy documentation and the configuration overhead inherited from its Spring nature. It took me some time to figure out what parts I actually need to make it work in the first place. But this is good news! Just tried using an empty `web.xml` and now it works. I guess I have to rename my `.xhtml` files to `.html` (`.xhtml` doesn't work), but that's fine. Maybe you can explicitly mention this no-configuration-required-thing in the examples and documentation? Anyway, thanks a lot. – Jack Apr 26 '13 at 02:14
  • I might be wrong on the JSF part, the FacesServet might be needed only for the purposes of getting xhtml enabled. You can definitely do it, we just added an example today that does it, but shouldn't be needed for JSF in general. Help on the docs is always welcome! All the pages have a little blue pencil icon in the upper right. Click that and you can edit the page and submit a kind of "pull request" – David Blevins Apr 26 '13 at 02:22
  • Okay, I was a little too quick. My example page showed up, but didn't render JSF tags. Actual solution: The CXF configuration is not required and had nothing to do with the problem (which is good). The FacesServlet mapping is required when you want to acess `.xhtml` JSF-pages via `.html`. The problem with my example is, that I named my page `home.html` but the `javax.faces.DEFAULT_SUFFIX` is `.xhtml`. Unless you change the suffix, you can't use `.html`. – Jack Apr 26 '13 at 02:55