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, withoutweb.xml
Using the
Application
subclass andweb.xml
Using
web.xml
, without theApplication
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.
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.
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.
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>
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>
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.
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>
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).