Book Image

RESTful Java Web Services, Second Edition

Book Image

RESTful Java Web Services, Second Edition

Overview of this book

Table of Contents (17 chapters)
RESTful Java Web Services Second Edition
Credits
About the Author
Acknowledgments
About the Reviewers
www.PacktPub.com
Preface
Index

Packaging and deploying JAX-RS applications


There are multiple ways to configure, package, and deploy a JAX-RS application. While configuring an application, you can use an annotation-based approach (for the Servlet 3.x based container) and thereby avoid deployment descriptors such as web.xml. Alternatively, you can use a mix of both approaches, which uses both annotations and web.xml. This section describes the various configurations and packaging models followed for a JAX-RS web service application.

The JAX-RS specification states that a RESTful web service must be packaged as part of a web application if you want to run it in a container (web server or application server). Following this rule, any JAX-RS application that you want to deploy on a server must be packaged in a Web Application Archive (WAR) file. If the web service is implemented using an EJB, it must be packaged and deployed within a WAR file. The application classes are packaged in WEB-INF/classes or WEB-INF/lib and all the dependent library jars are packaged in WEB-INF/lib. You can configure a JAX-RS application in following ways:

  • Using the javax.ws.rs.core.Application subclass, without web.xml

  • Using the Application subclass and web.xml

  • Using web.xml, without the Application subclass

Let's take a closer look at all these packaging models. The following discussion presumes the Jersey framework as the JAX-RS implementation. Though the basic packaging model is the same across all JAX-RS implementations, the exact value for certain metadata fields used in deployment descriptors, such as the servlet class, may change with each implementation. Please refer to the product documentation if you are using a different JAX-RS implementation.

Packaging JAX-RS applications with an Application subclass

The servlet 3.0 specification allows you to build a web application without web.xml. You will annotate the component as appropriate without describing them in web.xml. JAX-RS also follows the same model and allows you to annotate components for supplying metadata required by the runtime and thereby avoiding deployment descriptors, such as web.xml, for holding the metadata.

In this packaging model, you will define a class that extends javax.ws.rs.core.Application. Your subclass will have entries for all root resources and providers, such as filters, interceptors, message body reader/writers, and feature classes that are used in the application. Additionally, this class can return a map of custom application-wide properties. You can use the @javax.ws.rs.ApplicationPath annotation on the subclass to configure the context path for the RESTful web service.

The following is an example of a class that extends javax.ws.rs.core.Application. This class configures all the REST resources, message body reader, writer, filters, and interceptors that are used in the application:

//Other imports are removed for brevity
import javax.ws.rs.core.Application;

@javax.ws.rs.ApplicationPath("webresources")
public class HRApplication extends Application {
    //Get a set of root resource, provider and feature classes.
    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new java.util.HashSet<>();
        //Configure resource classes
        resources.add(HRResource.class);
       //Message body writer
        resources.add(CSVMessageBodyWriter.class);
        //Filters and interceptors
        resources.add(CORSResponseFilter.class);
        resources.add(ZippedWriterInterceptor.class);
        return resources;
    }
   //Get a map of custom application-wide properties
    @Override
    public Map<String, Object> getProperties() {
        return super.getProperties();
    }
   //Get Singletons instances of set of root resource, 
    //provider and feature classes
    @Override
    public Set<Object> getSingletons() {
        return super.getSingletons();
    }
}

The default implementations of getClasses() and getSingletons() return empty sets, which tells runtime to add all resource and provider classes that are identified via annotations. While deploying the application, the JAX-RS runtime scans the deployed artifacts for the REST resource classes (identified by the @Path annotation) and providers (identified by the @Provider annotation), and automatically discovers and registers all components before the activation of the application.

This packaging model assumes that the application is not bundled with any web.xml file. This model leverages the pluggability mechanism offered by the servlet 3.x framework to enable portability between containers. You cannot follow this model if you are deploying the application into servlet 2.x based containers.

If you would like to have a web.xml file for the application, then follow the steps given in the next section, for configuring the applications with a servlet, which will show you how to update a web.xml file with entries for the JAX-RS servlet.

Packaging the JAX-RS applications with web.xml and an Application subclass

Sometimes, you may want to use both Application subclass and web.xml for your JAX-RS application. This deployment model will be the best fit for the following scenarios, where you will use web.xml to configure the following:

  • To configure security for the application

  • To specify some context parameters for the application

  • To configure some container-specific parameters for the application

Depending on the capabilities of the target server, configuration entries in web.xml varies. This will be explained in the following sections.

Configuring web.xml for a servlet 2.x container

The following example illustrates the web.xml entries that you make for packaging a JAX-RS application, which contains both the Application subclass and web.xml. This example uses com.packtpub.rest.ch4.service.HRApplication as the application subclass. The following web.xml shows configuration entries that you may need to add for deploying into a servlet 2.x container. If there are multiple application subclasses, then you will need to configure them separately:

<web-app ... >
    <servlet>
        <servlet-name>jaxrs.servlet</servlet-name>

        <!—- Set this to fully qualified name of the 
        Servlet offered by the JAX-RS runtime -->
        <servlet-class>
        org.glassfish.jersey.servlet.ServletContainer
        </servlet-class>

        <!-- Set this element to define the class that 
       extends the javax.ws.rs.core.Application -->
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>
             com.packtpub.rest.ch4.service.HRApplication
            </param-value>
        </init-param>
        <!--Use init params as appropriate-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>jaxrs.servlet</servlet-name>
        <url-pattern>/webresources/*</url-pattern>
    </servlet-mapping>
</web-app>

Configuring web.xml for a Servlet 3.x container

If you are deploying the application on a servlet 3.x container, then the configuration entries are much simpler. In this case, you just need to mention the servlet name and servlet mapping, as follows (for each application subclass bundled in the application). Runtime will automatically add the servlet class and assign it to the name that you'd specified:

<web-app ...
    <servlet>
       <!-- Set this element to the fully qualified 
       name of the class that extends javax.ws.rs.core.Application
       -->
        <servlet-name>
         com.packtpub.rest.ch4.service.HRApplication
        </servlet-name> 
       <!-- servlet-class and init-param are not needed -->       
    </servlet>   
    <servlet-mapping>
        <servlet-name>
         com.packtpub.rest.ch4.service.HRApplication
        </servlet-name>
        <url-pattern>/webresources/*</url-pattern>
    </servlet-mapping>
</web-app>

Packaging the JAX-RS applications with web.xml and without an Application subclass

In some cases, your JAX-RS application will not have any Application subclass apart from web.xml. Though this scenario is rare, the framework supports such a packaging model.

Configuring web.xml for the servlet 2.x container

If the JAX-RS application does not have an Application subclass in the project, then you need to specify a fully qualified servlet class that is used by the JAX-RS runtime, and a servlet-mapping entry in web.xml. You can also specify the package where the runtime should scan though to find the JAX-RS components, such as class resources, filters, interceptors, and so on.

The following example shows the configuration entries that you may need to make in web.xml to deploy a JAX-RS application without the Application subclass on the servlet 2.0 based container:

<web-app>
    <servlet> 
        <servlet-name>jaxrs.servlet</servlet-name>
        <servlet-class>
         org.glassfish.jersey.servlet.ServletContainer
        </servlet-class>
        <!-- Register resources and providers
         under com.packtpub.rest -->
        <init-param>
            <param-name>
             jersey.config.server.provider.packages</param-name>
            <param-value>com.packtpub.rest</param-value>
        </init-param>

        <!—
         Register custom providers 
        (not needed if they are in com.packtpub.rest)  -->
        <init-param>
            <param-name>
             jersey.config.server.provider.classnames</param-name>
            <param-value> 
             com.packtpub.rest.filetr.SecurityRequestFilter;
             com.packtpub.rest.filetr.Logger
           </param-value>
        </init-param>   
    </servlet>
    <servlet-mapping>
        <servlet-name>jaxrs.servlet</servlet-name>
        <url-pattern>/webresources/*</url-pattern>
    </servlet-mapping>

</web-app>

Configuring web.xml for the servlet 3.x container

The following web.xml shows the configurations to deploy a JAX-RS application on the servlet 3.0 container. In this case, we are adding only the mapping entry, not the corresponding servlet class. The container is responsible for adding the corresponding servlet class automatically, for the javax.ws.rs.core.Application servlet name. The following web.xml demonstrates this configuration:

<web-app ...>
    <servlet>
        <servlet-name>javax.ws.rs.core.Application</servlet-name>
    </servlet>
    <servlet-mapping>
        <servlet-name>javax.ws.rs.core.Application</servlet-name>
        <url-pattern>/webresources/*</url-pattern>
    </servlet-mapping>
</web-app>

Note that in the preceding case, runtime will automatically detect and register JAX-RS components (by scanning through the annotations).