| <?xml version="1.0"?> | |
| <!-- | |
| Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. | |
| This program and the accompanying materials are made available under the | |
| terms of the Eclipse Public License v. 2.0, which is available at | |
| http://www.eclipse.org/legal/epl-2.0. | |
| This Source Code may also be made available under the following Secondary | |
| Licenses when the conditions for such availability set forth in the | |
| Eclipse Public License v. 2.0 are satisfied: GNU General Public License, | |
| version 2 with the GNU Classpath Exception, which is available at | |
| https://www.gnu.org/software/classpath/license.html. | |
| SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 | |
| --> | |
| <!DOCTYPE chapter [<!ENTITY % ents SYSTEM "jersey.ent" > %ents; | |
| <!ENTITY jersey.github.osgi.webapp.example.link "<link xlink:href='&jersey.github.examples.uri;/osgi-helloworld-webapp'>WAB Example</link>"> | |
| <!ENTITY jersey.github.osgi.httpservice.example.link "<link xlink:href='&jersey.github.examples.uri;/osgi-http-service'>HTTP Service example</link>"> | |
| ]> | |
| <chapter xmlns="http://docbook.org/ns/docbook" | |
| version="5.0" | |
| xml:lang="en" | |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| xmlns:xlink="http://www.w3.org/1999/xlink" | |
| xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd" | |
| xml:id="deployment"> | |
| <title>Application Deployment and Runtime Environments</title> | |
| <section xml:id="deployment.intro"> | |
| <title>Introduction</title> | |
| <para> | |
| 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. | |
| </para> | |
| <note> | |
| <para> | |
| This chapter is focused on server-side Jersey deployment models. The | |
| <link linkend="client">Jersey client runtime</link> does | |
| not have any specific container requirements and runs in plain Java SE 8 or higher runtime. | |
| </para> | |
| </note> | |
| </section> | |
| <section xml:id="environmenmt.appmodel"> | |
| <title>JAX-RS Application Model</title> | |
| <para> | |
| JAX-RS provides a deployment agnostic abstract class &jaxrs.core.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> | |
| <title>Deployment agnostic application model</title> | |
| <programlisting language="java" linenumbering="numbered">public class MyApplication extends Application { | |
| @Override | |
| public Set<Class<?>> getClasses() { | |
| Set<Class<?>> s = new HashSet<Class<?>>(); | |
| s.add(HelloWorldResource.class); | |
| return s; | |
| } | |
| }</programlisting> | |
| </example> | |
| </para> | |
| <para> | |
| Alternatively it is possible to reuse &jersey.server.ResourceConfig; - Jersey's own implementations | |
| of &lit.jaxrs.core.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. | |
| </para> | |
| <para> | |
| Compared to &lit.jaxrs.core.Application;, the &lit.jersey.server.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 | |
| <literal>getClasses</literal>. For example, the following application class that extends from | |
| &lit.jersey.server.ResourceConfig; scans during deployment for JAX-RS components in packages | |
| <literal>org.foo.rest</literal> and <literal>org.bar.rest</literal>: | |
| <note> | |
| <para> | |
| <emphasis>Package scanning</emphasis> ignores an inheritance and therefore &lit.jaxrs.Path; annotation | |
| on parent classes and interfaces will be ignored. These classes won't be registered as the JAX-RS component | |
| classes. | |
| </para> | |
| </note> | |
| <example> | |
| <title>Reusing Jersey implementation in your custom application model</title> | |
| <programlisting language="java" linenumbering="numbered">public class MyApplication extends ResourceConfig { | |
| public MyApplication() { | |
| packages("org.foo.rest;org.bar.rest"); | |
| } | |
| }</programlisting> | |
| </example> | |
| </para> | |
| <note> | |
| <para> | |
| Later in this chapter, the term <emphasis>&lit.jaxrs.core.Application; subclass</emphasis> is frequently used. | |
| Whenever used, this term refers to the JAX-RS Application Model explained above. | |
| </para> | |
| </note> | |
| </section> | |
| <section xml:id="deployment.autodiscoverable"> | |
| <title>Auto-Discoverable Features</title> | |
| <para> | |
| 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 &jaxrs.core.Feature;s using their | |
| &lit.jaxrs.core.Application; subclass. | |
| Since Jersey 3.1.0 all features which extends &jaxrs.core.Feature; and are listed as SPI of the &lit.jaxrs.core.Feature; | |
| interface are automatically registered (not required to be registered within &lit.jaxrs.core.Application; subclass). | |
| For server site Jersey 3.1.0 also registers SPIs for &lit.jaxrs.container.DynamicFeature; interface. | |
| For a few Jersey provided modules however there is no need to explicitly register their extension | |
| &lit.jaxrs.core.Feature;s as these are discovered and registered in the &jaxrs.core.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: | |
| <itemizedlist> | |
| <listitem> | |
| <para>JSON binding feature from <literal>jersey-media-moxy</literal></para> | |
| </listitem> | |
| <listitem> | |
| <para><literal>jersey-media-json-processing</literal></para> | |
| </listitem> | |
| <listitem> | |
| <para><literal>jersey-bean-validation</literal></para> | |
| </listitem> | |
| </itemizedlist> | |
| </para> | |
| <para> | |
| Besides these modules there are also few features/providers present in <literal>jersey-server</literal> module that | |
| are discovered by this mechanism and their availability is affected by Jersey auto-discovery support configuration | |
| (see <xref linkend="deployment.autodiscovery.config" />), namely: | |
| <itemizedlist> | |
| <listitem> | |
| <para>&jersey.server.WadlFeature; - enables WADL processing.</para> | |
| </listitem> | |
| <listitem> | |
| <para>&jersey.server.UriConnegFilter; - a URI-based content negotiation filter.</para> | |
| </listitem> | |
| </itemizedlist> | |
| Almost all Jersey auto-discovery implementations have <code>AutoDiscoverable.DEFAULT_PRIORITY</code> | |
| <literal>@Priority</literal> set. | |
| </para> | |
| <note> | |
| <para> | |
| Auto discovery functionality is in Jersey supported by implementing an internal | |
| <literal>AutoDiscoverable</literal> 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. | |
| </para> | |
| </note> | |
| <section xml:id="deployment.autodiscovery.config"> | |
| <title>Configuring Feature Auto-discovery Mechanism</title> | |
| <para> | |
| 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: | |
| <itemizedlist> | |
| <title>Common auto discovery properties</title> | |
| <listitem> | |
| <para>&jersey.common.CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE;</para> | |
| <para>When set, disables auto discovery globally on client/server.</para> | |
| </listitem> | |
| <listitem> | |
| <para>&jersey.common.CommonProperties.JSON_PROCESSING_FEATURE_DISABLE;</para> | |
| <para>When set, disables configuration of Json Processing (JSR-353) feature.</para> | |
| </listitem> | |
| <listitem> | |
| <para>&jersey.common.CommonProperties.MOXY_JSON_FEATURE_DISABLE;</para> | |
| <para>When set, disables configuration of MOXy Json feature.</para> | |
| </listitem> | |
| </itemizedlist> | |
| 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 &jersey.client.ClientProperties;/&jersey.server.ServerProperties;). | |
| When set, each of these client/server specific auto-discovery related properties overrides the value of the | |
| related common property. | |
| </para> | |
| <note> | |
| <para> | |
| 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. | |
| </para> | |
| </note> | |
| </section> | |
| </section> | |
| <section xml:id="deployment.feature.dynamicFeature"> | |
| <title>Feature and Dynamic Feature SPI automatic registration</title> | |
| <para> | |
| Since Jersey 3.1.0 there is a new specification requirement to automatically discover and register classes that | |
| implement &jaxrs.core.Feature; and &jaxrs.container.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 <literal>jakarta.ws.rs.loadServices</literal> | |
| (which is new specification property) to be set to false. This is also valid for | |
| &jersey.common.CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE; lookup. | |
| </para> | |
| </section> | |
| <section xml:id="deployment.classpath-scanning"> | |
| <title>Configuring the Classpath Scanning</title> | |
| <para> | |
| 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 <literal>META-INF/services/</literal> 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. | |
| <itemizedlist> | |
| <title>List of SPIs recognized by Jersey</title> | |
| <listitem> | |
| <para>&lit.jaxrs.core.Feature; (server, client) - | |
| Features are being registered similarly to AutoDiscoverable feature. In addition | |
| property jakarta.ws.rs.loadServices is checked before registration. | |
| </para> | |
| </listitem> | |
| <listitem> | |
| <para><literal>AutoDiscoverable</literal> (server, client) - | |
| it means if you disable service loading the AutoDiscoverable feature is automatically disabled too</para> | |
| </listitem> | |
| <listitem> | |
| <para><literal>ForcedAutoDiscoverable</literal> (server, client) - | |
| Jersey always looks for these auto discoverable features even if the service loading is disabled</para> | |
| </listitem> | |
| <listitem> | |
| <para><literal>HeaderDelegateProvider</literal> (server, client)</para> | |
| </listitem> | |
| <listitem> | |
| <para>&lit.jaxrs.container.DynamicFeature; (server) - | |
| Similar to &lit.jaxrs.core.Feature; registration but only for server.</para> | |
| </listitem> | |
| <listitem> | |
| <para><literal>ComponentProvider</literal> (server)</para> | |
| </listitem> | |
| <listitem> | |
| <para><literal>ContainerProvider</literal> (server)</para> | |
| </listitem> | |
| <listitem> | |
| <para><literal>AsyncContextDelegateProvider</literal> (server/Servlet)</para> | |
| </listitem> | |
| </itemizedlist> | |
| <itemizedlist> | |
| <title>List of additional SPIs recognized by Jersey in case the <literal>metainf-services</literal> module is on the classpath</title> | |
| <listitem> | |
| <para><literal>MessageBodyReader</literal> (server, client)</para> | |
| </listitem> | |
| <listitem> | |
| <para><literal>MessageBodyWriter</literal> (server, client)</para> | |
| </listitem> | |
| <listitem> | |
| <para><literal>ExceptionMapper</literal> (server, client)</para> | |
| </listitem> | |
| </itemizedlist> | |
| Since it is possible to configure all SPI implementation classes or instances manually in your | |
| &lit.jaxrs.core.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. | |
| </para> | |
| <para> | |
| The services lookup in Jersey (enabled by default) can be disabled via a dedicated | |
| &jersey.common.CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE; property. | |
| There is a client/server counter-part that only disables the feature on the client or server respectively: | |
| &jersey.client.ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE;/&jersey.server.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. | |
| </para> | |
| <para> | |
| For example, following code snippet disables service provider lookup and manually registers implementations | |
| of different JAX-RS and Jersey provider types | |
| (&jaxrs.container.ContainerRequestFilter;, &jaxrs.core.Feature;, &jersey.server.spi.ComponentProvider; | |
| and &jersey.server.spi.ContainerProvider;): | |
| <example> | |
| <title>Registering SPI implementations using ResourceConfig</title> | |
| <programlisting language="java" linenumbering="numbered">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);</programlisting> | |
| </example> | |
| Similarly, in scenarios where the deployment model requires extending the &lit.jaxrs.core.Application; subclass | |
| (e.g. in all Servlet container deployments), the following code could be used to achieve the same application | |
| configuration: | |
| <example> | |
| <title>Registering SPI implementations using &lit.jersey.server.ResourceConfig; subclass</title> | |
| <programlisting language="java" linenumbering="numbered">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); | |
| } | |
| }</programlisting> | |
| </example> | |
| </para> | |
| </section> | |
| <section xml:id="deployment.javase"> | |
| <title>Java SE Deployment Environments</title> | |
| <section xml:id="deployment.http"> | |
| <title>HTTP servers</title> | |
| <para> | |
| 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. | |
| </para> | |
| <section xml:id="deployment.http.jdk"> | |
| <title>JDK Http Server</title> | |
| <para> | |
| 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 <literal>jersey-container-jdk-http</literal> | |
| container extension module. | |
| Instead of creating the <literal>&jdk6.HttpServer;</literal> instance directly, use the | |
| <literal>createHttpServer()</literal> method of <literal>&jersey.jdkhttp.JdkHttpServerFactory;</literal>, | |
| which creates the <literal>HttpServer</literal> instance configured as a Jersey container and | |
| initialized with the supplied &lit.jaxrs.core.Application; subclass. | |
| </para> | |
| <para> | |
| Creating new Jersey-enabled jdk http server is as easy as: | |
| <example> | |
| <title>Using Jersey with JDK HTTP Server</title> | |
| <programlisting language="java" linenumbering="numbered"> URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build(); | |
| ResourceConfig config = new ResourceConfig(MyResource.class); | |
| HttpServer server = JdkHttpServerFactory.createHttpServer(baseUri, config);</programlisting> | |
| A JDK HTTP Container dependency needs to be added: | |
| <programlisting language="xml"><dependency> | |
| <groupId>org.glassfish.jersey.containers</groupId> | |
| <artifactId>jersey-container-jdk-http</artifactId> | |
| <version>&version;</version> | |
| </dependency></programlisting> | |
| </example> | |
| </para> | |
| </section> | |
| <section xml:id="deployment.http.grizzly"> | |
| <title>Grizzly HTTP Server</title> | |
| <para>&grizzly.link; is a multi-protocol framework built on top of Java &jdk6.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. | |
| </para> | |
| <para> | |
| Grizzly HTTP container supports injection of Grizzly-specific | |
| <literal>org.glassfish.grizzly.http.server.Request</literal> and | |
| <literal>org.glassfish.grizzly.http.server.Response</literal> instances into JAX-RS and Jersey | |
| application resources and providers. However, since Grizzly <literal>Request</literal> is not proxiable, | |
| the injection of Grizzly <literal>Request</literal> into singleton (by default) JAX-RS / Jersey providers | |
| is only possible via <literal>jakarta.inject.Provider</literal> instance. (Grizzly <literal>Response</literal> | |
| does not suffer the same restriction.) | |
| </para> | |
| <example> | |
| <title>Using Jersey with Grizzly HTTP Server</title> | |
| <programlisting language="java" linenumbering="numbered">URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build(); | |
| ResourceConfig config = new ResourceConfig(MyResource.class); | |
| HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, config);</programlisting> | |
| The container extension module dependency to be added is: | |
| <programlisting language="xml"><dependency> | |
| <groupId>org.glassfish.jersey.containers</groupId> | |
| <artifactId>jersey-container-grizzly2-http</artifactId> | |
| <version>&version;</version> | |
| </dependency></programlisting> | |
| </example> | |
| <note> | |
| <para> | |
| Jersey uses Grizzly extensively in the project unit and end-to-end tests via | |
| <link linkend="test-framework">test framework</link>. | |
| </para> | |
| </note> | |
| </section> | |
| <section xml:id="deployment.http.simple"> | |
| <title>Simple server</title> | |
| <para> | |
| <link xlink:href='http://www.simpleframework.org/'>Simple</link> 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 | |
| <literal>jersey-container-simple-http</literal> container extension module. | |
| </para> | |
| <para> | |
| Simple framework HTTP container supports injection of Simple framework-specific | |
| <literal>org.simpleframework.http.Request</literal> and | |
| <literal>org.simpleframework.http.Response</literal> instances into JAX-RS and Jersey | |
| application resources and providers. | |
| </para> | |
| <example> | |
| <title>Using Jersey with the Simple framework</title> | |
| <programlisting language="java" linenumbering="numbered">URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build(); | |
| ResourceConfig config = new ResourceConfig(MyResource.class); | |
| SimpleContainer server = SimpleContainerFactory.create(baseUri, config);</programlisting> | |
| The necessary container extension module dependency in this case is: | |
| <programlisting language="xml"><dependency> | |
| <groupId>org.glassfish.jersey.containers</groupId> | |
| <artifactId>jersey-container-simple-http</artifactId> | |
| <version>&version;</version> | |
| </dependency></programlisting> | |
| </example> | |
| <note> | |
| <para> | |
| Simple framework HTTP container does not support deployment on context paths other than | |
| root path ("<literal>/</literal>"). Non-root context path is ignored during deployment. | |
| </para> | |
| </note> | |
| </section> | |
| <section xml:id="deployment.http.jetty"> | |
| <title>Jetty HTTP Server</title> | |
| <para> | |
| 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 | |
| <xref linkend="deployment.servlet"/> section. We will here only focus on describing how to use | |
| Jetty's HTTP server. | |
| </para> | |
| <para> | |
| Jetty HTTP container supports injection of Jetty-specific | |
| <literal>org.eclipse.jetty.server.Request</literal> and | |
| <literal>org.eclipse.jetty.server.Response</literal> instances into JAX-RS and Jersey | |
| application resources and providers. However, since Jetty HTTP <literal>Request</literal> is not proxiable, | |
| the injection of Jetty <literal>Request</literal> into singleton (by default) JAX-RS / Jersey providers | |
| is only possible via <literal>jakarta.inject.Provider</literal> instance. (Jetty <literal>Response</literal> | |
| does not suffer the same restriction.) | |
| </para> | |
| <example> | |
| <title>Using Jersey with Jetty HTTP Server</title> | |
| <programlisting language="java" linenumbering="numbered">URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build(); | |
| ResourceConfig config = new ResourceConfig(MyResource.class); | |
| Server server = JettyHttpContainerFactory.createServer(baseUri, config);</programlisting> | |
| And, of course, we add the necessary container extension module dependency: | |
| <programlisting language="xml" linenumbering="numbered"><dependency> | |
| <groupId>org.glassfish.jersey.containers</groupId> | |
| <artifactId>jersey-container-jetty-http</artifactId> | |
| <version>&version;</version> | |
| </dependency></programlisting> | |
| </example> | |
| <note> | |
| <para> | |
| Jetty HTTP container does not support deployment on context paths other than | |
| root path ("<literal>/</literal>"). Non-root context path is ignored during deployment. | |
| </para> | |
| </note> | |
| </section> | |
| <section xml:id="deployment.http.netty"> | |
| <title>Netty HTTP Server</title> | |
| <para> | |
| 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. | |
| </para> | |
| <example> | |
| <title>Using Jersey with Netty HTTP Server</title> | |
| <programlisting language="java" linenumbering="numbered">URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build(); | |
| ResourceConfig resourceConfig = new ResourceConfig(HelloWorldResource.class); | |
| Channel server = NettyHttpContainerProvider.createServer(baseUri, resourceConfig, false);</programlisting> | |
| And, of course, we add the necessary container extension module dependency: | |
| <programlisting language="xml" linenumbering="numbered"><dependency> | |
| <groupId>org.glassfish.jersey.containers</groupId> | |
| <artifactId>jersey-container-netty-http</artifactId> | |
| <version>&version;</version> | |
| </dependency></programlisting> | |
| </example> | |
| <note> | |
| <para> | |
| Netty HTTP container does not support deployment on context paths other than | |
| root path ("<literal>/</literal>"). Non-root context path is ignored during deployment. | |
| </para> | |
| </note> | |
| </section> | |
| </section> | |
| <section xml:id="deployment.bootstrap.api"> | |
| <title>Jakarta REST Bootstrap API</title> | |
| <para> | |
| Jakarta REST 3.1 comes with a new API for starting an application in Java SE environment. This | |
| <literal>Bootstrap</literal> API is mainly represented by &lit.jaxrs.SeBootstrap; interface. | |
| The Jakarta REST application is started as follows: | |
| <programlisting language="java">Application application = new MyApplication(); | |
| SeBootstrap.Configuration.Builder configBuilder = SeBootstrap.Configuration.builder(); | |
| CompletionStage<SeBootstrap.Instance> completionStage = SeBootstrap.start(application, configBuilder.build());</programlisting> | |
| </para> | |
| <para> | |
| Later, when the SE application is no longer needed, it can be shutdown as follows: | |
| <programlisting language="java">CompletionStage<SeBootstrap.Instance> completionStage = ... | |
| SeBootstrap.Instance instance = completionStage().get(); | |
| instance.stop();</programlisting> | |
| </para> | |
| <para> | |
| The &lit.jaxrs.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 | |
| &lit.jaxrs.SeBootstrap; is configured as follows: | |
| <programlisting language="java">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");</programlisting> | |
| </para> | |
| <para> | |
| The &lit.jaxrs.SeBootstrap; deployment is backed up by an HTTP server described in | |
| <xref linkend="deployment.http"/>. If multiple Jersey container modules are on the classpath, | |
| the first found is used. | |
| </para> | |
| </section> | |
| <section xml:id="deployment.webserver.spi"> | |
| <title>Jersey WebServer SPI</title> | |
| <para> | |
| Jersey &jersey.server.spi.WebServer; and &jersey.server.spi.WebServerProvider; are SPI interfaces similar to | |
| &jersey.server.spi.ContainerProvider; but they are used for the SE deployment. They serve as a bridge between | |
| Jersey containers and &lit.jaxrs.SeBootstrap; API. | |
| The Jakarta REST application can be started as follows: | |
| <programlisting language="java">Application application = new MyApplication(); | |
| SeBootstrap.Configuration.Builder configBuilder = SeBootstrap.Configuration.builder(); | |
| WebServer webServer = WebServerFactory.createServer(WebServer.class, application, configBuilder.build());</programlisting> | |
| </para> | |
| <para> | |
| Later, when the SE application is no longer needed, it can be shutdown as follows: | |
| <programlisting language="java">WebServer webServer = ... | |
| webServer.stop();</programlisting> | |
| </para> | |
| <para> | |
| &jersey.server.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 &lit.jersey.server.spi.WebServer; by a concrete WebServer subclass, for instance: | |
| <programlisting language="java"> | |
| WebServer webServer = WebServerFactory.createServer(GrizzlyHttpServer.class, application, configBuilder.build());</programlisting> | |
| Another way to choose the &lit.jersey.server.spi.WebServer; implementation is by the | |
| &lit.jersey.server.spi.WebServerProvider; implementation: | |
| <programlisting language="java"> | |
| WebServer webServer = GrizzlyHttpServerProvider.createServer(WebServer.class, application, configBuilder.build());</programlisting> | |
| </para> | |
| <para> | |
| For additional customization of the WebServer settings, see <xref linkend="appendix-properties-webserver"/>. | |
| </para> | |
| </section> | |
| <warning xml:id="ports.warning" xreflabel="Default ports"> | |
| <para> | |
| When the port is set to -1, the default ports are used. | |
| Unlike the default ports used by the <xref linkend="deployment.http"/>, the &lit.jaxrs.SeBootstrap; API and | |
| &lit.jersey.server.spi.WebServer; SPI use default ports 8080 and 8443, respectively. | |
| </para> | |
| <para> | |
| 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. | |
| </para> | |
| <para> | |
| Using the restricted ports can be ensured either by setting directly the port, or by setting | |
| &jersey.server.ServerProperties.WEBSERVER_ALLOW_PRIVILEGED_PORTS; property to true in the | |
| &lit.jaxrs.SeBootstrap.Configuration; | |
| </para> | |
| </warning> | |
| </section> | |
| <section xml:id="deployment.jaxrs.endpoint"> | |
| <title>Creating programmatic JAX-RS endpoint</title> | |
| <para> | |
| JAX-RS specification also defines the ability to programmatically create a JAX-RS application endpoint | |
| (i.e. container) for any instance of a &lit.jaxrs.core.Application; subclass. For example, Jersey supports | |
| creation of <link xlink:href="http://grizzly.java.net/">Grizzly</link> <literal>HttpHandler</literal> instance | |
| as follows: | |
| <programlisting language="java">HttpHandler endpoint = RuntimeDelegate.getInstance() | |
| .createEndpoint(new MyApplication(), HttpHandler.class);</programlisting> | |
| Once the Grizzly <literal>HttpHandler</literal> endpoint is created, it can be used for in-process deployment | |
| to a specific base URL. | |
| </para> | |
| </section> | |
| <section xml:id="deployment.servlet"> | |
| <title>Servlet-based Deployment</title> | |
| <para> | |
| 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. | |
| </para> | |
| <section xml:id="deployment.servlet.2"> | |
| <title>Servlet 2.x way</title> | |
| <para> | |
| 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. | |
| </para> | |
| <para> | |
| Using Servlet 2.x way, you have to explicitly declare the Jersey container Servlet in your Web application's | |
| <literal>web.xml</literal> deployment descriptor file. | |
| <example> | |
| <title>Hooking up Jersey as a Servlet</title> | |
| <programlisting language="xml" linenumbering="numbered"><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></programlisting> | |
| </example> | |
| Alternatively, you can register Jersey container as a <emphasis>filter</emphasis>: | |
| <example> | |
| <title>Hooking up Jersey as a Servlet Filter</title> | |
| <programlisting language="xml" linenumbering="numbered"><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></programlisting> | |
| </example> | |
| </para> | |
| <important> | |
| <para> | |
| 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 <literal>jersey.config.servlet.filter.contextPath</literal> for | |
| <literal>jersey-container-servlet-core</literal>. | |
| Or <literal>jersey-container-servlet</literal> shall be used. | |
| </para> | |
| </important> | |
| <para> | |
| The content of the <literal><init-param></literal> element will vary depending on the way you decide to | |
| configure Jersey resources. | |
| </para> | |
| <section xml:id="deployment.servlet.2.application"> | |
| <title>Custom &lit.jaxrs.core.Application; subclass</title> | |
| <para> | |
| If you extend the &jaxrs.core.Application; class to provide the list of relevant root resource | |
| classes (<literal>getClasses()</literal>) and singletons (<literal>getSingletons()</literal>), | |
| i.e. your JAX-RS application model, you then need to register it in your web application | |
| <literal>web.xml</literal> deployment descriptor using a Servlet or Servlet filter initialization | |
| parameter with a name of <literal>jakarta.ws.rs.Application</literal> [<emphasis>sic</emphasis>] as follows: | |
| <example> | |
| <title> | |
| Configuring Jersey container Servlet or Filter to use custom &lit.jaxrs.core.Application; subclass | |
| </title> | |
| <programlisting language="xml" linenumbering="numbered"><init-param> | |
| <param-name>jakarta.ws.rs.Application</param-name> | |
| <param-value>org.foo.MyApplication</param-value> | |
| </init-param></programlisting> | |
| </example> | |
| Jersey will consider all the classes returned by <literal>getClasses()</literal> and | |
| <literal>getSingletons()</literal> methods of your &lit.jaxrs.core.Application; implementation. | |
| </para> | |
| <note> | |
| <para> | |
| The name of the configuration property as defined by JAX-RS specification is indeed | |
| <literal>jakarta.ws.rs.Application</literal> and not <literal>jakarta.ws.rs.core.Application</literal> | |
| as one might expect. | |
| </para> | |
| </note> | |
| </section> | |
| <section xml:id="deployment.servlet.2.package"> | |
| <title>Jersey package scanning</title> | |
| <para> | |
| 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> | |
| <title>Configuring Jersey container Servlet or Filter to use package scanning</title> | |
| <programlisting language="xml" linenumbering="numbered"><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></programlisting> | |
| </example> | |
| 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 | |
| <literal>jersey.config.server.provider.scanning.recursive</literal> property. | |
| The default value is <literal>true</literal>, i.e. the recursive scanning of sub-packages is enabled. | |
| </para> | |
| </section> | |
| <section xml:id="deployment.servlet.2.classes"> | |
| <title>Selecting concrete resource and provider classes</title> | |
| <para> | |
| 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 &lit.jaxrs.core.Application; subclass. The specific resource and provider | |
| fully-qualified class names can be provided in a comma-separated value of | |
| <literal>jersey.config.server.provider.classnames</literal> initialization parameter. | |
| </para> | |
| <example> | |
| <title>Configuring Jersey container Servlet or Filter to use a list of classes</title> | |
| <programlisting language="xml" linenumbering="numbered"><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></programlisting> | |
| </example> | |
| </section> | |
| <note> | |
| <para> | |
| 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. | |
| </para> | |
| </note> | |
| </section> | |
| <section xml:id="deployment.servlet.5"> | |
| <title>Servlet 5.x Container</title> | |
| <section xml:id="deployment.servlet.5.no.descriptor"> | |
| <title>Descriptor-less deployment</title> | |
| <para> | |
| There are multiple deployment options in the Servlet 5.0 container for a JAX-RS application defined | |
| by implementing a custom &jaxrs.core.Application; subclass. For simple deployments, no | |
| <literal>web.xml</literal> is necessary at all. Instead, an &jaxrs.ApplicationPath; annotation can be used | |
| to annotate the custom &jaxrs.core.Application; subclass and define the base application URI for all | |
| JAX-RS resources configured in the application: | |
| <example> | |
| <title>Deployment of a JAX-RS application using &lit.jaxrs.ApplicationPath; with Servlet 5.0</title> | |
| <programlisting language="java" linenumbering="numbered">@ApplicationPath("resources") | |
| public class MyApplication extends ResourceConfig { | |
| public MyApplication() { | |
| packages("org.foo.rest;org.bar.rest"); | |
| } | |
| }</programlisting> | |
| </example> | |
| </para> | |
| <note> | |
| <para> | |
| There are many other convenience methods in the &lit.jersey.server.ResourceConfig; that can be used | |
| in the constructor of your custom subclass to configure your JAX-RS application, | |
| see &jersey.server.ResourceConfig; API documentation for more details. | |
| </para> | |
| </note> | |
| <para> | |
| In case you are not providing <literal>web.xml</literal> deployment descriptor for your maven-based web | |
| application project, you need to configure your <literal>maven-war-plugin</literal> to ignore the missing | |
| <literal>web.xml</literal> file by setting | |
| <link xlink:href="http://maven.apache.org/plugins/maven-war-plugin/war-mojo.html#failOnMissingWebXml">failOnMissingWebXml</link> | |
| configuration property to &lit.false; in your project <literal>pom.xml</literal> file: | |
| <example> | |
| <title>Configuration of maven-war-plugin to ignore missing <literal>web.xml</literal></title> | |
| <programlisting language="xml" linenumbering="numbered"><plugins> | |
| ... | |
| <plugin> | |
| <groupId>org.apache.maven.plugins</groupId> | |
| <artifactId>maven-war-plugin</artifactId> | |
| <version>2.3</version> | |
| <configuration> | |
| <failOnMissingWebXml>false</failOnMissingWebXml> | |
| </configuration> | |
| </plugin> | |
| ... | |
| </plugins></programlisting> | |
| </example> | |
| </para> | |
| </section> | |
| <section xml:id="deployment.servlet.5.descriptor"> | |
| <title>Deployment using <literal>web.xml</literal> descriptor</title> | |
| <para> | |
| Another Servlet 5.x container deployment model is to declare the JAX-RS application details in the | |
| <literal>web.xml</literal>. | |
| 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 | |
| &jaxrs.core.Application; may be used in the definition of a <literal><servlet-name></literal> | |
| element as part of your application's <literal>web.xml</literal> deployment descriptor. | |
| </para> | |
| <para> | |
| Following example illustrates this approach: | |
| <example> | |
| <title>Deployment of a JAX-RS application using <literal>web.xml</literal> with Servlet 5.0 | |
| </title> | |
| <programlisting language="xml" linenumbering="numbered"><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></programlisting> | |
| </example> | |
| Note that the <literal><servlet-class></literal> element is omitted from the Servlet declaration. | |
| This is a correct declaration utilizing the Servlet 5.0 extension mechanism described in detail in the | |
| <xref linkend="deployment.servlet.5.pluggability"/> section. Also note that | |
| <literal><servlet-mapping></literal> is used in the example to define the base resource URI. | |
| </para> | |
| </section> | |
| <section xml:id="deployment.servlet.5.pluggability"> | |
| <title>Servlet Pluggability Mechanism</title> | |
| <para> | |
| 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 | |
| <literal>web.xml</literal> 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 <literal>web.xml</literal> 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. | |
| </para> | |
| <section xml:id="deployment.servlet.5.pluggability.noapp"> | |
| <title>JAX-RS application without an &lit.jaxrs.core.Application; subclass</title> | |
| If no &lit.jaxrs.core.Application; (or &lit.jersey.server.ResourceConfig;) subclass is present, | |
| Jersey will dynamically add a Jersey container Servlet and set its name to | |
| <literal>jakarta.ws.rs.core.Application</literal>. The web application path will be scanned and all the | |
| root resource classes (the classes annotated with &jaxrs.Path; annotation) as well as any providers that are | |
| annotated with &jaxrs.ext.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 <literal>jakarta.ws.rs.core.Application</literal> Servlet: | |
| <example> | |
| <title> | |
| <literal>web.xml</literal> of a JAX-RS application without an &lit.jaxrs.core.Application; subclass | |
| </title> | |
| <programlisting language="xml" linenumbering="numbered"><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></programlisting> | |
| </example> | |
| </section> | |
| <section xml:id="deployment.servlet.5.pluggability.app"> | |
| <title>JAX-RS application with a custom &lit.jaxrs.core.Application; subclass</title> | |
| <para> | |
| When a custom &lit.jaxrs.core.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. | |
| </para> | |
| <para> | |
| If the <literal>web.xml</literal> contains a Servlet definition, that has an initialization parameter | |
| <literal>jakarta.ws.rs.Application</literal> whose value is the fully qualified name of the | |
| &lit.jaxrs.core.Application; subclass, Jersey does not perform any additional steps in such case. | |
| </para> | |
| <para> | |
| If no such Servlet is defined to handle the custom &lit.jaxrs.core.Application; subclass, Jersey | |
| dynamically adds a Servlet with a fully qualified name equal to the name of the provided | |
| &lit.jaxrs.core.Application; subclass. To define the mapping for the added Servlet, you can either | |
| annotate the custom &lit.jaxrs.core.Application; subclass with an &jaxrs.ApplicationPath; annotation | |
| (Jersey will use the annotation value appended with <literal>/*</literal> to automatically define | |
| the mapping for the Servlet), or specify the mapping for the Servlet in the | |
| <literal>web.xml</literal> descriptor directly. | |
| </para> | |
| <para> | |
| In the following example, let's assume that the JAX-RS application is defined using a custom | |
| &lit.jaxrs.core.Application; subclass named <literal>org.example.MyApplication</literal>. | |
| Then the <literal>web.xml</literal> file could have the following structure: | |
| <example> | |
| <programlisting language="xml" linenumbering="numbered"><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></programlisting> | |
| </example> | |
| </para> | |
| <note> | |
| <para> | |
| If your custom &lit.jaxrs.core.Application; subclass is packaged in the <literal>war</literal>, it defines | |
| which resources will be taken into account. | |
| <itemizedlist> | |
| <listitem> | |
| If both <literal>getClasses()</literal> and <literal>getSingletons()</literal> 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 | |
| <literal>.war</literal> file. | |
| </listitem> | |
| <listitem> | |
| If any of the two mentioned methods - <literal>getClasses()</literal> or | |
| <literal>getSingletons()</literal> returns a non-empty collection, only those classes and/or | |
| singletons will be published in the JAX-RS application. | |
| </listitem> | |
| </itemizedlist> | |
| </para> | |
| </note> | |
| <table pgwide="1" frame='all' xml:id="environment-table-pluggability"> | |
| <title>Servlet 3 Pluggability Overview</title> | |
| <tgroup cols='4' align='left' colsep='1' rowsep='1'> | |
| <thead> | |
| <row> | |
| <entry>Condition</entry> | |
| <entry>Jersey action</entry> | |
| <entry>Servlet Name</entry> | |
| <entry><literal>web.xml</literal></entry> | |
| </row> | |
| </thead> | |
| <tbody> | |
| <row> | |
| <entry>No &lit.jaxrs.core.Application; subclass</entry> | |
| <entry>Adds Servlet</entry> | |
| <entry><literal>jakarta.ws.rs.core.Application</literal></entry> | |
| <entry>Servlet mapping is required</entry> | |
| </row> | |
| <row> | |
| <entry>&lit.jaxrs.core.Application; subclass handled by existing Servlet</entry> | |
| <entry>No action</entry> | |
| <entry>Already defined</entry> | |
| <entry>Not required</entry> | |
| </row> | |
| <row> | |
| <entry>&lit.jaxrs.core.Application; subclass NOT handled by existing Servlet</entry> | |
| <entry>Adds Servlet</entry> | |
| <entry>FQN of the &lit.jaxrs.core.Application; subclass</entry> | |
| <entry> | |
| if no &lit.jaxrs.ApplicationPath; on the &lit.jaxrs.core.Application; | |
| subclass, then Servlet mapping is required | |
| </entry> | |
| </row> | |
| </tbody> | |
| </tgroup> | |
| </table> | |
| </section> | |
| </section> | |
| </section> | |
| <section xml:id="deployment.servlet.containers"> | |
| <title>Jersey Servlet container modules</title> | |
| <para> | |
| Jersey uses its own <literal>&jersey.servlet.ServletContainer;</literal> 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. | |
| </para> | |
| <para> | |
| When deploying to a Servlet container, Jersey application is typically packaged as a <literal>.war</literal> file. | |
| As with any other Servlet application, JAX-RS application classes are packaged in | |
| <literal>WEB-INF/classes</literal> or <literal>WEB-INF/lib</literal> and required application libraries are | |
| located in <literal>WEB-INF/lib</literal>. | |
| For more details, please refer to the Servlet Specification (&servlet5.link;). | |
| </para> | |
| <para> | |
| 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: | |
| <programlisting language="xml"><dependency> | |
| <groupId>org.glassfish.jersey.containers</groupId> | |
| <artifactId>jersey-container-servlet-core</artifactId> | |
| </dependency></programlisting> | |
| To support additional Servlet 5.x deployment modes and asynchronous JAX-RS resource programming model, | |
| an additional Jersey module is required: | |
| <programlisting language="xml"><dependency> | |
| <groupId>org.glassfish.jersey.containers</groupId> | |
| <artifactId>jersey-container-servlet</artifactId> | |
| </dependency></programlisting> | |
| The <literal>jersey-container-servlet</literal> module depends on | |
| <literal>jersey-container-servlet-core</literal> module, therefore when it is used, it is not necessary to | |
| explicitly declare the <literal>jersey-container-servlet-core</literal> dependency. | |
| </para> | |
| <para> | |
| Note that in simple cases, you don't need to provide the deployment descriptor (<literal>web.xml</literal>) | |
| and can use the <literal>@ApplicationPath</literal> annotation, as described in | |
| <xref linkend="deployment.servlet.3.pluggability.noapp"/> section. | |
| </para> | |
| </section> | |
| </section> | |
| <section xml:id="deployment.javaee"> | |
| <title>Jakarta EE Platform</title> | |
| <para> | |
| 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. | |
| </para> | |
| <section xml:id="deployment.javaee.managed"> | |
| <title>Managed Beans</title> | |
| <para> | |
| Jersey supports the use of Jakarta EE Managed beans as root resource classes, providers as well as | |
| &lit.jaxrs.core.Application; subclasses. | |
| </para> | |
| <para> | |
| 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 <literal>getIt()</literal>: | |
| <programlisting language="java" linenumbering="numbered">@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!"; | |
| } | |
| }</programlisting> | |
| </para> | |
| </section> | |
| <section xml:id="deployment.javaee.cdi"> | |
| <title>Context and Dependency Injection (CDI)</title> | |
| <para> | |
| CDI beans can be used as Jersey root resource classes, providers as well as &lit.jaxrs.core.Application; | |
| subclasses. Providers and &lit.jaxrs.core.Application; subclasses have to be singleton or application scoped. | |
| </para> | |
| <para> | |
| 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 | |
| (<literal>MyOtherCdiBean</literal>): | |
| <programlisting language="java" linenumbering="numbered">@Path("/cdibean") | |
| public class CdiBeanResource { | |
| @Inject MyOtherCdiBean bean; // CDI injected bean | |
| @GET | |
| @Produces("text/plain") | |
| public String getIt() { | |
| return bean.getIt(); | |
| } | |
| }</programlisting> | |
| </para> | |
| <para> | |
| 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 <xref linkend="cdi.support"/>. | |
| </para> | |
| </section> | |
| <section xml:id="deployment.javaee.ejb"> | |
| <title>Enterprise Java Beans (EJB)</title> | |
| <para> | |
| Stateless and Singleton Session beans can be used as Jersey root resource classes, providers and/or | |
| &lit.jaxrs.core.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 (<literal>ejb-jar.xml</literal>). 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. | |
| </para> | |
| <para> | |
| Following example consists of a stateless EJB and a local interface used in Jersey: | |
| <programlisting language="java" linenumbering="numbered">@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!"; | |
| } | |
| }</programlisting> | |
| </para> | |
| <note> | |
| <para> | |
| 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. | |
| </para> | |
| </note> | |
| </section> | |
| <section xml:id="deployment.appservers"> | |
| <title>Jakarta EE Servers</title> | |
| <section xml:id="deployment.appservers.glassfish"> | |
| <title>GlassFish Application Server</title> | |
| <para> | |
| As explained in <link linkend="servlet-app-glassfish">2.3.1</link> , you don't need to add any specific | |
| dependencies on GlassFish, Jersey is already packaged within GlassFish. You only need to add the | |
| <literal>provided</literal>-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. | |
| </para> | |
| <para> | |
| Started with version 2.7, Jersey allows injecting Jersey specific types into CDI enabled JAX-RS components | |
| using the <literal>@jakarta.inject.Inject</literal> 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. | |
| </para> | |
| <para> | |
| 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, &jersey.ext.cdi1x.spi.Hk2CustomBoundTypesProvider;, SPI. | |
| Please see the linked javadoc to get detailed information on how to use the SPI in your application. | |
| </para> | |
| </section> | |
| <section xml:id="deployment.appservers.weblogic"> | |
| <title>Oracle WebLogic Server</title> | |
| <para> | |
| 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) | |
| </para> | |
| <para> | |
| 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 <link xlink:href="https://docs.oracle.com/middleware/12213/wls/WLUPG/upgrade_ws.htm#WLUPG331"> | |
| Upgrading a 10.3.x RESTful Web Service (JAX-RS) to 12.2.x</link> | |
| </para> | |
| </section> | |
| <section xml:id="deployment.appservers.other"> | |
| <title>Other Application Servers</title> | |
| <para> | |
| 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. | |
| </para> | |
| <para> | |
| 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.</para> | |
| </section> | |
| </section> | |
| </section> | |
| <section xml:id="deployment.osgi"> | |
| <title>OSGi</title> | |
| <para> | |
| 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 | |
| <link xlink:href='http://www.osgi.org/Download/Release4V42'>OSGi 4.2.0 Download Site</link>. | |
| </para> | |
| <para> | |
| The two supported ways of running an OSGi web application are: | |
| <itemizedlist> | |
| <listitem>WAB (Web Application Bundle)</listitem> | |
| <listitem>HTTP Service</listitem> | |
| </itemizedlist> | |
| WAB is in fact just an OSGified WAR archive. HTTP Service feature allows you to publish Jakarta EE Servlets in | |
| the OSGi runtime. | |
| </para> | |
| <para> | |
| Two examples were added to the Jersey distribution to depict the above mentioned features and show how to use | |
| them with Jersey: | |
| <itemizedlist> | |
| <listitem>&jersey.github.osgi.webapp.example.link;</listitem> | |
| <listitem>&jersey.github.osgi.httpservice.example.link;</listitem> | |
| </itemizedlist> | |
| 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 <link xlink:href='http://ops4j1.jira.com/wiki/display/PAXEXAM3/Pax+Exam'>PAX Exam</link> | |
| framework. Both OSGi examples also include a readme file containing instructions | |
| how to manually run the example applications using &felix.link; framework. | |
| </para> | |
| <para> | |
| The rest of the chapter describes how to run the above mentioned examples on GlassFish 6 application server. | |
| </para> | |
| <section xml:id="osgi.shell"> | |
| <title>Enabling the OSGi shell in Glassfish</title> | |
| <para> | |
| 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 <literal>asadmin</literal> console and creating a Java system property | |
| <literal>glassfish.osgi.start.level.final</literal> and setting its value to <literal>3</literal>: | |
| <example> | |
| Start the admin console: | |
| <programlisting language="bash shell" linenumbering="numbered" continuation="restarts"> | |
| ~/glassfish/bin$ ./asadmin | |
| Use "exit" to exit and "help" for online help. | |
| asadmin></programlisting> | |
| You can check the actual value of the java property (loaded from the configuration file): | |
| <programlisting language="bash shell" linenumbering="numbered" continuation="continues"> | |
| asadmin> list-jvm-options | |
| ... | |
| -Dglassfish.osgi.start.level.final=2 | |
| ...</programlisting> | |
| And change the value by typing: | |
| <programlisting language="bash shell" linenumbering="numbered" continuation="continues"> | |
| asadmin> create-jvm-options --target server -Dglassfish.osgi.start.level.final=3</programlisting> | |
| </example> | |
| </para> | |
| <para> | |
| The second option is to change the value in the <literal>osgi.properties</literal> configuration file: | |
| <programlisting language="bash shell" linenumbering="numbered"> | |
| # 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</programlisting> | |
| You can then execute the Felix shell commands by typing <literal>osgi <felix_command></literal> in | |
| the <literal>asadmin</literal> console. For example: | |
| <programlisting language="bash shell" linenumbering="numbered"> | |
| asadmin> osgi lb | |
| ... list of bundles ...</programlisting> | |
| or launching the shell using <literal>osgi-shell</literal> command in the admin console (the domain must be | |
| started, otherwise the osgi shell won't launch): | |
| <programlisting language="bash shell" linenumbering="numbered"> | |
| asadmin> osgi-shell | |
| Use "exit" to exit and "help" for online help. | |
| gogo$</programlisting> | |
| and execute the osgi commands directly (without the "<literal>osgi</literal>" prefix): | |
| <programlisting language="bash shell" linenumbering="numbered"> | |
| gogo$ lb | |
| ... list of bundles ...</programlisting> | |
| </para> | |
| </section> | |
| <section xml:id="osgi.wab"> | |
| <title>WAB Example</title> | |
| <para> | |
| 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: | |
| <programlisting language="text" linenumbering="numbered">Web-ContextPath: helloworld | |
| Webapp-Context: helloworld | |
| Bundle-ClassPath: WEB-INF/classese</programlisting> | |
| 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 | |
| <link xlink:href='http://wiki.osgi.org/wiki/Category:Manifest_Header'>OSGi Wiki</link>. | |
| </para> | |
| <para> | |
| For more detailed information on the example please see the &jersey.github.osgi.webapp.example.link; source code. This | |
| example does not package into a single <literal>war</literal> file. Instead a <literal>war</literal> and a | |
| set of additional <literal>jar</literal>s is produced during the build. See the next example to see how to deploy OSGi | |
| based Jersey application to GlassFish. | |
| </para> | |
| </section> | |
| <section xml:id="osgi.httpservice"> | |
| <title>HTTP Service Example</title> | |
| <note> | |
| <para> | |
| When deploying an OSGi HTTP Service example to GlassFish, please make sure the OSGi HTTP Service bundle is | |
| installed on your GlassFish instance. | |
| </para> | |
| </note> | |
| <para> | |
| 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): | |
| </para> | |
| <para> | |
| 1) Build (optional) | |
| <programlisting language="bash" linenumbering="numbered"> | |
| examples$ cd osgi-http-service/bundle | |
| bundle$ mvn clean package</programlisting> | |
| You can also get the binary readily compiled from | |
| <link xlink:href='&maven.java.net.releases.link;org/glassfish/jersey/examples/osgi-http-service/bundle/&version;'>Java.net Maven Repository</link>. | |
| </para> | |
| <para> | |
| 2) Install into OSGi runtime: | |
| <programlisting language="bash shell" linenumbering="numbered"> | |
| gogo$ install file:///path/to/file/bundle.jar | |
| Bundle ID: 303</programlisting> | |
| or install it directly from the maven repository: | |
| <programlisting language="bash shell" linenumbering="numbered"> | |
| gogo$ install https://repo1.maven.org/maven2/org/glassfish/jersey/examples/osgi-http-service/bundle/<version>/bundle-<version>.jar | |
| Bundle ID: 303</programlisting> | |
| </para> | |
| <para> | |
| Make sure to replace <literal><version></literal> 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: | |
| <programlisting language="bash" linenumbering="numbered">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$</programlisting> | |
| In the opposite scenario (example bundle version 3.0.0-M1 and Glassfish Jersey version higher), everything should | |
| work fine. | |
| </para> | |
| <para> | |
| 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. | |
| </para> | |
| <para> | |
| As a final step, start the bundle: | |
| <programlisting language="bash" linenumbering="numbered">gogo$ start 303</programlisting> | |
| Again, the Bundle ID (in our case 303) has to be replaced by the correct one returned from the | |
| <literal>install</literal> command. | |
| </para> | |
| <para> | |
| The example app should now be up and running. You can access it on | |
| <link xlink:href='http://localhost:8080/osgi/jersey-http-service/status'> | |
| http://localhost:8080/osgi/jersey-http-service/status | |
| </link>. Please see &jersey.github.osgi.httpservice.example.link; source code for more details on the example. | |
| </para> | |
| </section> | |
| </section> | |
| <section xml:id="deployment.other"> | |
| <title>Other Environments</title> | |
| <section xml:id="deployment.other.cloud"> | |
| <title>Oracle Java Cloud Service</title> | |
| <para> | |
| As Oracle Public Cloud is based on WebLogic server, the same applies as in the paragraph about WebLogic | |
| deployment (see <xref linkend="deployment.appservers.weblogic" />). More on developing applications for | |
| Oracle Java Cloud Service can be found in this &cloud.guide;. | |
| </para> | |
| </section> | |
| </section> | |
| </chapter> |