Table of Contents
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.
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.
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
:
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"); } }
Later in this chapter, the term Application
subclass is frequently used.
Whenever used, this term refers to the JAX-RS Application Model explained above.
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.
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.
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.
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.
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.
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
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)
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); } }
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.
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.0.17</version> </dependency>
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.0.17</version> </dependency>
Jersey uses Grizzly extensively in the project unit and end-to-end tests via test framework.
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.0.17</version> </dependency>
Simple framework HTTP container does not support deployment on context paths other than
root path ("/
"). Non-root context path is ignored during deployment.
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.7, “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.0.17</version> </dependency>
Jetty HTTP container does not support deployment on context paths other than
root path ("/
"). Non-root context path is ignored during deployment.
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.0.17</version> </dependency>
Netty HTTP container does not support deployment on context paths other than
root path ("/
"). Non-root context path is ignored during deployment.
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.
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.
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>
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.
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.
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.
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.
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>
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.
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"); } }
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>
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.7.2.3, “Servlet Pluggability Mechanism” section. Also note that
<servlet-mapping>
is used in the example to define the base resource URI.
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.
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>
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>
If your custom Application
subclass is packaged in the war
, it defines
which resources will be taken into account.
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.
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
|
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.
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.
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!"; } }
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.
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!"; } }
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.
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.
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
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.
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 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:
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.
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.
~/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 ...
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.
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.
As Oracle Public Cloud is based on WebLogic server, the same applies as in the paragraph about WebLogic deployment (see Section 4.8.4.2, “Oracle WebLogic Server”). More on developing applications for Oracle Java Cloud Service can be found in this guide.