Table of Contents
Following experimental APIs have been promoted to become part of public Jersey API:
Jersey client-side HttpAuthenticationFeature API.
Jersey server-side DestroyListener (formerly
ExtendedMonitoringStatisticsListener
), which has been slightly refactored and
is now a separate interface (e.g. not extending MonitoringStatisticsListener
),
hence providing better compatibility with lambdas.
These APIs are now part of the official public Jersey 2.x API.
Because of a bug fix for issue
JERSEY-2602, we re-generate WADL
classes from wadl.xsd
to make sure the getters for boolean properties starts with
is
instead of get
as in Jersey 1 and Jersey <= 2.6.
For performance purposes a new server property ServerProperties.MONITORING_ENABLED
has been introduced. It is possible to enable just basic almost static monitoring information using the
property. It allows to inject ApplicationInfo object,
renamed original class org.glassfish.jersey.server.monitoring.ApplicationStatistics
.
And MonitoringStatistics no more
have a reference to ApplicationStatistics
, method
getApplicationStatistics()
has been removed.
Several experimental Jersey APIs have matured enough and as such we have decided to promote them from Beta status, namely:
Jersey client-side ConnectorProvider SPI.
Jersey server-side ResponseErrorMapper SPI.
These APIs are now part of the official public Jersey 2.x API.
Jersey is now preventing message body providers (MBR, MBW) from closing given input/output stream. With this change Jersey is enforcing the JavaDoc statements present in message body providers.
We have reintroduced support for JSON processing via Jackson 1.x JSON provider (1.9.11). In order to use
Jackson 1 in your application you need to add jersey-media-json-jackson1
module (+ it's
dependencies) to your class-path and register Jackson1Feature
in your application (server
or client).
Client-side providers (such asClientRequestFilter
s) implementing the new
org.glassfish.jersey.client.ClientLifecycleListener
interface will be notified when
various lifecycle events occur. Currently client runtime initialization triggers the
onInit()
method and client closing triggers onClose()
method.
Such providers implementing the ClientLifecycleListener
can be registered in a common
way, e.g. into a JerseyClient
or JerseyWebTarget
instance, or into a
(potentially) auto discoverable feature context.
Gerard updated the Declarative Linking extension module which has been ported to Jersey 2 in version 2.6. You can read more about what Declarative Linking does and what it's capable of in the following blog posts:
Our media module that supports working with JSON via Jackson library has been updated to use Jackson 2.x (2.3.2).
All samples and tests have been rewritten to use Jackson 2 as well. In order to use Jackson 2 in your application
you need to add jersey-media-json-jackson (+ it's Jackson dependencies) to your class-path and register
JacksonFeature
in your application.
We dropped automatic registration of message body providers (MessageBodyWriter, MessageBodyReader) and exception
mappers via META-INF/services mechanism. This functionality can be restored by adding jersey-metainf-services
module to the class-path of your application.
Note: This change may affect 3rd party libraries (e.g. Jackson 2.x) in a way their provider would not be
registered in an JAX-RS app. You need to either register them manually or use mentioned
jersey-metainf-services
module.
Jersey Test Framework now supports TestNG to run the tests (in addition to the JUnit, which is supported by default). You can now run the tests in parallel using either JUnit or TestNG. See chapters dedicated to TestNG and parallel testing for more information: Section 23.3, “Running TestNG Tests” and Section 23.5, “Parallel Testing with Jersey Test Framework”.
Some of the feature specific configuration properties (disable WADL, disable BV, disable JSON-Processing,
enable Monitoring), and their server/client counterparts, are no longer affected by a value of properties
CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE
or
CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE
. The specific properties have to
be used to change default behaviour of mentioned features (e.g.
ServerProperties.WADL_FEATURE_DISABLE
).
Automatic registration of MessageBodyWriter
, MessageBodyReaders
and ExceptionMappers
via META-INF/services
mechanism has been
removed. Disabling the automatic registration of providers via META-INF/services
may affect 3rd party libraries (i.e. Jackson 2.x) that are using this mechanism to register it's
providers. In order to restore this functionality the org.glassfish.jersey.ext:jersey-metainf-services
has to be added on the classpath. Otherwise such providers has to be registered manually.
The Jackson JSON Jersey module has been updated to use Jackson 2.x instead of Jackson 1.x. This means that all the code that has been using Jackson 1.x for JSON (de)serialization has to be migrated to Jackson 2.x.
Because of a bug fix for issue
JERSEY-2458, there has been
a slight change in the behavior of UriInfo getPath
and
getPathSegments
methods. The getPath
methods no longer return
a path prefixed with a slash ('/'
), instead they now correctly return a request
path relative to the base request URI. Also, the UriInfo
now correctly handles requests which URI contains empty path segments
(e.g. http://localhost///a/b//c
). These empty path segments are now correctly
included in the lists returned by the UriInfo.getPathSegments
methods.
SseFeature now gets automatically discovered and enabled if the SSE module is present
on the class path. This behavior can be suppressed by setting DISABLE_SSE
property to true
. The behavior can also be selectively suppressed in either
client or server runtime by setting the DISABLE_SSE_CLIENT or
DISABLE_SSE_SERVER property respectively.
Deprecated getDestroyTime
method has been removed from
org.glassfish.jersey.server.monitoring.ApplicationStatistics
.
To get the application shutdown information,
a ContainerLifecycleListener should be registered and its
onShutdown
method implemented to listen to and process the application
shutdown event.
Method triggerEvent(RequestEvent.Type)
has been removed from the public
ContainerRequest API. This method has never been intended for public,
application-level use.
In Jersey 2.7 and earlier it was (under certain conditions) possible to supply custom
TestContainerFactory as part of the tested JAX-RS / Jersey application.
This factory would be picked and used by JerseyTest to instantiate
TestContainer that will host the tested application. This feature was
unreliable and redundant. As such, support for the feature has been removed. To specify a custom
TestContainerFactory
to be used by your JerseyTest
subclass, please override the JerseyTest.getTestContainerFactory
method instead.
Overriding getTestContainerFactory
now remains the only reliable way of specifying
custom TestContainerFactory
implementation to be used in your tests.
Protected method setTestContainerFactory
has been removed from the
JerseyTest
API as calling the method had no effect on the
TestContainerFactory
instance used by the JerseyTest
subclass.
Protected method getClient
has been removed from the JerseyTest
API. To configure test client instances, please override the configureClient
method instead.
Utility methods JerseyTest
that provide access to pre-configured
Client and WebTarget instances (client()
,
target(...)
) have been made final to prevent overriding in subclasses
and thus ensure consistency of the jersey test framework functionality.
JerseyTest
constructor
JerseyTest(Class<? extends Application>)
has been made deprecated
and will be removed in the subsequent Jersey release.
It was previously possible to pass in a custom ContainerProvider that was supposed to deploy and run the application as one of the JAX-RS / Jersey application providers. This ability has been removed without any substitute as the concept was fundamentally flawed. Typical use cases should not be affected by this change.
Factory methods createHttpServer
which take Jersey
ApplicationHandler as one of the input parameters have been removed from the
Jersey container factory API as inherently broken. This impacts
GrizzlyHttpServerFactory, JdkHttpServerFactory,
JettyHttpContainerFactory and SimpleContainerFactory implementations.
The methods that take ResourceConfig as input parameter should be used instead.
Typical use cases should not be affected by this change.
Method registerAdditionalBinders
on ApplicationHandler
has been removed from the public API. Please use the specific ApplicationHandler
constructor that accepts custom HK2 binders instead.
Several configuration properties were renamed, especially those having client and server versions
along with the common version in CommonProperties
. Please see following table
for complete reference:
Table 25.1. List of changed configuration properties:
Constant | Old value (Jersey 2.7 and before) | New value (Jersey 2.8+) |
---|---|---|
ClientProperties.FEATURE_AUTO_DISCOVERY_DISABLE | jersey.config.disableAutoDiscovery.client | jersey.config.client.disableAutoDiscovery |
ServerProperties.FEATURE_AUTO_DISCOVERY_DISABLE | jersey.config.disableAutoDiscovery.server | jersey.config.server.disableAutoDiscovery |
ClientProperties.JSON_PROCESSING_FEATURE_DISABLE | jersey.config.disableJsonProcessing.client | jersey.config.client.disableJsonProcessing |
ServerProperties.JSON_PROCESSING_FEATURE_DISABLE | jersey.config.disableJsonProcessing.server | jersey.config.server.disableJsonProcessing |
ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE | jersey.config.disableMetainfServicesLookup.client | jersey.config.client.disableMetainfServicesLookup |
ServerProperties.METAINF_SERVICES_LOOKUP_DISABLE | jersey.config.disableMetainfServicesLookup.server | jersey.config.server.disableMetainfServicesLookup |
ClientProperties.MOXY_JSON_FEATURE_DISABLE | jersey.config.disableMoxyJson.client | jersey.config.client.disableMoxyJson |
ServerProperties.MOXY_JSON_FEATURE_DISABLE | jersey.config.disableMoxyJson.server | jersey.config.server.disableMoxyJson |
ClientProperties.OUTBOUND_CONTENT_LENGTH_BUFFER | jersey.config.contentLength.buffer.client | jersey.config.client.contentLength.buffer |
ServerProperties.OUTBOUND_CONTENT_LENGTH_BUFFER | jersey.config.contentLength.buffer.server | jersey.config.server.contentLength.buffer |
ServerProperties.TRACING | jersey.config.server.tracing | jersey.config.server.tracing.type |
The old names are still working for now, but are deprecated. There is a fallback mechanism
implemented while reading the property and each get, that resolves the value from the old-named
property, will log a CONFIG
level warning.
Until version 2.6, Jersey was compiled with Java SE 6. This has changes in Jersey 2.7.
Now almost all Jersey components are compiled with Java SE 7 target. It means, that you will need at least Java
SE 7 to be able to compile and run your application that is using latest Jersey.
Only core-common
and core-client
modules are still compiled with Java class
version runnable with Java SE 6.
MVC support: method writeTo
of TemplateProcessor
was modified by adding an argument MultivaluedMap<String, Object> httpHeaders
.
This is an incompatible change (the method was modified directly in the interface). All
Jersey provided MVC implementation were adjusted but if you have your own MVC implementation
then you need to modify the method signature of the implementation.
A minor JAX-RS incompatibility issue has been recently discovered and reported
(see JERSEY-2387). As part of the
fix, minor breaking changes related to URI resolving and creation have been introduced in the
behavior of UriBuilder, Link.Builder and WebTarget classes.
It is no longer possible to successfully build a new URI
instance from a
UriBuilder
that contains unresolved template parameters.
An IllegalArgumentException
will be thrown in such case, as mandated by
JAX-RS API javadoc. Similarly, it is not possible to successfully create a Link
instance from a URI template with unresolved template parameters.
Also, it is not possible to successfully send a request on a WebTarget
that
represents a URI template that does not have all the template parameters properly resolved.
Any attempt to do so will fail with an exception. Note that this also applies to any managed clients
injected into JAX-RS server-side components using Uri annotation.
In Jersey 2.6 and earlier, producing a URI from an incompletely resolved URI template would succeed
and all unresolved template parameter locations would be encoded without change into the resulting
URI, for example "/path/{param}"
would be implicitly encoded as
"/path/%7Bparam%7D"
. While we do not expect our users to depend on this
functionality, if the former behavior is desired for some reason,
UriComponent.encodeTemplateNames
method can be used instead:
URI.create(UriComponent.encodeTemplateNames(UriBuilder.fromUri("/path/{param}").toTemplate()));
or simply
URI.create(UriComponent.encodeTemplateNames("/path/{param}"));
Jersey no longer depend directly on Guava and ASM artifacts which means that users are free to use their own versions of mentioned libraries.
New bundle has been created for Guava (bundles/repackaged/jersey-guava
), with Maven coordinates:
org.glassfish.jersey.bundles.repackaged:jersey-guava
(Repackaged) ASM is now part of Jersey Server. Jersey currently uses ASM 5 for package-scanning capabilities.
Following APIs were deprecated:
org.glassfish.jersey.message.internal.HttpDateFormat
- method
getPreferedDateFormat()
has been marked as deprecated due to typo in the name. New
method getPreferredDateFormat()
should be used instead.
Following, already deprecated, APIs were removed:
org.glassfish.jersey.client.filter.HttpBasicAuthFilter
and org.glassfish.jersey.client.filter.HttpDigestAuthFilter
(use HttpAuthenticationFeature instead)
org.glassfish.jersey.apache.connector.ApacheClientProperties.HTTP_PARAMS
(use org.glassfish.jersey.apache.connector.ApacheClientProperties#REQUEST_CONFIG
instead),
org.glassfish.jersey.apache.connector.ApacheClientProperties.PROXY_URI
,
org.glassfish.jersey.apache.connector.ApacheClientProperties.PROXY_USERNAME
,
org.glassfish.jersey.apache.connector.ApacheClientProperties.PROXY_PASSWORD
(use corresponding ClientProperties instead.
org.glassfish.jersey.server.validation.ValidationConfig.setMessageInterpolator
org.glassfish.jersey.server.validation.ValidationConfig.setTraversableResolver
org.glassfish.jersey.server.validation.ValidationConfig.setConstraintValidatorFactory
org.glassfish.jersey.server.validation.ValidationConfig.setParameterNameProvider
(use corresponding methods of the same class without "set"
prefix in the method names).
org.glassfish.jersey.server.mvc.MvcProperties
(use properties of org.glassfish.jersey.server.mvc.MvcFeature
instead).
MVC does not allow to specify the resolving class. Resolving class is used to create a path of the template. Changes are:
Annotation attribute Class<?> org.glassfish.jersey.server.mvc.Template.resolvingClass()
(the attribute was obsolete and therefore removed. Resolving class now always the resource
class in which the MVC resource method is defined).
resolvingClass
was removed from Viewable. The constructor
no longer accepts this argument and there is no getter for this field.
org.glassfish.jersey.server.mvc.freemarker.FreemarkerProperties
(use
FreemarkerMvcFeature instead)
org.glassfish.jersey.server.mvc.jsp.JspProperties
(use JspMvcFeature instead)
org.glassfish.jersey.server.model.RuntimeResource.getFirstParentResource()
(use Resource.getParent() instead).
WADL is by default displayed in the simplified form. It does not contain supporting resources
like OPTIONS methods or /application.wadl
itself. In order to get the
full WADL use query param detail=true
. For example make a GET request
to http://localhost:8080/application.wadl?detail=true
.
WADL is by default displayed in the simplified form. It does not contain supporting resources
like OPTIONS methods or /application.wadl
itself. In order to get the
full WADL use query param detail=true
. For example make a GET request
to http://localhost:8080/application.wadl?detail=true
.
Client chunked encoding configuration behaviour has changed:
Jersey client uses chunked encoding (streaming) for serialization of the entity as a default option.
Before Jersey 2.5 release entity buffering has been used by default. The size of the chunk can still
be controlled by ClientProperties.CHUNKED_ENCODING_SIZE property, this property
however no longer enforces the use of chunked encoding. To control request entity buffering and
chunked transfer coding selection, please utilize use the new
ClientProperties.REQUEST_ENTITY_PROCESSING property. The behaviour of the property
is however not unified across the available Connector implementations and depends
on the connector implementation configured for the Client instance.
Default connector produced by HttpUrlConnectorProvider still uses
buffering as default options due to bugs in HttpURLConnection
. On the other hand,
Jetty HTTP Client based connectors produced by JettyConnectorProvider do not support
chunked encoding at all.
Please note that this is not a newly introduced limitation - it's merely an official acknowledgement of the fact that different connectors have different capabilities and limitations - something that has always been part of the individual connector implementations, it just was not publicly acknowledged.
New ConnectorProvider SPI has been introduced to decouple Connector
instantiation from Client instance boot-strapping. As such, the
connector(Connector)
method has been removed from ClientConfig
API. It has been replaced with a newly introduced
connectorProvider(ConnectorProvider)
method.
org.glassfish.jersey.client.HttpUrlConnector
has been removed from the public API.
HttpUrlConnectorProvider should be used to produce HttpURLConnection
connector instances instead.
ClientProperties.HTTP_URL_CONNECTION_SET_METHOD_WORKAROUND
property has been moved to the new HttpUrlConnectorProvider
has been introduced in Jersey 2.4) has been moved to the new HttpUrlConnectorProvider
class as this property is specific to the connector instances created by
HttpUrlConnectorProvider
only. The property has been also renamed to
HttpUrlConnector.SET_METHOD_WORKAROUND. The name of the property
remains the same - jersey.config.client.httpUrlConnection.setMethodWorkaround
.
ClientProperties.HTTP_URL_CONNECTOR_FIX_LENGTH_STREAMING
property (that
class as this property is specific to the connector instances created by
HttpUrlConnectorProvider
only. The property has been also renamed to
HttpUrlConnectorProvider.USE_FIXED_LENGTH_STREAMING and the new property name
is jersey.config.client.httpUrlConnector.useFixedLengthStreaming
.
org.glassfish.jersey.grizzly.connector.GrizzlyConnector
has been removed from the public
API. GrizzlyConnectorProvider should be used to produce Grizzly Asynchronous HTTP Client
connector instances instead.
Public constructor has been removed from the ApacheConnector API. ApacheConnectorProvider should be used to provide Apache HTTP Client connector instances instead.
Public constructor has been removed from the JettyConnector API. JettyConnectorProvider should be used to provide Jetty HTTP Client connector instances instead.
Renamed property CACHING_TEMPLATES_ENABLED
in MustacheMvcFeature
from jersey.config.server.mvc.caching.mustache.enabled
to
jersey.config.server.mvc.caching.mustache
.
Authentication filters org.glassfish.jersey.client.filter.HttpBasicAuthFilter
and org.glassfish.jersey.client.filter.HttpDigestAuthFilter
were deprecated and replaced by HttpAuthenticationFeature.
The ContainerLifecycleListener invokes event onStartup
and onShutdown
also when application is being started or stopped because of
application redeploy. The interface was marked as a Beta now.
The monitoring statistics method ApplicationStatistics.getDestroyTime()
is deprecated and returns always null. Use ContainerLifecycleListener to
listen on application destroy and get the destroy time.
org.glassfish.jersey.spi.ResponseExecutorsProvider
contract has been completely
removed from the Jersey SPI as it was inconsistently used by Jersey runtime and we did not find
a suitable use case where a custom response executor would make sense. While we have no indication
that the removed SPI is used in the Jersey community, please do not hesitate to contact us in case
you think that you have a valid use case where the use of a custom response executor makes sense.
org.glassfish.jersey.spi.RequestsExecutorsProvider
contract has been renamed to
RequestExecutorProvider. It has been also extended with an additional
releaseRequestingExecutor
method to address executor shutdown handling issues
reported in JERSEY-2205. As such,
any custom implementation of the SPI is now required to implement the new method.
The unsupported ClientProperties.BUFFER_RESPONSE_ENTITY_ON_EXCEPTION
property,
with value of jersey.config.client.bufferResponseEntityOnException
, has been
removed from the API. Since Jersey 2.4 where
JERSEY-2157
issue has been fixed, Jersey client runtime automatically buffers error response entities.
This behavior is automatic and there is no need to set any property.
All deprecated SSE InboundEvent getData(...)
methods have been removed
from the API. Use the new readData(...)
methods have been introduced instead in
Jersey 2.3 for consistency with other parts of client-side JAX-RS API.
Access to the raw SSE event data content is provided via a InboundEvent
's
byte[] getRawData()
method that has been too introduced in Jersey 2.3.
All EJB and CDI integration classes have been moved into internal Jersey packages, to clearly state the integration code should not be used as a public API.
All existing SSE InboundEvent getData(...)
methods have been made
deprecated and new readData(...)
methods have been introduced instead for consistency
with other parts of client-side JAX-RS API. The deprecated getData(...)
methods will
be removed in Jersey 2.4. A new SSE InboundEvent byte[] getRawData()
method
has been introduced to provide access to the raw SSE event data content.
Generic Broadcaster methods for adding/removing BroadcasterListener
registrations have been renamed from addBroadcasterListener/removeBroadcasterListener
to simply add/remove
.
Generic Broadcaster (and transitively, SseBroadcaster)
add/remove
methods - that are responsible for
adding/removing BroadcasterListener and ChunkedOutput
(or EventOutput) registrations - no longer try to avoid duplicate registrations by comparing
hash code of the added/removed instance with the hash codes of already registered instances. This behavior
has been identified as a potential source of hard to discover bugs and was removed as such. The issue with
the former behavior was that hash codes as integer values provide only a very limited value space that
could lead to false-positive duplicate registration rejections, especially with larger number of
simultaneously connected SSE clients (represented by ChunkedOutput
or
EventOutput
broadcaster registrations). Consequently, users who rely on the old registration
behavior in their application code need to adapt the code to the revised behavior of
Broadcaster
add/remove
methods.
This chapter is a migration guide for people switching from Jersey 1.x. Since many of the Jersey 1.x features became part of JAX-RS 2.0 standard which caused changes in the package names, we decided it is a good time to do a more significant incompatible refactoring, which will allow us to introduce some more interesting new features in the future. As the result, there are many incompatibilities between Jersey 1.x and Jersey 2.0. This chapter summarizes how to migrate the concepts found in Jersey 1.x to Jersey/JAX-RS 2.0 concepts.
Jersey 1.x contains number of proprietary server APIs. This section covers migration of application code relying on those APIs.
Jersey 1.x have its own internal dependency injection framework which handles injecting various parameters into field or methods. It also provides a way how to register custom injection provider in Singleton or PerRequest scopes. Jersey 2.x uses HK2 as dependency injection framework and users are also able to register custom classes or instances to be injected in various scopes.
Main difference in Jersey 2.x is that you don't need to create special classes or providers for this task; everything should be achievable using HK2 API. Custom injectables can be registered at ResourceConfig level by adding new HK2 Module or by dynamically adding binding almost anywhere using injected HK2 Services instance.
Jersey 1.x Singleton:
ResourceConfig resourceConfig = new DefaultResourceConfig(); resourceConfig.getSingletons().add( new SingletonTypeInjectableProvider<Context, SingletonType>( SingletonType.class, new SingletonType()) {});
Jersey 1.x PerRequest:
ResourceConfig resourceConfig = new DefaultResourceConfig(); resourceConfig.getSingletons().add( new PerRequestTypeInjectableProvider<Context, PerRequestType>() { @Override public Injectable<PerRequestType> getInjectable(ComponentContext ic, Context context) { //... } });
Jersey 2.0 HK2 Module:
public static class MyBinder extends AbstractBinder { @Override protected void configure() { // request scope binding bind(MyInjectablePerRequest.class).to(MyInjectablePerRequest.class).in(RequestScoped.class); // singleton binding bind(MyInjectableSingleton.class).in(Singleton.class); // singleton instance binding bind(new MyInjectableSingleton()).to(MyInjectableSingleton.class); } } // register module to ResourceConfig (can be done also in constructor) ResourceConfig rc = new ResourceConfig(); rc.addClasses(/* ... */); rc.addBinders(new MyBinder());
Jersey 2.0 dynamic binding:
public static class MyApplication extends Application { @Inject public MyApplication(ServiceLocator serviceLocator) { System.out.println("Registering injectables..."); DynamicConfiguration dc = Injections.getConfiguration(serviceLocator); // request scope binding Injections.addBinding( Injections.newBinder(MyInjectablePerRequest.class).to(MyInjectablePerRequest.class).in(RequestScoped.class), dc); // singleton binding Injections.addBinding( Injections.newBinder(MyInjectableSingleton.class) .to(MyInjectableSingleton.class) .in(Singleton.class), dc); // singleton instance binding Injections.addBinding( Injections.newBinder(new MyInjectableSingleton()) .to(MyInjectableSingleton.class), dc); // request scope binding with specified custom annotation Injections.addBinding( Injections.newBinder(MyInjectablePerRequest.class) .to(MyInjectablePerRequest.class) .qualifiedBy(new MyAnnotationImpl()) .in(RequestScoped.class), dc); // commits changes dc.commit(); } @Override public Set<Class<?>> getClasses() { return ... }}
In Jersey 1, the reload functionality is based on two interfaces:
Containers, which support the reload functionality implement the ContainerListener
interface, so that once you get access to the actual container instance, you could call it's
onReload
method and get the container re-load the config. The second interface helps you to
obtain the actual container instance reference. An example on how things are wired together follows.
Example 25.1. Jersey 1 reloader implementation
public class Reloader implements ContainerNotifier { List<ContainerListener> ls; public Reloader() { ls = new ArrayList<ContainerListener>(); } public void addListener(ContainerListener l) { ls.add(l); } public void reload() { for (ContainerListener l : ls) { l.onReload(); } } }
Example 25.2. Jersey 1 reloader registration
Reloader reloader = new Reloader(); resourceConfig.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_NOTIFIER, reloader);
In Jersey 2, two interfaces are involved again, but these have been re-designed.
The Container
interface introduces two reload
methods, which you can call
to get the application re-loaded. One of these methods allows to pass in a new ResourceConfig
instance.
You can register your implementation of ContainerLifecycleListener
the same way as any
other provider (i.e. either by annotating it by @Provider annotation or adding it to the
Jersey ResourceConfig directly either using the class (using
ResourceConfig.addClasses()
) or registering a particular instance using
ResourceConfig.addSingletons()
method.
An example on how things work in Jersey 2 follows.
Example 25.3. Jersey 2 reloader implementation
public class Reloader implements ContainerLifecycleListener { Container container; public void reload(ResourceConfig newConfig) { container.reload(newConfig); } public void reload() { container.reload(); } @Override public void onStartup(Container container) { this.container = container; } @Override public void onReload(Container container) { // ignore or do whatever you want after reload has been done } @Override public void onShutdown(Container container) { // ignore or do something after the container has been shutdown } }
Example 25.4. Jersey 2 reloader registration
Reloader reloader = new Reloader(); resourceConfig.addSingletons(reloader);
JAX-RS 2.0 defines new order of MessageBodyWorkers - whole set is sorted by declaration distance,
media type and source (custom providers having higher priority than default ones provided by Jersey).
JAX-RS 1.x ordering can still be forced by setting parameter
MessageProperties.LEGACY_WORKERS_ORDERING
("jersey.config.workers.legacyOrdering"
) to true
in ResourceConfig
or ClientConfig
properties.
JAX-RS 2.0 provides functionality that is equivalent to the Jersey 1.x proprietary client API. Here is a rough mapping between the Jersey 1.x and JAX-RS 2.0 Client API classes:
Table 25.2. Mapping of Jersey 1.x to JAX-RS 2.0 client classes
Jersey 1.x Class | JAX-RS 2.0 Class | Notes |
---|---|---|
com.sun.jersey.api.client.Client | ClientBuilder | For the static factory methods and constructors. |
Client | For the instance methods. | |
com.sun.jersey.api.client.WebResource | WebTarget | |
com.sun.jersey.api.client.AsyncWebResource | WebTarget | You can access async versions of the async methods by calling
WebTarget.request().async()
|
The following sub-sections show code examples.
Jersey 1.x way:
Client client = Client.create(); WebResource webResource = client.resource(restURL).path("myresource/{param}"); String result = webResource.pathParam("param", "value").get(String.class);
JAX-RS 2.0 way:
Client client = ClientBuilder.newClient(); WebTarget target = client.target(restURL).path("myresource/{param}"); String result = target.pathParam("param", "value").get(String.class);
Jersey 1.x way:
Client client = Client.create(); WebResource webResource = client.resource(restURL); webResource.addFilter(new HTTPBasicAuthFilter(username, password));
JAX-RS 2.0 way:
Client client = ClientBuilder.newClient(); WebTarget target = client.target(restURL); target.register(new HttpBasicAuthFilter(username, password));
Jersey 1.x way:
Client client = Client.create(); WebResource webResource = client.resource(restURL).accept("text/plain"); ClientResponse response = webResource.get(ClientResponse.class);
JAX-RS 2.0 way:
Client client = ClientBuilder.newClient(); WebTarget target = client.target(restURL); Response response = target.request("text/plain").get();
Jersey 1.x way:
Client client = Client.create(); WebResource webResource = client.resource(restURL); ClientResponse response = webResource.post(ClientResponse.class, "payload");
JAX-RS 2.0 way:
Client client = ClientBuilder.newClient(); WebTarget target = client.target(restURL); Response response = target.request().post(Entity.text("payload"));
Jersey 1.x way:
HTTPSProperties prop = new HTTPSProperties(hostnameVerifier, sslContext); DefaultClientConfig dcc = new DefaultClientConfig(); dcc.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, prop); Client client = Client.create(dcc);
Jersey 2.0 way:
Client client = ClientBuilder.newBuilder() .sslContext(sslContext) .hostnameVerifier(hostnameVerifier) .build();
JSON Support has undergone certain changes in Jersey 2.x. The most visible difference for the developer is in the initialization and configuration.
In Jersey 1.x, the JAXB/JSON Support was implemented as a set of MessageBodyReaders
and
MessageWriters
in the jersey-json
module.
Internally, there were several implementations of JSON to Object mapping ranging from Jersey's own custom
solution to third party providers, such as Jackson
or Jettison
.
The configuration of the JSON support was centralized in the JSONConfiguration
and
JSONJAXBContext
classes.
There are three main JSON-mapping handling approaches, which are preserved in Jersey 2: JAXB-based, POJO mapping and Low-level parsing The following table shows how to enable each of them in both Jersey 2 compared to Jersey 1:
Table 25.3. JSON approaches and usage in Jersey 1 vs Jersey 2
Approach | Jersey 1 | Jersey 2 |
---|---|---|
POJO | register POJOMappingFeature , use
ObjectMapper for configuration
|
use Jackson provider:
(add jersey-media-json-jackson dependency
and register
the JacksonFeature ), configure with custom
ObjectMapper instance.
|
JAXB | Default; use JSONConfiguration /JSONJAXBContext
for configuration
| use MOXy (add the jersey-media-moxy
dependency; the feature will be registered
automatically), configure
using MoxyJsonConfig
|
Low-level | Direct usage of JSONObject and/or
JSONArray classes | use JSON-P (standard) or Jettison (non-standard) APIs (add the relevant dependency) |
Example 25.5. Initializing JAXB-based support with MOXy
<dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-moxy</artifactId> <version>2.13</version> </dependency>
For JAXB-based support, MOXy is the default way in Jersey 2. However, other providers
(Jackson
, Jettison
) can be used as well.
The relevant feature has to be registered (and dependency added) and custom implementation
of ContextResolver
has to be provided. See the code snippets
in the related chapter.
For more on particular Feature
registration, see also:
Jackson registration,
Jettison registration,
MOXy registration,
JSON-P registration.
It is important to point out, that the Feature
registration has to be done
separately for client and server.
With Jersey 2.9, Jackson
has been updated to version 2.3.2. The feature is
still configured via mentioned ObjectMapper
class, but the package has changed.
jackson 1.x
,
use org.codehaus.jackson.map.ObjectMapper
jackson 2.x
, use
com.fasterxml.jackson.core.ObjectMapper
Jersey 1 was selecting the provider automatically based on the desired JSON Notation. This concept was replaced in Jersey 2 by direct choice of provider (as shown above). To provide some guide how to achieve the same results as in the previous Jersey version, see the following list:
MAPPED
not supported
NATURAL
default MOXy output
JETTISON_MAPPED
supported by Jettison
BADGERFISH
supported by Jettison
As mentioned, the centralized configuration of Jersey 1's JSONConfiguration
does not have
a direct equivalent in Jersey 2. Each provider has it's own way to be configured. Detailed description of
each
method and property is out of scope of this migration guide and can be found in the documentation and APIs of
the relevant providers and/or the relevant Jersey module API.
Bellow are several basic examples how to configure certain options when using MOXy with Jersey's
MoxyJsonConfig
class.
Formated output
Jersey 1: JSONConfiguration.createJSONConfigurationWithFormatted()
Jersey 2/MOXy: MoxyJsonConfig.setFormattedOutput()
Namespaces mapping
Jersey 1: JSONConfiguration.natural().xml2JsonNs()
Jersey 2/MOXy: MoxyJsonConfig.setNamespacePrefixMapper()
Namespace separator
Jersey 1: JSONConfiguration.natural().nsSeparator()
Jersey 2/MOXy: MoxyJsonConfig.setNamespaceSeparator()
Properties can be also passed directly to Marshaller
and/or Unmarshaller
using: MoxyJsonConfig
's property()
,
marshallerProperty()
and unmarshallerProperty()
methods.
More on the JSON Support topic can be found in Section 8.1, “JSON”.