Chapter 18. Migrating from Jersey 1.x | ||
---|---|---|
Prev |
Table of Contents
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 incompatiblities 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(RequestScope.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 18.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 18.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 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 18.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 18.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 have smaller priority than Jersey provided). 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 18.1. 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 | javax.ws.rs.client.ClientBuilder | For the static factory methods and constructors. |
javax.ws.rs.client.Client | For the instance methods. | |
com.sun.jersey.api.client.WebResource | javax.ws.rs.client.WebTarget | |
com.sun.jersey.api.client.AsyncWebResource | javax.ws.rs.client.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 = ClientFactory.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 = ClientFactory.newClient(); WebTarget target = client.target(restURL); target.configuration().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 = ClientFactory.newClient(); WebTarget target = client.target(restURL); Response response = target.request("text/plain").get(Response.class);
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 = ClientFactory.newClient(); WebTarget target = client.target(restURL); Response response = target.request().post(Entity.text("payload"), Response.class);
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 = ClientFactory.newClient(); client.configuration().setProperty(ClientProperties.SSL_CONTEXT, sslContext); client.configuration().setProperty(ClientProperties.HOSTNAME_VERIFIER, hostnameVerifier);
Prev | ||
Chapter 17. Building and Testing Jersey | Home |