How do I migrate from Jersey 1.0 to Jersey 2.0?
Asked Answered
G

5

26

I'm trying to upgrade to Jersey 2.0 and I'm having a lot of trouble because the groupIds and artifactIds of Jersey have completely changed and I can't find a migration plan in the Jersey docs.

Here's what my pom.xml used to look like, and this compiled fine:

        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>1.17</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-servlet</artifactId>
            <version>1.17</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server-linking</artifactId>
            <version>1.17.1</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-client</artifactId>
            <version>1.17.1</version>
        </dependency>

What should these be changed to? This unrelated StackOverflow question was somewhat helpful, but I'm having trouble finding things like where the @Ref annotation moved to.


Update

  1. It seems that @Ref no longer exists or at least it's not mentioned in the documentation anymore. Now you use a UriBuilder.
  2. I found a very helpful section in the documentation that answers my maven issues.
  3. The HTTPBasicAuthFilter has been renamed to HttpBasicAuthFilter. Notice the capitalization.
  4. Client client = Client.create(); has become Client client = ClientBuilder.newClient();
  5. This:

        String json = client
            .resource(getBaseUrl() + url)
            .accept(MediaType.APPLICATION_JSON_TYPE)
            .get(String.class);
    

    has become

    String json = client
            .target(getBaseUrl())
            .path(url)
            .request(MediaType.APPLICATION_JSON_TYPE)
            .get(String.class);
    
Gandy answered 13/6, 2013 at 22:35 Comment(2)
@PaulBellora No, it's not solved. This is just the information I have. There's more issues.Gandy
4 years later is your issue solved?Aureus
A
15

You don't.

Jersey 2.0 is missing a lot of functionality from Jersey 1.0. Contrary to what the committers will tell you, some things are plain impossible to implement right now (e.g. Guice, Spring integration). Things appear to work on the surface, but once you dig in deeper you will find a lot of features are still broken.

Many of the 1.x plugins do not exist in 2.x, mainly because of the aforementioned breakage.

In light of this, I suggest a holding off on Jersey 2.x for the foreseeable future. Hopefully the committers will clean this up in the coming year.

Awe answered 26/2, 2014 at 6:47 Comment(4)
The Spring integration part is not true anymore: jersey.java.net/documentation/latest/spring.htmlSquatness
We used hk2.java.net/spring-bridge for integrating Spring 4 and Jersey 2Squatness
@Awe do you still feel this way? It's been a couple years since you made this recommendation and I'm wondering what problems you still find in Jersey 1.x -> 2.x migrations.Sension
@Sension I believe that most of the missing functionality was eventually added to 2.x but migrating existing code is still extremely painful. Also, Guice and Spring integration remains fundamentally broken (cannot be implemented properly given the current design). My biggest beef with 2.x is that the team behind it ignores user feedback (and then attacks users who call them out on it). The main reason I used and contributed plugins to Jersey 1.x was because the strong developer/community support. When Oracle bought Sun, they replaced the team and everything went downhill.Awe
S
10

It is pain in the neck I have to say. We are currently knee deep into migrating relatively large 3+ years old client-server project and boy do I want to bite my neck off. Hopefully we are at the end of the struggle... While there is a migration guide indeed it is not comprehensive by any means.

  • UniformInterfaceException (and others) is no more.

Instead it is replaced by WebApplication exception and successors. There is not a word about that in the migration guide and this is very very important.

  • JSON support

The migration guide says:

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.

Great. What if you have chosen the "Jersey's own custom solution" (which we did for whatever reason)? There is no alternative to that in jersey 2. I tried to produce the same JSON format using Jettison, Jackson and Moxy providers. I did not succeed. For reference, my unanswered question here: Jersey 2 JSON Jettison unwrapping root element

Schoonmaker answered 5/4, 2016 at 15:34 Comment(0)
P
7

See the 1.x to 2.0 migration guide in the Jersey docs. (2019 link to 1.x to 2.0 migration guide)

Peruse answered 14/11, 2013 at 13:13 Comment(1)
That's helpful but I wouldn't say completely comprehensive. EG: No mention of @Ref and where it went. No mention of migrating maven poms, etc.Gandy
S
3

It looks like @InjectLink is the replacement for @Ref.

From that link, I was able to drop this into my pom.xml:

    <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-declarative-linking</artifactId>
        <version>2.6</version>
    </dependency>

and then I took an existing @Ref and was able to drop in replace with @InjectLink.

public Long id; // This id is referenced below in the link

@InjectLink(resource = FavoriteResource.class, method = "updateFavorites", bindings = {
        @Binding(name = "listId", value = "${instance.id}")
})
public URI linkURI;

It looks like some of the JavaDocs from @Ref are in @InjectLink even, which would be further confirmation that it's the replacement:

/**
 * ...
 * @Ref(resource=SomeResource.class)
 * @Ref(resource=SomeResource.class, bindings={
 *   @Binding(name="id" value="${instance.id}"}
 * )
*/

EDIT:

Tricky stuff. I needed one more piece to make this work for me. In web.xml, I now have:

<servlet>
    <servlet-name>jersey-servlet</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com.mycompany.root</param-value>
    </init-param>
    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>com.mycompany.root.web.filter.AuditResourceFilterFactory;com.mycompany.root.web.filter.OtherAuditResourceFilterFactory</param-value>
    </init-param>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>com.mycompany.root.web.resource.config.CustomResourceConfig</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

and finally, CustomResourceConfig.java looks like this

import org.glassfish.jersey.linking.DeclarativeLinkingFeature;
import org.glassfish.jersey.server.ResourceConfig;

public class CustomResourceConfig extends ResourceConfig {
    public CustomResourceConfig() {
        packages("org.glassfish.jersey.examples.linking");
        register(DeclarativeLinkingFeature.class);
    }
}
Spangler answered 26/2, 2014 at 19:34 Comment(0)
O
0

You can follow following steps for migration from Jersey 1 to Jersey 2 :

Add following dependencies in POM file : Jersey 2.23.2 dependencies

   <dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet-core</artifactId>
    <version>2.23.2</version>
   </dependency>
   <dependency>
    <groupId>org.glassfish.jersey.ext</groupId>
    <artifactId>jersey-spring3</artifactId>
    <version>2.23.2</version>
    <exclusions>
     <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
     </exclusion>
     <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
     </exclusion>
     <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
     </exclusion>
    </exclusions>
   </dependency>
   <dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-client</artifactId>
    <version>2.23.2</version>
   </dependency>
   <dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-moxy</artifactId>
    <version>2.23.2</version>
   </dependency>
   <dependency>
    <groupId>org.glassfish.jersey.ext</groupId>
    <artifactId>jersey-entity-filtering</artifactId>
    <version>2.23.2</version>
   </dependency>
   <dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-server</artifactId>
    <version>2.23.2</version>
   </dependency>
   <dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-common</artifactId>
    <version>2.23.2</version>
   </dependency>
   <dependency>
    <groupId>org.glassfish.jersey.bundles.repackaged</groupId>
    <artifactId>jersey-guava</artifactId>
    <version>2.23.2</version>
   </dependency>
   <dependency>
      <groupId>org.glassfish.jersey.media</groupId>
      <artifactId>jersey-media-json-jackson</artifactId>
      <version>2.23.2</version>
      <exclusions>
       <exclusion>
        <groupId>com.fasterxml.jackson.core</groupId>
         <artifactId>jackson-annotations</artifactId>
       </exclusion>
      </exclusions>
   </dependency>
   <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.5.4</version>
   </dependency>
   <dependency>
       <groupId>org.glassfish.jersey.media</groupId>
       <artifactId>jersey-media-multipart</artifactId>
       <version>2.23.2</version>
   </dependency>

   <dependency>
       <groupId>org.jvnet</groupId>
       <artifactId>mimepull</artifactId>
       <version>1.6</version>
   </dependency>

Make Following entry in Web.xml :

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

 <servlet>
  <servlet-name>jersey-servlet</servlet-name>
  <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
  <init-param>
   <param-name>javax.ws.rs.Application</param-name>
   <param-value>com.jsg.resource.initializer.RestResourceInitializer</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name>jersey-servlet</servlet-name>
  <url-pattern>/rest/*</url-pattern>
 </servlet-mapping> '

       <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:applicationContext.xml</param-value>
 </context-param>
      <resource-ref>
        <description>DB Connection</description>
        <res-ref-name>jdbc/myAppName</res-ref-name>
       <res-type>javax.sql.DataSource</res-type>
       <res-auth>Container</res-auth>
   </resource-ref>
</web-app>

Write following code in RestResourceIntializer

    package com.jsg.resource.initializer;

    import java.util.HashSet;
    import java.util.Set;
    import javax.ws.rs.core.Application;

    public class RestResourceInitializer extends Application {

     /**
      * Gets the classes.
      *
      * @return the classes
      */
     public Set<Class<?>> getClasses() {
      Set<Class<?>> classes = new HashSet<Class<?>>(); 

      // Resources
      classes.add(org.glassfish.jersey.jackson.JacksonFeature.class);
      classes.add(org.glassfish.jersey.server.spring.scope.RequestContextFilter.class);
      classes.add(org.glassfish.jersey.media.multipart.MultiPartFeature.class);

                   //Rest classes within Application.
                    classes.add(com.jsg.rest.AbcRestService.class);

      classes.add(com.jsg.rest.CdeRestService.class);
      return classes;
     }
    }

Now if you will deploy code with above changes on websphere,you will get following exception :

Caused by: java.lang.NoSuchMethodError: javax/ws/rs/core/Application.getProperties()Ljava/util/Map; at org.glassfish.jersey.server.ApplicationHandler.(ApplicationHandler.java:287) at org.glassfish.jersey.servlet.WebComponent.(WebComponent.java:311)

Reason for above exception is that,Websphere supports JAX-RS 1 implementation,however we are deploying Jersey 2 code which is Jax-rs 2 implementation.

Steps for resolving above exception:

So basically what we have to do is to force WebSphere to pick our Jersey 2 jars instead of default Jax-rs 1.We need to follow following steps for that

1) Disable in built JAX-RS by setting following JVM property to true

com.ibm.websphere.jaxrs.server.DisableIBMJAXRSEngine=true

This property can be set through admin console of WebSphere by going to Servers->All Server -> ->Server Infrastructure -> Java and Process Management ->Process Deifinition ->Additional Properties-> Java Virtual Machine ->Additional Properties-> Custom Properties

2) Create Isolated Shared Library having the Jersey 2 Jars and Spring 4 Jars Isolated shared library can be created through admin Console of Websphere by going to Environment-> Shared Libraries ->New

n the classpath box,we need to enter path of the folder on the server,where we have placed all Jersey 2 and Spring 4 Jars

/var/was/server2/jerseyLib1/spring-context-4.3.4.RELEASE.jar
/var/was/server2/jerseyLib1/spring-core-4.3.4.RELEASE.jar
/var/was/server2/jerseyLib1/spring-beans-4.3.4.RELEASE.jar
/var/was/server2/jerseyLib1/spring-aop-4.3.4.RELEASE.jar
/var/was/server2/jerseyLib1/spring-web-4.3.4.RELEASE.jar
/var/was/server2/jerseyLib1/spring-expression-4.3.4.RELEASE.jar
/var/was/server2/jerseyLib1/spring-bridge-2.5.0-b05.jar
/var/was/server2/jerseyLib1/hk2-locator-2.5.0-b05.jar
/var/was/server2/jerseyLib1/hk2-api-2.5.0-b05.jar
/var/was/server2/jerseyLib1/hk2-utils-2.5.0-b05.jar
/var/was/server2/jerseyLib/javax.inject-2.5.0-b05.jar
/var/was/server2/jerseyLib1/javax.annotation-api-1.2-b03.jar
/var/was/server2/jerseyLib1/javax.ws.rs-api-2.0.1.jar
/var/was/server2/jerseyLib1/jersey-client-2.23.2.jar
/var/was/server2/jerseyLib1/jersey-spring3-2.23.2.jar
/var/was/server2/jerseyLib1/jersey-container-servlet-core-2.23.2.jar
/var/was/server2/jerseyLib1/jersey-server-2.23.2.jar
/var/was/server2/jerseyLib1/jersey-common-2.23.2.jar

/var/was/server2/jerseyLib1/jersey-guava-2.23.2.jar

Also in class loading section ,select "use an isolated class loader for this shared library"

and then finally click on Apply and Ok and we are done with creation of isolated shared library.

  1. Bind this isolated shared library with your application war file as follows in admin Console

    a) Application -> All Applications -> Click on your application name b) Go to References -> Shared Library References -> Reference Shared Libraries ->select your application war(Not ear) and click ok. c) Select the library that we created in Step 2 in "Available" combo box on left side and put it on right side in "Selected" combo box and click ok. With this we have associated the isolated shared library with application war file.

  2. Restart Server and application should be up and running.
Oilbird answered 12/3, 2017 at 11:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.