Lee Duckworth
Lee Duckworth

Reputation: 340

Servlet 3.0 and JAX-RS

I've found conflicting answers to this question and I've failed to successfully run an example.

Can JAX-RS be implemented using Servlet 3.0 (in particular, Tomcat 7) with annotations, only, without having to implement another Servlet Container?

If no, please explain why the following quote from this book is either, incorrect or I'm interpreting it, wrong.

Because this example deploys within a Java EE application server or standalone Servlet 3.x container, all we need is an empty web.xml file. The server will detect that an Application class is within your WAR and automatically deploy it. (RESTful Java with JAX-RS 2.0, Bill Burke)

To clarify what I don't need help with... I've, successfully, implemented JAX-RS in Tomcat 7 with Jersey using a web.xml, so, I don't need any explanation of how to do so. Also, I'm fully aware that other Java EE/Servlet Containers (TomEE, Glassfish, Jersey, Websphere, etc...) are all JAX-RS aware out of the box. I just need to know if I'm chasing my tail trying to get Tomcat 7 (Servlet 3.0) to work with JAX-RS without adding a Servlet Container and without web.xml entries.

Upvotes: 3

Views: 4435

Answers (1)

Paul Samsotha
Paul Samsotha

Reputation: 209004

In a Servlet environment, Jersey runs as a servlet or servlet filter. No way around that. So how does it work without declaring it in the web.xml? Two main components to this functionality

  • Programmatic registration of Servlet components (i.e. servlets and fitlers). You can do a Google search, and you should find some hits of examples.

  • Servlet pluggability introduced in Servlet 3.x. How it works is you implement a ServletContainerInitializer, list that implementation in a file named javax.servlet.ServletContainerInitializer, and put that file in the META-INF/services directory of the jar. The servlet container should scan jars looking for this file. When it finds on, it sees the implementation, finds the implementation, instantiates it, then calls it onStartup method.

    Jersey has such an implementation of the SevletContainerInitializer in the JerseyServletContainerInitializer. This class is located in the jersey-container-servlet jar. So you need this jar for this to work. If you look at this method, this is where you will see the programmatic registration of the ServletContainer (the same one that yo would declare in the web.xml

But that's not all. We still need some way of configuring our application, at the least declare the servlet mapping. That's where the Application class and the @ApplicationPath annotation come in. We would extend the Application class and and annotate the @ApplicationPath("/path") where "path" is the same as the servlet mapping in the web.xml

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

This is standard JAX-RS. With Jersey normally instead of an Application class, we use a ResourceConfig class (which is a subclass of Application)

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

You can see more about Jersey deployment options in a Servlet 3.x environment, here.

It should also be noted, that a Java EE server has the JAX-RS implementation, so we only need to add the javaee-api jar to our application as provided dependency. But in a servlet container, we need to provide our own implementation, Jersey being such an implementation.

If you are using Maven, the main dependency you'll need is this one

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>${jersey2.version}</version>
</dependency>

This will pull a bunch of other jars in. You you aren't using Maven, then you can download all the jars here (the JAX-RS 2.0 RI bundle), and put all those into your application.

See Also:

Upvotes: 7

Related Questions