Chapter 4. Application Deployment and Runtime Environments
Prev |  | Next

Links: Table of Contents | Single HTML

# Chapter 4. Application Deployment and Runtime Environments

## 4.1. Introduction

This chapter is an overview of various server-side environments currently capable of running JAX-RS applications on top of Jersey server runtime. Jersey supports wide range of server environments from lightweight http containers up to full-fledged Java/Jakarta EE servers. Jersey applications can also run in an OSGi runtime. The way how the application is published depends on whether the application shall run in a Java SE environment or within a container.

### Note

This chapter is focused on server-side Jersey deployment models. The Jersey client runtime does not have any specific container requirements and runs in plain Java SE 8 or higher runtime.

## 4.2. JAX-RS Application Model

JAX-RS provides a deployment agnostic abstract class Application for declaring root resource and provider classes, and root resource and provider singleton instances. A Web service may extend this class to declare root resource and provider classes. For example,

Example 4.1. Deployment agnostic application model

    public class MyApplication extends Application {
        @Override
        public Set<Class<?>> getClasses() {
            Set<Class<?>> s = new HashSet<Class<?>>();
            s.add(HelloWorldResource.class);
            return s;
        }
    }

Alternatively it is possible to reuse ResourceConfig - Jersey's own implementations of `Application` class. This class can either be directly instantiated and then configured or it can be extended and the configuration code placed into the constructor of the extending class. The approach typically depends on the chosen deployment runtime.

Compared to `Application`, the `ResourceConfig` provides advanced capabilities to simplify registration of JAX-RS components, such as scanning for root resource and provider classes in a provided classpath or a set of package names etc. All JAX-RS component classes that are either manually registered or found during scanning are automatically added to the set of classes that are returned by `getClasses`. For example, the following application class that extends from `ResourceConfig` scans during deployment for JAX-RS components in packages `org.foo.rest` and `org.bar.rest`:

### Note

Package scanning ignores an inheritance and therefore `@Path` annotation on parent classes and interfaces will be ignored. These classes won't be registered as the JAX-RS component classes.

Example 4.2. Reusing Jersey implementation in your custom application model

    public class MyApplication extends ResourceConfig {
        public MyApplication() {
            packages("org.foo.rest;org.bar.rest");
        }
    }

### Note

Later in this chapter, the term `Application` subclass is frequently used. Whenever used, this term refers to the JAX-RS Application Model explained above.

## 4.3. Auto-Discoverable Features

By default Jersey 3.x does not implicitly register any extension features from the modules available on the classpath, unless explicitly stated otherwise in the documentation of each particular extension. Users are expected to explicitly register the extension Features using their `Application` subclass. Since Jersey 3.1.0 all features which extends Feature and are listed as SPI of the `Feature` interface are automatically registered (not required to be registered within `Application` subclass). For server site Jersey 3.1.0 also registers SPIs for `DynamicFeature` interface. For a few Jersey provided modules however there is no need to explicitly register their extension `Feature`s as these are discovered and registered in the Configuration (on client/server) automatically by Jersey runtime whenever the modules implementing these features are present on the classpath of the deployed JAX-RS application. The modules that are automatically discovered include:

- JSON binding feature from `jersey-media-moxy`

- `jersey-media-json-processing`

- `jersey-bean-validation`

Besides these modules there are also few features/providers present in `jersey-server` module that are discovered by this mechanism and their availability is affected by Jersey auto-discovery support configuration (see Section 4.3.1, “Configuring Feature Auto-discovery Mechanism”), namely:

- WadlFeature - enables WADL processing.

- UriConnegFilter - a URI-based content negotiation filter.

Almost all Jersey auto-discovery implementations have `AutoDiscoverable.DEFAULT_PRIORITY` `@Priority` set.

### Note

Auto discovery functionality is in Jersey supported by implementing an internal `AutoDiscoverable` Jersey SPI. This interface is not public at the moment, and is subject to change in the future, so be careful when trying to use it.

### 4.3.1. Configuring Feature Auto-discovery Mechanism

The mechanism of feature auto-discovery in Jersey that described above is enabled by default. It can be disabled by using special (common/server/client) properties:

Common auto discovery properties

- CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE

  When set, disables auto discovery globally on client/server.

- CommonProperties.JSON_PROCESSING_FEATURE_DISABLE

  When set, disables configuration of Json Processing (JSR-353) feature.

- CommonProperties.MOXY_JSON_FEATURE_DISABLE

  When set, disables configuration of MOXy Json feature.

For each of these properties there is a client/server counter-part that is only honored by the Jersey client or server runtime respectively (see ClientProperties/ServerProperties). When set, each of these client/server specific auto-discovery related properties overrides the value of the related common property.

### Note

In case an auto-discoverable mechanism (in general or for a specific feature) is disabled, then all the features, components and/or properties, registered by default using the auto-discovery mechanism have to be registered manually.

## 4.4. Feature and Dynamic Feature SPI automatic registration

Since Jersey 3.1.0 there is a new specification requirement to automatically discover and register classes that implement Feature and DynamicFeature interfaces. This is being done via SPI search thus all those classes in order to be discovered automatically shall be listed as SPIs for given interfaces. This automatic registration can also be disabled by `jakarta.ws.rs.loadServices` (which is new specification property) to be set to false. This is also valid for CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE lookup.

## 4.5. Configuring the Classpath Scanning

Jersey uses a common Java Service Provider mechanism to obtain all service implementations. It means that Jersey scans the whole class path to find appropriate `META-INF/services/` files. The class path scanning may be time consuming. The more jar or war files on the classpath the longer the scanning time. In use cases where you need to save every millisecond of application bootstrap time, you may typically want to disable the services provider lookup in Jersey.

List of SPIs recognized by Jersey

- `Feature` (server, client) - Features are being registered similarly to AutoDiscoverable feature. In addition property jakarta.ws.rs.loadServices is checked before registration.

- `AutoDiscoverable` (server, client) - it means if you disable service loading the AutoDiscoverable feature is automatically disabled too

- `ForcedAutoDiscoverable` (server, client) - Jersey always looks for these auto discoverable features even if the service loading is disabled

- `HeaderDelegateProvider` (server, client)

- `DynamicFeature` (server) - Similar to `Feature` registration but only for server.

- `ComponentProvider` (server)

- `ContainerProvider` (server)

- `AsyncContextDelegateProvider` (server/Servlet)

List of additional SPIs recognized by Jersey in case the `metainf-services` module is on the classpath

- `MessageBodyReader` (server, client)

- `MessageBodyWriter` (server, client)

- `ExceptionMapper` (server, client)

Since it is possible to configure all SPI implementation classes or instances manually in your `Application` subclass, disabling services lookup in Jersey does not affect any functionality of Jersey core modules and extensions and can save dozens of ms during application initialization in exchange for a more verbose application configuration code.

The services lookup in Jersey (enabled by default) can be disabled via a dedicated CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE property. There is a client/server counter-part that only disables the feature on the client or server respectively: ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE/ServerProperties.METAINF_SERVICES_LOOKUP_DISABLE. As in all other cases, the client/server specific properties overrides the value of the related common property, when set.

For example, following code snippet disables service provider lookup and manually registers implementations of different JAX-RS and Jersey provider types (ContainerRequestFilter, Feature, ComponentProvider and ContainerProvider):

Example 4.3. Registering SPI implementations using ResourceConfig

    ResourceConfig resourceConfig = new ResourceConfig(MyResource.class);
    resourceConfig.register(org.glassfish.jersey.server.filter.UriConnegFilter.class);
    resourceConfig.register(org.glassfish.jersey.server.validation.ValidationFeature.class);
    resourceConfig.register(org.glassfish.jersey.server.spring.SpringComponentProvider.class);
    resourceConfig.register(org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainerProvider.class);
    resourceConfig.property(ServerProperties.METAINF_SERVICES_LOOKUP_DISABLE, true);

Similarly, in scenarios where the deployment model requires extending the `Application` subclass (e.g. in all Servlet container deployments), the following code could be used to achieve the same application configuration:

Example 4.4. Registering SPI implementations using `ResourceConfig` subclass

    public class MyApplication extends ResourceConfig {
        public MyApplication() {
            register(org.glassfish.jersey.server.filter.UriConnegFilter.class);
            register(org.glassfish.jersey.server.validation.ValidationFeature.class);
            register(org.glassfish.jersey.server.spring.SpringComponentProvider.class);
            register(org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainerProvider.class);
            property(ServerProperties.METAINF_SERVICES_LOOKUP_DISABLE, true);
        }
    }

## 4.6. Java SE Deployment Environments

### 4.6.1. HTTP servers

Java based HTTP servers represent a minimalistic and flexible way of deploying Jersey application. The HTTP servers are usually embedded in the application and configured and started programmatically. In general, Jersey container for a specific HTTP server provides a custom factory method that returns a correctly initialized HTTP server instance.

#### 4.6.1.1. JDK Http Server

Starting with Java SE 6, Java runtime ships with a built-in lightweight HTTP server. Jersey offers integration with this Java SE HTTP server through the `jersey-container-jdk-http` container extension module. Instead of creating the `HttpServer` instance directly, use the `createHttpServer()` method of `JdkHttpServerFactory`, which creates the `HttpServer` instance configured as a Jersey container and initialized with the supplied `Application` subclass.

Creating new Jersey-enabled jdk http server is as easy as:

Example 4.5. Using Jersey with JDK HTTP Server

     URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
    ResourceConfig config = new ResourceConfig(MyResource.class);
    HttpServer server = JdkHttpServerFactory.createHttpServer(baseUri, config);

A JDK HTTP Container dependency needs to be added:

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-jdk-http</artifactId>
        <version>3.1.8</version>
    </dependency>

#### 4.6.1.2. Grizzly HTTP Server

Grizzly is a multi-protocol framework built on top of Java NIO. Grizzly aims to simplify development of robust and scalable servers. Jersey provides a container extension module that enables support for using Grizzly as a plain vanilla HTTP container that runs JAX-RS applications. Starting a Grizzly server to run a JAX-RS or Jersey application is one of the most lightweight and easy ways how to expose a functional RESTful services application.

Grizzly HTTP container supports injection of Grizzly-specific `org.glassfish.grizzly.http.server.Request` and `org.glassfish.grizzly.http.server.Response` instances into JAX-RS and Jersey application resources and providers. However, since Grizzly `Request` is not proxiable, the injection of Grizzly `Request` into singleton (by default) JAX-RS / Jersey providers is only possible via `jakarta.inject.Provider` instance. (Grizzly `Response` does not suffer the same restriction.)

Example 4.6. Using Jersey with Grizzly HTTP Server

    URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
        ResourceConfig config = new ResourceConfig(MyResource.class);
        HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, config);

The container extension module dependency to be added is:

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-grizzly2-http</artifactId>
        <version>3.1.8</version>
    </dependency>

### Note

Jersey uses Grizzly extensively in the project unit and end-to-end tests via test framework.

#### 4.6.1.3. Simple server

Simple is a framework which allows developers to create a HTTP server instance and embed it within an application. Again, creating the server instance is achieved by calling a factory method from the `jersey-container-simple-http` container extension module.

Simple framework HTTP container supports injection of Simple framework-specific `org.simpleframework.http.Request` and `org.simpleframework.http.Response` instances into JAX-RS and Jersey application resources and providers.

Example 4.7. Using Jersey with the Simple framework

    URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
        ResourceConfig config = new ResourceConfig(MyResource.class);
        SimpleContainer server = SimpleContainerFactory.create(baseUri, config);

The necessary container extension module dependency in this case is:

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-simple-http</artifactId>
        <version>3.1.8</version>
    </dependency>

### Note

Simple framework HTTP container does not support deployment on context paths other than root path ("`/`"). Non-root context path is ignored during deployment.

#### 4.6.1.4. Jetty HTTP Server

Jetty is a popular Servlet container and HTTP server. We will not look into Jetty's capabilities as a Servlet container (although we are using it in our tests and examples), because there is nothing specific to Jetty when using a Servlet-based deployment model, which is extensively described later in our Section 4.8, “Servlet-based Deployment” section. We will here only focus on describing how to use Jetty's HTTP server.

Jetty HTTP container supports injection of Jetty-specific `org.eclipse.jetty.server.Request` and `org.eclipse.jetty.server.Response` instances into JAX-RS and Jersey application resources and providers. However, since Jetty HTTP `Request` is not proxiable, the injection of Jetty `Request` into singleton (by default) JAX-RS / Jersey providers is only possible via `jakarta.inject.Provider` instance. (Jetty `Response` does not suffer the same restriction.)

Example 4.8. Using Jersey with Jetty HTTP Server

    URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
    ResourceConfig config = new ResourceConfig(MyResource.class);
    Server server = JettyHttpContainerFactory.createServer(baseUri, config);

And, of course, we add the necessary container extension module dependency:

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-jetty-http</artifactId>
        <version>3.1.8</version>
    </dependency>

### Note

Jetty HTTP container does not support deployment on context paths other than root path ("`/`"). Non-root context path is ignored during deployment.

#### 4.6.1.5. Netty HTTP Server

Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients. Jersey supports Netty as a container and as a client connector - this chapter will present how to use the container.

Example 4.9. Using Jersey with Netty HTTP Server

    URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
    ResourceConfig resourceConfig = new ResourceConfig(HelloWorldResource.class);
    Channel server = NettyHttpContainerProvider.createServer(baseUri, resourceConfig, false);

And, of course, we add the necessary container extension module dependency:

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-netty-http</artifactId>
        <version>3.1.8</version>
    </dependency>

### Note

Netty HTTP container does not support deployment on context paths other than root path ("`/`"). Non-root context path is ignored during deployment.

### 4.6.2. Jakarta REST Bootstrap API

Jakarta REST 3.1 comes with a new API for starting an application in Java SE environment. This `Bootstrap` API is mainly represented by `SeBootstrap` interface. The Jakarta REST application is started as follows:

    Application application = new MyApplication();
    SeBootstrap.Configuration.Builder configBuilder = SeBootstrap.Configuration.builder();
    CompletionStage<SeBootstrap.Instance> completionStage = SeBootstrap.start(application, configBuilder.build());

Later, when the SE application is no longer needed, it can be shutdown as follows:

    CompletionStage<SeBootstrap.Instance> completionStage = ...
    SeBootstrap.Instance instance = completionStage().get();
    instance.stop();

The `SeBootstrap.Configuration` allows for configuring the Jersey runtime. The Jakarta REST 3.1 allows for configuring the HTTP port, the protocol (HTTP), the hostname, the root path, and SSL. The `SeBootstrap` is configured as follows:

    SeBootstrap.Configuration.Builder configBuilder = SeBootstrap.Configuration.builder();
    configBuilder.property(SeBootstrap.Configuration.PROTOCOL, "HTTP")
        .property(SeBootstrap.Configuration.HOST, "localhost")
        .property(SeBootstrap.Configuration.PORT, 1234)
        .property(SeBootstrap.Configuration.ROOT_PATH, "/root/path");

The `SeBootstrap` deployment is backed up by an HTTP server described in Section 4.6.1, “HTTP servers”. If multiple Jersey container modules are on the classpath, the first found is used.

### 4.6.3. Jersey WebServer SPI

Jersey WebServer and WebServerProvider are SPI interfaces similar to ContainerProvider but they are used for the SE deployment. They serve as a bridge between Jersey containers and `SeBootstrap` API. The Jakarta REST application can be started as follows:

    Application application = new MyApplication();
    SeBootstrap.Configuration.Builder configBuilder = SeBootstrap.Configuration.builder();
    WebServer webServer = WebServerFactory.createServer(WebServer.class, application, configBuilder.build());

Later, when the SE application is no longer needed, it can be shutdown as follows:

    WebServer webServer = ...
    webServer.stop();

WebServerFactory is used to automatically choose among available implementations on a classpath. If there are multiple implementations available, the first found is used. The user can choose the implementation of a `WebServer` by a concrete WebServer subclass, for instance:

    WebServer webServer = WebServerFactory.createServer(GrizzlyHttpServer.class, application, configBuilder.build());

Another way to choose the `WebServer` implementation is by the `WebServerProvider` implementation:

    WebServer webServer = GrizzlyHttpServerProvider.createServer(WebServer.class, application, configBuilder.build());

For additional customization of the WebServer settings, see Section A.3, “SeBootstrap and WebServer related configuration properties”.

### Warning

When the port is set to -1, the default ports are used. Unlike the default ports used by the Section 4.6.1, “HTTP servers”, the `SeBootstrap` API and `WebServer` SPI use default ports 8080 and 8443, respectively.

When the port is set to 0, the implementation scans for a free port. The privileged ports are skipped, and the scanning starts with port 1024.

Using the restricted ports can be ensured either by setting directly the port, or by setting ServerProperties.WEBSERVER_ALLOW_PRIVILEGED_PORTS property to true in the `SeBootstrap.Configuration`

## 4.7. Creating programmatic JAX-RS endpoint

JAX-RS specification also defines the ability to programmatically create a JAX-RS application endpoint (i.e. container) for any instance of a `Application` subclass. For example, Jersey supports creation of Grizzly `HttpHandler` instance as follows:

    HttpHandler endpoint = RuntimeDelegate.getInstance()
            .createEndpoint(new MyApplication(), HttpHandler.class);

Once the Grizzly `HttpHandler` endpoint is created, it can be used for in-process deployment to a specific base URL.

## 4.8. Servlet-based Deployment

In a Servlet container, JAX-RS defines multiple deployment options depending on the Servlet API version supported by the Servlet container. Following sections describe these options in detail.

### 4.8.1. Servlet 2.x way

Jersey integrates with any Servlet containers supporting at least Servlet 2.5 specification. Running on a Servlet container that supports Servlet API 5.0 it's required to adjust this approach to jakartified Servlet API. This includes Jakarta EE 9 namespaces which is applied since the 5.x Servlet API version. In this section we will focus on the basic deployment models available in any Servlet 2.5 container.

Using Servlet 2.x way, you have to explicitly declare the Jersey container Servlet in your Web application's `web.xml` deployment descriptor file.

Example 4.10. Hooking up Jersey as a Servlet

    <web-app>
                            <servlet>
                            <servlet-name>MyApplication</servlet-name>
                            <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
                            <init-param>
                            ...
                            </init-param>
                            </servlet>
                            ...
                            <servlet-mapping>
                            <servlet-name>MyApplication</servlet-name>
                            <url-pattern>/myApp/*</url-pattern>
                            </servlet-mapping>
                            ...
                            </web-app>

Alternatively, you can register Jersey container as a filter:

Example 4.11. Hooking up Jersey as a Servlet Filter

    <web-app>
                            <filter>
                            <filter-name>MyApplication</filter-name>
                            <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
                            <init-param>
                            ...
                            </init-param>
                            </filter>
                            ...
                            <filter-mapping>
                            <filter-name>MyApplication</filter-name>
                            <url-pattern>/myApp/*</url-pattern>
                            </filter-mapping>
                            ...
                            </web-app>

### Important

Since pure Servlet 2.x way deployment does not provide a way how to programmatically read the filter mappings in order to make application with filter work correctly, the context path of the app needs to be defined using init parameter `jersey.config.servlet.filter.contextPath` for `jersey-container-servlet-core`. Or `jersey-container-servlet` shall be used.

The content of the `<init-param>` element will vary depending on the way you decide to configure Jersey resources.

#### 4.8.1.1. Custom `Application` subclass

If you extend the Application class to provide the list of relevant root resource classes (`getClasses()`) and singletons (`getSingletons()`), i.e. your JAX-RS application model, you then need to register it in your web application `web.xml` deployment descriptor using a Servlet or Servlet filter initialization parameter with a name of `jakarta.ws.rs.Application` [sic] as follows:

Example 4.12. Configuring Jersey container Servlet or Filter to use custom `Application` subclass

    <init-param>
                                <param-name>jakarta.ws.rs.Application</param-name>
                                <param-value>org.foo.MyApplication</param-value>
                                </init-param>

Jersey will consider all the classes returned by `getClasses()` and `getSingletons()` methods of your `Application` implementation.

### Note

The name of the configuration property as defined by JAX-RS specification is indeed `jakarta.ws.rs.Application` and not `jakarta.ws.rs.core.Application` as one might expect.

#### 4.8.1.2. Jersey package scanning

If there is no configuration properties to be set and deployed application consists only from resources and providers stored in particular packages, you can instruct Jersey to scan these packages and register any found resources and providers automatically:

Example 4.13. Configuring Jersey container Servlet or Filter to use package scanning

    <init-param>
                                <param-name>jersey.config.server.provider.packages</param-name>
                                <param-value>
                                org.foo.myresources,org.bar.otherresources
                                </param-value>
                                </init-param>
                                <init-param>
                                <param-name>jersey.config.server.provider.scanning.recursive</param-name>
                                <param-value>false</param-value>
                                </init-param>

Jersey will automatically discover the resources and providers in the selected packages. You can also decide whether Jersey should recursively scan also sub-packages by setting the `jersey.config.server.provider.scanning.recursive` property. The default value is `true`, i.e. the recursive scanning of sub-packages is enabled.

#### 4.8.1.3. Selecting concrete resource and provider classes

While the above-mentioned package scanning is useful esp. for development and testing, you may want to have a little bit more control when it comes to production deployment in terms of being able to enumerate specific resource and provider classes. In Jersey it is possible to achieve this even without a need to implement a custom `Application` subclass. The specific resource and provider fully-qualified class names can be provided in a comma-separated value of `jersey.config.server.provider.classnames` initialization parameter.

Example 4.14. Configuring Jersey container Servlet or Filter to use a list of classes

    <init-param>
                            <param-name>jersey.config.server.provider.classnames</param-name>
                            <param-value>
                            org.foo.myresources.MyDogResource,
                            org.bar.otherresources.MyCatResource
                            </param-value>
                            </init-param>

### Note

All of the techniques that have been described in this section also apply to Servlet containers that support Servlet API 5.0 with jakartified adjustments. Newer Servlet specifications only give you additional features, deployment options and more flexibility.

### 4.8.2. Servlet 5.x Container

#### 4.8.2.1. Descriptor-less deployment

There are multiple deployment options in the Servlet 5.0 container for a JAX-RS application defined by implementing a custom Application subclass. For simple deployments, no `web.xml` is necessary at all. Instead, an @ApplicationPath annotation can be used to annotate the custom Application subclass and define the base application URI for all JAX-RS resources configured in the application:

Example 4.15. Deployment of a JAX-RS application using `@ApplicationPath` with Servlet 5.0

    @ApplicationPath("resources")
    public class MyApplication extends ResourceConfig {
        public MyApplication() {
            packages("org.foo.rest;org.bar.rest");
        }
    }

### Note

There are many other convenience methods in the `ResourceConfig` that can be used in the constructor of your custom subclass to configure your JAX-RS application, see ResourceConfig API documentation for more details.

In case you are not providing `web.xml` deployment descriptor for your maven-based web application project, you need to configure your `maven-war-plugin` to ignore the missing `web.xml` file by setting failOnMissingWebXml configuration property to `false` in your project `pom.xml` file:

Example 4.16. Configuration of maven-war-plugin to ignore missing `web.xml`

    <plugins>
        ...
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.3</version>
            <configuration>
                <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
        </plugin>
        ...
    </plugins>

#### 4.8.2.2. Deployment using `web.xml` descriptor

Another Servlet 5.x container deployment model is to declare the JAX-RS application details in the `web.xml`. This is typically suitable for more complex deployments, e.g. when security model needs to be properly defined or when additional initialization parameters have to be passed to Jersey runtime. JAX-RS 1.1 and later specifies that a fully qualified name of the class that implements Application may be used in the definition of a `<servlet-name>` element as part of your application's `web.xml` deployment descriptor.

Following example illustrates this approach:

Example 4.17. Deployment of a JAX-RS application using `web.xml` with Servlet 5.0

    <web-app>
        <servlet>
            <servlet-name>org.foo.rest.MyApplication</servlet-name>
        </servlet>
        ...
        <servlet-mapping>
            <servlet-name>org.foo.rest.MyApplication</servlet-name>
            <url-pattern>/resources</url-pattern>
        </servlet-mapping>
        ...
    </web-app>

Note that the `<servlet-class>` element is omitted from the Servlet declaration. This is a correct declaration utilizing the Servlet 5.0 extension mechanism described in detail in the Section 4.8.2.3, “Servlet Pluggability Mechanism” section. Also note that `<servlet-mapping>` is used in the example to define the base resource URI.

#### 4.8.2.3. Servlet Pluggability Mechanism

Servlet framework pluggability mechanism is a feature introduced with Servlet 3.0 specification. It simplifies the configuration of various frameworks built on top of Servlets. Instead of having one `web.xml` file working as a central point for all the configuration options, it is possible to modularize the deployment descriptor by using the concept of so-called web fragments - several specific and focused `web.xml` files. A set of web fragments basically builds up the final deployment descriptor. This mechanism also provides SPI hooks that enable web frameworks to register themselves in the Servlet container or customize the Servlet container deployment process in some other way. This section describes how JAX-RS and Jersey leverage the Servlet pluggability mechanism.

##### 4.8.2.3.1. JAX-RS application without an `Application` subclass

If no `Application` (or `ResourceConfig`) subclass is present, Jersey will dynamically add a Jersey container Servlet and set its name to `jakarta.ws.rs.core.Application`. The web application path will be scanned and all the root resource classes (the classes annotated with @Path annotation) as well as any providers that are annotated with @Provider annotation packaged with the application will be automatically registered in the JAX-RS application. The web application has to be packaged with a deployment descriptor specifying at least the mapping for the added `jakarta.ws.rs.core.Application` Servlet:

Example 4.18. `web.xml` of a JAX-RS application without an `Application` subclass

    <web-app version="5.0"
        xmlns="https://jakarta.ee/xml/ns/jakartaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

        <!-- Servlet declaration can be omitted in which case
             it would be automatically added by Jersey -->
        <servlet>
            <servlet-name>jakarta.ws.rs.core.Application</servlet-name>
        </servlet>

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

##### 4.8.2.3.2. JAX-RS application with a custom `Application` subclass

When a custom `Application` subclass is provided, in such case the Jersey server runtime behavior depends od whether or not there is a Servlet defined to handle the application subclass.

If the `web.xml` contains a Servlet definition, that has an initialization parameter `jakarta.ws.rs.Application` whose value is the fully qualified name of the `Application` subclass, Jersey does not perform any additional steps in such case.

If no such Servlet is defined to handle the custom `Application` subclass, Jersey dynamically adds a Servlet with a fully qualified name equal to the name of the provided `Application` subclass. To define the mapping for the added Servlet, you can either annotate the custom `Application` subclass with an @ApplicationPath annotation (Jersey will use the annotation value appended with `/*` to automatically define the mapping for the Servlet), or specify the mapping for the Servlet in the `web.xml` descriptor directly.

In the following example, let's assume that the JAX-RS application is defined using a custom `Application` subclass named `org.example.MyApplication`. Then the `web.xml` file could have the following structure:

Example 4.19.

    <web-app version="5.0"
        xmlns="https://jakarta.ee/xml/ns/jakartaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

        <!-- Servlet declaration can be omitted in which case
             it would be automatically added by Jersey -->
        <servlet>
            <servlet-name>org.example.MyApplication</servlet-name>
        </servlet>

        <!-- Servlet mapping can be omitted in case the Application subclass
             is annotated with @ApplicationPath annotation; in such case
             the mapping would be automatically added by Jersey -->
        <servlet-mapping>
            <servlet-name>org.example.MyApplication</servlet-name>
            <url-pattern>/myresources/*</url-pattern>
        </servlet-mapping>
    </web-app>

### Note

If your custom `Application` subclass is packaged in the `war`, it defines which resources will be taken into account.

- If both `getClasses()` and `getSingletons()` methods return an empty collection, then ALL the root resource classes and providers packaged in the web application archive will be used, Jersey will automatically discover them by scanning the `.war` file.
- If any of the two mentioned methods - `getClasses()` or `getSingletons()` returns a non-empty collection, only those classes and/or singletons will be published in the JAX-RS application.

Table 4.1. Servlet 3 Pluggability Overview

Condition | Jersey action | Servlet Name | `web.xml`
--- | --- | --- | ---
No `Application` subclass | Adds Servlet | `jakarta.ws.rs.core.Application` | Servlet mapping is required
`Application` subclass handled by existing Servlet | No action | Already defined | Not required
`Application` subclass NOT handled by existing Servlet | Adds Servlet | FQN of the `Application` subclass | if no `@ApplicationPath` on the `Application` subclass, then Servlet mapping is required

### 4.8.3. Jersey Servlet container modules

Jersey uses its own `ServletContainer` implementation of Servlet and Servlet Filter API to integrate with Servlet containers. As any Jakartified JAX-RS runtime (JAX-RS spec 3.0), Jersey provides support for Servlet containers that support Servlet specification version 5.0 or higher is required.

When deploying to a Servlet container, Jersey application is typically packaged as a `.war` file. As with any other Servlet application, JAX-RS application classes are packaged in `WEB-INF/classes` or `WEB-INF/lib` and required application libraries are located in `WEB-INF/lib`. For more details, please refer to the Servlet Specification (Servlet 5 spec).

Jersey provides two Servlet modules. The first module is the Jersey core Servlet module that provides the core Servlet integration support and is required in any Servlet 5 or higher container:

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet-core</artifactId>
    </dependency>

To support additional Servlet 5.x deployment modes and asynchronous JAX-RS resource programming model, an additional Jersey module is required:

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
    </dependency>

The `jersey-container-servlet` module depends on `jersey-container-servlet-core` module, therefore when it is used, it is not necessary to explicitly declare the `jersey-container-servlet-core` dependency.

Note that in simple cases, you don't need to provide the deployment descriptor (`web.xml`) and can use the `@ApplicationPath` annotation, as described in ??? section.

## 4.9. Jakarta EE Platform

This section describes, how you can publish Jersey JAX-RS resources as various Jakarta EE platform elements. JAX-RS and Jersey give you wide choice of possibilities and it is up to your taste (and design of your application), what Jakarta EE technology you decide to use for the management of your resources.

### 4.9.1. Managed Beans

Jersey supports the use of Jakarta EE Managed beans as root resource classes, providers as well as `Application` subclasses.

In the code below, you can find an example of a bean, that uses a managed-bean interceptor defined as a JAX-RS bean. The bean is used to intercept calls to the resource method `getIt()`:

    @ManagedBean
    @Path("/managedbean")
    public class ManagedBeanResource {

        public static class MyInterceptor {
            @AroundInvoke
            public String around(InvocationContext ctx) throws Exception {
                System.out.println("around() called");
                return (String) ctx.proceed();
            }
        }

        @GET
        @Produces("text/plain")
        @Interceptors(MyInterceptor.class)
        public String getIt() {
            return "Hi managed bean!";
        }
    }

### 4.9.2. Context and Dependency Injection (CDI)

CDI beans can be used as Jersey root resource classes, providers as well as `Application` subclasses. Providers and `Application` subclasses have to be singleton or application scoped.

The next example shows a usage of a CDI bean as a JAX-RS root resource class. We assume, that CDI has been enabled. The code snipped uses the type-safe dependency injection provided in CDI by using another bean (`MyOtherCdiBean`):

    @Path("/cdibean")
    public class CdiBeanResource {
        @Inject MyOtherCdiBean bean;  // CDI injected bean

        @GET
        @Produces("text/plain")
        public String getIt() {
            return bean.getIt();
        }
    }

The above works naturally inside any Java/Jakarta EE compliant AS container. In Jersey version 2.15, container agnostic CDI support was introduced. This feature allows you to publish CDI based JAX-RS resources also in other containers. Jersey cdi-webapp example shows Jersey/CDI integration in Grizzly HTTP and Apache Tomcat server. Detailed description of Jersey CDI support outside of a fully fledged Java/Jakarta EE application container could be found in Chapter 26, Jersey CDI Container Agnostic Support.

### 4.9.3. Enterprise Java Beans (EJB)

Stateless and Singleton Session beans can be used as Jersey root resource classes, providers and/or `Application` subclasses. You can choose from annotating the methods in the EJB's local interface or directly the method in an interface-less EJB POJO. JAX-RS specifications requires its implementors to discover EJBs by inspecting annotations on classes (or local interfaces), but not in the deployment descriptors (`ejb-jar.xml`). As such, to keep your JAX-RS application portable, do not override EJB annotations or provide any additional meta-data in the deployment descriptor file.

Following example consists of a stateless EJB and a local interface used in Jersey:

    @Local
    public interface LocalEjb {
        @GET
        @Produces("text/plain")
       public String getIt();
    }

    @Stateless
    @Path("/stateless")
    public class StatelessEjbResource implements LocalEjb {
        @Override
        public String getIt() {
            return "Hi Stateless!";
        }
    }

### Note

Please note that Jersey currently does not support deployment of JAX-RS applications packaged as standalone EJB modules (ejb-jars). To use EJBs as JAX-RS resources, the EJBs need to be packaged either directly in a WAR or in an EAR that contains at least one WAR. This is to ensure Servlet container initialization that is necessary for bootstrapping of the Jersey runtime.

### 4.9.4. Jakarta EE Servers

#### 4.9.4.1. GlassFish Application Server

As explained in 2.3.1 , you don't need to add any specific dependencies on GlassFish, Jersey is already packaged within GlassFish. You only need to add the `provided`-scoped dependencies to your project to be able to compile it. At runtime, GlassFish will make sure that your application has access to the Jersey libraries.

Started with version 2.7, Jersey allows injecting Jersey specific types into CDI enabled JAX-RS components using the `@jakarta.inject.Inject` annotation. This covers also custom HK2 bindings, that are configured as part of Jersey application. The feature specifically enables usage of Jersey monitoring statistics (provided that the statistic feature is turned on) in CDI environment, where injection is the only mean to get access to monitoring data.

Since both CDI and HK2 use the same injection annotation, Jersey could get confused in certain cases, which could lead to nasty runtime issues. The get better control over what Jersey evaluates as HK2 injection, end-users could take advantage of newly introduced, Hk2CustomBoundTypesProvider, SPI. Please see the linked javadoc to get detailed information on how to use the SPI in your application.

#### 4.9.4.2. Oracle WebLogic Server

For now Oracle WebLogic Server does not support Jakartified Jersey 3.x deployment (for deployment of prior versions of Jersey please refer to corresponding manual/user guide)

In 10.3.x, a set of pre-built shared libraries were delivered with WebLogic Server to support Jersey 1.9 and 1.1.5.1 Java API for RESTful Web Services (JAX-RS) Reference Implementations (RIs). In 12.2.x, WebLogic Server supports Jersey 2.21.x (JAX-RS 2.0 RI) by default. To use the pre-built shared libraries of 10.3.x, you needed to register them with the WebLogic Server instance, and modify the web.xml and weblogic.xml deployment descriptors to use the Jersey servlet and reference the shared libraries, respectively. In 12.2.x, as WebLogic Server supports Jersey 2.21.x (JAX-RS 2.0 RI) by default, registration as a shared library with WebLogic Server is no longer required. Please read through the Upgrading a 10.3.x RESTful Web Service (JAX-RS) to 12.2.x

#### 4.9.4.3. Other Application Servers

Third party Java/Jakarta EE application servers usually ship with a JAX-RS implementation. If you want to use Jersey instead of the default JAX-RS provider, you need to add Jersey libraries to your classpath and disable the default JAX-RS provider in the container.

In general, Jersey will be deployed as a Servlet and the resources can be deployed in various ways, as described in this section. However, the exact steps will vary from vendor to vendor.

## 4.10. OSGi

OSGi support has been added to the Jersey version 1.2. Since then, you should be able to utilize standard OSGi means to run Jersey based web applications in OSGi runtime as described in the OSGi Service Platform Enterprise Specification. Jersey is currently compatible with OSGi 4.2.0, the specification could be downloaded from the OSGi 4.2.0 Download Site.

The two supported ways of running an OSGi web application are:

- WAB (Web Application Bundle)
- HTTP Service

WAB is in fact just an OSGified WAR archive. HTTP Service feature allows you to publish Jakarta EE Servlets in the OSGi runtime.

Two examples were added to the Jersey distribution to depict the above mentioned features and show how to use them with Jersey:

- WAB Example
- HTTP Service example

Both examples are multi-module maven projects and both consist of an application OSGi bundle module and a test module. The tests are based on the PAX Exam framework. Both OSGi examples also include a readme file containing instructions how to manually run the example applications using Apache Felix framework.

The rest of the chapter describes how to run the above mentioned examples on GlassFish 6 application server.

### 4.10.1. Enabling the OSGi shell in Glassfish

Since GlassFish utilizes Apache Felix, an OSGi runtime comes out of the box with GlassFish. However, for security reasons, the OSGi shell has been turned off. You can however explicitly enable it either by starting GlassFish the `asadmin` console and creating a Java system property `glassfish.osgi.start.level.final` and setting its value to `3`:

Example 4.20.

Start the admin console:

    ~/glassfish/bin$ ./asadmin
    Use "exit" to exit and "help" for online help.
    asadmin>

You can check the actual value of the java property (loaded from the configuration file):

    asadmin>  list-jvm-options
    ...
    -Dglassfish.osgi.start.level.final=2
    ...

And change the value by typing:

    asadmin>  create-jvm-options --target server -Dglassfish.osgi.start.level.final=3

The second option is to change the value in the `osgi.properties` configuration file:

    # Final start level of OSGi framework. This is used by GlassFish launcher code
    # to set the start level of the OSGi framework once server is up and running so that
    # optional services can start. The initial start level of framework is controlled using
    # the standard framework property called org.osgi.framework.startlevel.beginning
    glassfish.osgi.start.level.final=3

You can then execute the Felix shell commands by typing `osgi <felix_command>` in the `asadmin` console. For example:

    asadmin> osgi lb
    ... list of bundles ...

or launching the shell using `osgi-shell` command in the admin console (the domain must be started, otherwise the osgi shell won't launch):

    asadmin> osgi-shell
    Use "exit" to exit and "help" for online help.
    gogo$

and execute the osgi commands directly (without the "`osgi`" prefix):

    gogo$ lb
    ... list of bundles ...

### 4.10.2. WAB Example

As mentioned above, WAB is just an OSGi-fied WAR archive. Besides the usual OSGi headers it must in addition contain a special header, Web-ContextPath, specifying the web application context path. Our WAB has (beside some other) the following headers present in the manifest:

    Web-ContextPath: helloworld
    Webapp-Context: helloworld
    Bundle-ClassPath: WEB-INF/classese

Here, the second header is ignored by GlassFish, but may be required by other containers not fully compliant with the OSGi Enterprise Specification mentioned above. The third manifest header worth mentioning is the Bundle-ClassPath specifying where to find the application Java classes within the bundle archive. More about manifest headers in OSGi can be found in the OSGi Wiki.

For more detailed information on the example please see the WAB Example source code. This example does not package into a single `war` file. Instead a `war` and a set of additional `jar`s is produced during the build. See the next example to see how to deploy OSGi based Jersey application to GlassFish.

### 4.10.3. HTTP Service Example

### Note

When deploying an OSGi HTTP Service example to GlassFish, please make sure the OSGi HTTP Service bundle is installed on your GlassFish instance.

You can directly install and activate the Jersey application bundle. In case of our example, you can either install the example bundle stored locally (and alternatively build from Jersey sources):

1) Build (optional)

    examples$ cd osgi-http-service/bundle
    bundle$ mvn clean package

You can also get the binary readily compiled from Java.net Maven Repository.

2) Install into OSGi runtime:

    gogo$ install file:///path/to/file/bundle.jar
    Bundle ID: 303

or install it directly from the maven repository:

    gogo$ install https://repo1.maven.org/maven2/org/glassfish/jersey/examples/osgi-http-service/bundle/<version>/bundle-<version>.jar
    Bundle ID: 303

Make sure to replace `<version>` with an appropriate version number. Which one is appropriate depends on the specific GlassFish 6.x version you are using. The version of the bundle cannot be higher than the version of Jersey integrated in your GlassFish 6.x server. Jersey bundles declare dependencies on other bundles at the OSGi level and those dependencies are version-sensitive. If you use example bundle from let's say version 3.0.0-RC2, but Glassfish has Jersey 3.0.0-M1, dependencies will not be satisfied and bundle will not start. If this happens, the error will look something like this:

    gogo$ lb
    ...
    303 | Installed  |    1| jersey-examples-osgi-http-service-bundle (2.5.0.SNAPSHOT)
    gogo$ start 303

    org.osgi.framework.BundleException: Unresolved constraint in bundle
    org.glassfish.jersey.examples.osgi-http-service.bundle [303]: Unable to resolve 308.0: missing requirement
    [303.0] osgi.wiring.package; (&(osgi.wiring.package=org.glassfish.jersey.servlet)
    (version>=3.0.0.RC2))

    gogo$

In the opposite scenario (example bundle version 3.0.0-M1 and Glassfish Jersey version higher), everything should work fine.

Also, if you build GlassFish from the main trunk sources and use the example from most recent Jersey release, you will most likely be able to run the examples from the latest Jersey release, as Jersey team typically integrates all newly released versions of Jersey immediately into GlassFish.

As a final step, start the bundle:

    gogo$ start 303

Again, the Bundle ID (in our case 303) has to be replaced by the correct one returned from the `install` command.

The example app should now be up and running. You can access it on http://localhost:8080/osgi/jersey-http-service/status . Please see HTTP Service example source code for more details on the example.

## 4.11. Other Environments

### 4.11.1. Oracle Java Cloud Service

As Oracle Public Cloud is based on WebLogic server, the same applies as in the paragraph about WebLogic deployment (see Section 4.9.4.2, “Oracle WebLogic Server”). More on developing applications for Oracle Java Cloud Service can be found in this guide.

Prev |  | Next
Chapter 3. JAX-RS Application, Resources and Sub-Resources | Home | Chapter 5. Client API