which init-param to use: jersey.config.server.provider.packages or javax.ws.rs.Application?

Marcus Junius Brutus picture Marcus Junius Brutus · Apr 10, 2014 · Viewed 35.2k times · Source

I am deploying JAX-RS web services to a Tomcat servlet container.

I have seen code examples that use either of the following two methods of indicating the resources in the web.xml file:

method 1 - using the `jersey.config.server.provider.packages` init-param

  <servlet>
      <servlet-name>Jersey Web Application</servlet-name>
      <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
      <init-param>
          <param-name>jersey.config.server.provider.packages</param-name>
          <param-value>com.example</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
  </servlet>

...where the resources are expected to reside in the com.example package and I suppose are discovered by means of Java RTTI.

method 2 - using the `javax.ws.rs.Application` init-param

<servlet>
 <servlet-name>jersey-serlvet</servlet-name>
 <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
   <init-param>
           <param-name>javax.ws.rs.Application</param-name>
           <param-value>full.qualified.name.to.MyApplication</param-value>
   </init-param>
 <load-on-startup>1</load-on-startup>
</servlet> 

... where the MyApplication class identifies explicitly the resource classes:

public class MyApplication extends javax.ws.rs.core.Application {
   public Set<Class<?>> getClasses() {
      Set<Class<?>> s = new HashSet<Class<?>>();
      s.add(ResourceA.class);
      return s;
}

Is using the one versus the other method purely a matter of taste and configuration effort and what are some trade-offs to consider? Personally, I prefer the more fine-grained control offered by method 2, however the maven Jersey 2.7 archetype:

mvn archetype:generate -DarchetypeArtifactId=jersey-quickstart-webapp \
            -DarchetypeGroupId=org.glassfish.jersey.archetypes -DinteractiveMode=false \
            -DgroupId=com.example -DartifactId=simple-service-webapp -Dpackage=com.example \
            -DarchetypeVersion=2.7

... is using method 1 and that got me thinking.

Answer

Andrei I picture Andrei I · Apr 13, 2014

Method 1 (using servlet's init param jersey.config.server.provider.packages): is Jersey specific and looks only in packages. It is not portable between different JAX-RS implementations. You can use it in scenarios when you want to restrict the considered JAX-RS Resource classes/applications.

Method 2 (using servlet's init param javax.ws.rs.Application): any JAX-RS implementation MUST support this deployment option, thus portable (although if you switch to another JAX-RS implementation like RestEasy, you will have to change the servlet's class). This option offers more granularity (you can select exactly the classes to be considered, not only entire packages). The disadvantage: you have to write more code.

Method 3 (in a Servlet ver. 3 Container, where you probably already deploy): defining only your JAX-RS applications without any servlets (check Deployment using web.xml descriptor) is probably the best way (it is also portable between JAX-RS implementations and you can change the JAX-RS implementation without a change in web.xml), if you have an explicitly declared JAX-RS Application (which you have).

Method 4 If you want to deploy all classes from your war archive in a servlet container 3 (without an explicitly-defined JAX-RS application), you can do that also in a portable way. Check it here: JAX-RS application without an Application subclass