How do I migrate from Jersey 1.0 to Jersey 2.0?

旧时模样 提交于 2019-12-20 11:22:31

问题


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);
    

回答1:


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.




回答2:


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




回答3:


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




回答4:


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);
    }
}



回答5:


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.

Reference with screenshots -> http://javasolutionsguide.blogspot.nl/2017/03/howtomigratefromjersey1tojersey2InWebsphere.html



来源:https://stackoverflow.com/questions/17098341/how-do-i-migrate-from-jersey-1-0-to-jersey-2-0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!