Hello, it seems that it is not possible to have multiple JAX-RS servlets in one web.xml. Only the first one accessed becomes available, the others throw an exception and no jaxrs.* init parameters have any influence. I'm using CFX 3.0.0.milestone2.
The situation: I'm trying to deploy a RESTful service that consists of several quite independent parts. The parts are implemented using Apache Olingo (a library implementing the OData protocol), each part is actually a JAX-RS application, i.e. a separate servlet. My deployment provides all the parts in a single web application, i.e. all the parts are declared in the same web.xml. Here is the web.xml with the parts making troubles being commented out: <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 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" id="WebApp_ID" version="2.5"> <servlet> <servlet-name>SessionServiceServlet</servlet-name> <servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>net.atos.dirx.access.net.rest.services.session.SessionODataApplication</param-value> </init-param> </servlet> <!-- TODO: enable when working <servlet> <servlet-name>RequestServiceServlet</servlet-name> <servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>net.atos.dirx.access.net.rest.services.authz.RequestODataApplication</param-value> </init-param> </servlet> --> <servlet-mapping> <servlet-name>SessionServiceServlet</servlet-name> <url-pattern>/sessioning/*</url-pattern> </servlet-mapping> <!-- TODO: enable when working <servlet-mapping> <servlet-name>RequestServiceServlet</servlet-name> <url-pattern>/authz/*</url-pattern> </servlet-mapping> --> </web-app> When the second servlet is uncommented, following exception can be observed: org.apache.cxf.service.factory.ServiceConstructionException at org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:210) at org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet.createServerFromApplication(CXFNonSpringJaxrsServlet.java:446) at org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet.init(CXFNonSpringJaxrsServlet.java:93) at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:512) ... Caused by: org.apache.cxf.service.factory.ServiceConstructionException: There is an endpoint already running on /. at org.apache.cxf.jaxrs.JAXRSBindingFactory.addListener(JAXRSBindingFactory.java:85) at org.apache.cxf.endpoint.ServerImpl.start(ServerImpl.java:131) at org.apache.cxf.jaxrs.JAXRSServerFactoryBean.create(JAXRSServerFactoryBean.java:197) at org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet.createServerFromApplication(CXFNonSpringJaxrsServlet.java:446) at org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet.init(CXFNonSpringJaxrsServlet.java:93) at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:512) ... Behaviour from the user's point of view: I wonder firstly why the servlet mapping is not respected and why there is any path conflict when the paths to the servlets neither overlap nor are ambiguous. But I can admit that it is necessary from technical reasons to provide an additional resolution parameter - like "jaxrs.address" seemed to be. Unfortunately, using it didn't change anything. Well, it's a pity - I tried then "jaxrs.application.address.ignore" set to true or false and annotating the JAX-RS application classes with @Path (otherwise I didn't use them, since I'm afraid of a conflict with Olingo's resource path management and the endpoint paths should be managed by the deployment descriptor in our case, if possible). Stepping through the code: The "jaxrs.address" parameter, which I think should be the proper way to resolve the path conflict, if the servlet mapping is not sufficient, unfortunately is completely ignored: - CXFNonSpringJaxrsServlet.init() sets "address" field with the parameter value, but it is in the code branch that is not executed. - Instead, createServerFromApplication() and subsequently createApplication() are called. - Then createApplication() does set the "address" field, but only either to the path given by the application's annotation, or to "/". Hey, we've got here a fixed "/" string that is then complained about! Well, being curious, I tried to employ annotations to see what happens then. I set the values to "sessioning" and "authz" that are used in the servlet mapping. This somewhat helped: both parts can be then accessed without errors. The values were concatenated with the mapping path - not nice (and I don't know how to avoid that), but I can understand that. What I don't understand well is that now four endpoints can be accessed: /sessioning/sessioning/ /sessioning/authz/ /authz/sessioning/ /authz/authz/ It looks like all the JAX-RS servlets share something more than one would expect. I must say that it is pretty inconvenient, at least in this scenario when the servlets are supposed to be rather independent, just deployed via the same web.xml. Ideally, I would like to have only: /sessioning/ /authz/ Exactly as specified by the servlet mapping. Is there any way to achieve this? And is the described behaviour a bug, or a feature? Thanks for any comments! Petr
