Multiple JAX-RS applications in the same WAR

2019-03-20 23:02发布

问题:

I have

@ApplicationPath("/resourcesP")
public class RestfulPrediction extends Application {
    @Override
    public Set<Class<?>> getClasses() {
    Set<Class<?>> set = new HashSet<Class<?>>();
        set.add(PredictionsRS.class);
        return set;
    }
}

And

@ApplicationPath("/resourcesA")
public class RestfulAdage extends Application {
    @Override
    public Set<Class<?>> getClasses() {
    Set<Class<?>> set = new HashSet<Class<?>>();
        set.add(Adages.class);
        return set;
    }
}

Two different ApplicationPath and the class are as follows.

@Path("/")
public class service.Adages {}

@Path("/")
public class webservices.PredictionsRS {}

Both of them are declared in different ApplicationPath. I'm using Jersey and the config in web.xml looks like

  <servlet>  
    <servlet-name>jersey</servlet-name>  
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>  
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>
            service
            webservices
        </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>  

And I'm getting

SEVERE: Conflicting URI templates. The URI template / for root resource class service.Adages and the URI template / transform to the same regular expression (/.*)?

Why if I have two different ApplicationPath this exception comes at startup ?

If I take out a package in param-value this works, also if I change one of the @Path annotations this works, so it is a problem with my configuration ?

I'm using Jersey 1.10. Thanks all.

回答1:

You did not define your JAX-RS applications in your web.xml. Try the following:

<servlet>
    <servlet-name>full.name.RestfulAdage</servlet-name>
</servlet>

<servlet>
    <servlet-name>full.name.RestfulPrediction</servlet-name>
</servlet>

<servlet-mapping>
    <servlet-name>full.name.RestfulPrediction</servlet-name>
    <url-pattern>/resourcesP/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>full.name.RestfulPrediction</servlet-name>
    <url-pattern>/resourcesA/*</url-pattern>
</servlet-mapping>

and remove the @ApplicationPAth annotations from code.

I checked the above code with Jersey 2.7, servlet container 3.0 and it works. If still having that bug, try upgrading to Jersey 1.17 (which should not change any behavior from Jersey 1.10, and fix bugs instead) and eventually using also a servlet container 3.0.

UPDATE

After checking the possibilities the configuration below work with Jersey 1.17

   <servlet>  
    <servlet-name>jersey</servlet-name>  
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>  
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>
            com.koitoer.webservices
        </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

It seems there is bug in the spec in older version of Jersey that kind of circle back the references and mark as duplicate endpoints. Using the configuration above both endpoints load without any problem.

8/04/2014 09:13:40 PM com.sun.jersey.server.impl.container.servlet.JerseyServletContainerInitializer addServletWithApplication INFO: Registering the Jersey servlet application, named com.koitoer.webservices.chapter2.service2.RestfulPrediction, at the servlet mapping, /resourcesP/*, with the Application class of the same name

8/04/2014 09:13:40 PM com.sun.jersey.server.impl.container.servlet.JerseyServletContainerInitializer addServletWithApplication INFO: Registering the Jersey servlet application, named com.koitoer.webservices.chapter2.RestfulAdage, at the servlet mapping, /resourcesA/*, with the Application class of the same name



回答2:

You should have a single subclass of javax.ws.rs.core.Application in your webapp, and then use different @Path annotation values on your service.Adages and webservices.PredictionsRS resource types. AFAIK, in JEE6 containers, you are not allowed to have 2 such subclasses...