How to use Jersey as JAX-RS implementation without web.xml?

I have read that from JavaEE 6 web.xml is optional.

So without web.xml, how can I tell the application server to use Jersey as the implementation for JAX-RS specification?


Solution 1:

What @AlexNevidomsky wrote in his answer is correct, as far as how to implement the app configuration with no web.xml; you use an @ApplicationPath annotation on an Application subclass.

@ApplicationPath("/api")
public class AppConfig extends Application {}

For more information on deployment options, see the Jersey Docs: Chapter 4. Application Deployment and Runtime Environments

Or more commonly, with Jersey as implementation, we would extend ResourceConfig (which extends Application).

@ApplicationPath("api")
public class AppConfig extends ResourceConfig {
    public AppConfig() {
        packages("package.to.scan");
    }
}

So how is this implemented...

First things first, not all Java EE servers use Jersey. Actually the only ones I know that use Jersey are Glassfish and WebLogic. JBoss uses Resteasy. Tom EE uses CXF. WebSphere uses Apache Wink. Those are the only ones I can think of.

So I guess the question is "How does the Server know how to load the JAX-RS application?"

Servlet 3.0 introduced the pluggability mechanism, which makes use of a ServletContainerInitializer. How it works is that when the Server/Servlet container is started, it scans jars for a META-INF/services folder with a file named javax.servlet.ServletContainerInitializer. This file should include one or more fully qualified names of implementations of the ServletContainerInitializer.

This interface has only one method

void onStartup(java.util.Set<java.lang.Class<?>> c, ServletContext ctx)

The Set<Class<?> will be a list of classes, fitting the criteria in the @HandlesTypes annotation on the ServletContainerInitializer implementation. If you look at Jersey's implementation

@HandlesTypes({ Path.class, Provider.class, Application.class, ApplicationPath.class })
public final class JerseyServletContainerInitializer 
                   implements ServletContainerInitializer {

You should notice some familiar annotation classes, as well as the Application.class. All these classes matching the criteria, while scanning, are added to the Set passed to the onStartup method.

If you scan the rest of the source code, you will see all the registration being done with all of those classes.

Resteasy uses

@HandlesTypes({Application.class, Path.class, Provider.class})
public class ResteasyServletInitializer implements ServletContainerInitializer

I won't get into to others.

Some source you can look at...

  • JerseyServletContainerInitializer source code
  • ResteasyServletInitializer source code
  • JAX-RS specs

Solution 2:

You don't have to specify anything in web.xml. Define an activator class:

@ApplicationPath("/rest")
public class _JaxRsActivator extends javax.ws.rs.core.Application {

  static {
      //Check some system init on REST init.
      Config.initCheck();
  }
}