Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support jersey 2 for eureka #846

Open
nodje opened this issue Feb 23, 2016 · 17 comments
Open

Support jersey 2 for eureka #846

nodje opened this issue Feb 23, 2016 · 17 comments

Comments

@nodje
Copy link

nodje commented Feb 23, 2016

Using Jersey for the REST layer in a project, I've got a dependency conflict when using Spring Cloud as follow:

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-parent</artifactId>
                <version>Brixton.M4</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-zuul</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-security</artifactId>
          <scope>runtime</scope>
      </dependency>

The Spring Boot Jersey dependency org.springframework.boot:spring-boot-starter-jersey:jar:1.3.2.RELEASE is used.

The error is

java.lang.NoSuchMethodError: javax.ws.rs.core.Application.getProperties()Ljava/util/Map;
    at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:331) ~[jersey-server-2.22.1.jar:na]
    at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:390) ~[jersey-container-servlet-core-2.22.1.jar:na]
    at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:172) ~[jersey-container-servlet-core-2.22.1.jar:na]
    at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:364) ~[jersey-container-servlet-core-2.22.1.jar:na]
    at javax.servlet.GenericServlet.init(GenericServlet.java:158) ~[tomcat-embed-core-8.0.30.jar:8.0.30]

and it comes from the fact that both

  • javax.ws.rs:javax.ws.rs-api:jar:2.0.1:compile
  • javax.ws.rs:jsr311-api:jar:1.1.1:runtime
    are present in the classpath.

spring-cloud-starter-zuul includes jsr311-api.jar from its ribbon-httpclient dependency

+- com.netflix.ribbon:ribbon-httpclient:jar:2.1.0:compile
    [INFO] |  |  |  +- com.sun.jersey:jersey-client:jar:1.19:runtime
    [INFO] |  |  |  |  \- com.sun.jersey:jersey-core:jar:1.19:runtime
    [INFO] |  |  |  |     \- javax.ws.rs:jsr311-api:jar:1.1.1:runtime
    [INFO] |  |  |  \- com.sun.jersey.contribs:jersey-apache-client4:jar:1.19:runtime

I solved it by excluding jersey-client like this

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-parent</artifactId>
                <version>Brixton.M4</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-zuul</artifactId>
          <exclusions>
                <exclusion>
                    <groupId>com.sun.jersey</groupId>
                    <artifactId>jersey-client</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jersey.contribs</groupId>
                    <artifactId>jersey-apache-client4</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-security</artifactId>
            <scope>runtime</scope>
        </dependency>

It works when testing Zuul manually but I'm not sure it would under all conditions.

It's heavy handed but I figure I already have a much newer jersey client org.glassfish.jersey.core:jersey-client:jar:2.22.1:compile included with Spring Boot Jersey.

Why would ribbon use older Jersey client dependency? Is there any reason it wouldn't work with the newest org.glassfish.jersey.core:jersey-client:jar:2.22.1 ??

@dsyer
Copy link
Contributor

dsyer commented Feb 23, 2016

Why would ribbon use older Jersey client dependency?

You'd have to take that up with the Ribbon devs. Ribbon is a Netflix project.

Is there any reason it wouldn't work with the newest org.glassfish.jersey.core:jersey-client:jar:2.22.1 ?

I'd be very surprised if it worked (it's a major upgrade of a core component), but if you have something that works, that's awesome.

@spencergibb
Copy link
Member

Do we document that ribbon and eureka use jersey and therefor could conflict?

@dsyer
Copy link
Contributor

dsyer commented Mar 3, 2016

I guess so. Note that it's only a problem with eureka server as far as I know (which has never been very embeddable).

@maihacke
Copy link

maihacke commented May 1, 2016

There are additional problems when using ribbon clients.

The exception is

org.springframework.beans.factory.BeanInitializationException: Failed to process @EventListener annotation on bean with name 'ribbonRestClient'; nested exception is java.lang.NoClassDefFoundError: com/sun/jersey/api/client/config/ClientConfig

The cause is that org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration imports

import com.sun.jersey.api.client.Client; import com.sun.jersey.client.apache4.ApacheHttpClient4;

which belongs to JAX-RS 1.x and is not available in JAX-RS 2.

@dsyer
Copy link
Contributor

dsyer commented May 1, 2016

Yeah, that's right, sorry. You can't use ribbon with JAX-RS 2.0.

@nodje
Copy link
Author

nodje commented May 24, 2016

I'm stuck with this problem agan. I have to migrate a monolithic app using Jersey 2.0 to a microservice.
Has anyone been touch with Netflix about it?

I guess having them migrate their code to use a Jersey 2.0 client is the the best bet to solve this problem.

@spencergibb
Copy link
Member

@nodje see Netflix/eureka#600

Short answer: the code allows an implementation now as there is an abstraction. Netflix isn't keen on building it themselves, but would be open to PR's. We may do some work on this, but it would likely be based on RestTemplate, not jersey.

@spencergibb
Copy link
Member

For those watching, Netflix has started a jersey 2 client. https://github.com/Netflix/eureka/tree/master/eureka-client-jersey2

Not sure how much more work they are going to do.

@voor
Copy link

voor commented Oct 26, 2016

Update in this thread, looks like Eureka Client 1.6 will be compatible: Netflix/eureka#821

@spencergibb spencergibb changed the title Dependency conflict when using Spring Cloud with spring-boot-starter-jersey Support jersey 2 for eureka Nov 16, 2016
@aksain
Copy link

aksain commented Dec 19, 2016

@spencergibb Can this be included in 1.3.0.M1 milestone as this issue resolution is quite crucial to use Jersey 2 with Spring cloud?

@spencergibb
Copy link
Member

@aksain, probably not. I don't know what is involved to get this to work and haven't had time to look at it.

@aksain
Copy link

aksain commented Dec 25, 2016

@spencergibb Alright. For now, I have created one more starter on top of Spring cloud netflix one. Sharing the changes that i had to do, as this could be handy -

  1. In CloudEurekaClient.java - Replaced DiscoveryClientOptionalArgs with AbstractDiscoveryClientOptionalArgs
  2. In MutableDiscoveryClientOptionalArgs.java - Made it extend from Jersey2DiscoveryClientOptionalArgs, Replaced ClientFilter with ClientRequestFilter and added a constructor to set TransportClientFactories in super class to Jersey2TransportClientFactories.getInstance() using setTransportClientFactories method
  3. In EurekaClientAutoConfiguration - Replaced DiscoveryClientOptionalArgs with AbstractDiscoveryClientOptionalArgs

@spencergibb
Copy link
Member

@aksain Pull Requests are welcome.

@michael-simons
Copy link

Having Jersey 1.x on the classpath of a Spring Boot app running JAX-RS on Jetty prevents the application from starting with the Spring Boot Maven plugin. See ticket over here spring-projects/spring-boot#13290. We use Ribbon and not Eureka and at the moment, we're just excluding Jersey-Client 1.x.

@jlelong-onepoint
Copy link

Same problem from me. Is there any roadmap, news about a migration path ?

@dsyer
Copy link
Contributor

dsyer commented Nov 19, 2020

The migration path is to not use Jersey 1.x, I guess (https://cloud.spring.io/spring-cloud-netflix/multi/multi__service_discovery_eureka_clients.html#_eurekaclient_without_jersey). And I guess to not use Ribbon.

@jlelong-onepoint
Copy link

jlelong-onepoint commented Nov 19, 2020

The migration path is to not use Jersey 1.x, I guess (https://cloud.spring.io/spring-cloud-netflix/multi/multi__service_discovery_eureka_clients.html#_eurekaclient_without_jersey). And I guess to not use Ribbon.

I had wrongly guess that was not supported as this ticket is open. On my side i have also exclude the jsr311 (jax-rs 1) dependency as my point was to avoid conflict with jax-rs 2. Eureka client and core explicitly depend on it in addition to jersey.

For reference my final gradle configuration is :

    implementation('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client') {
        exclude group: 'com.sun.jersey'
        exclude module: 'jsr311-api'
    }

We have now to test in order to assure compatibility between Eureka and jaxrs 2.

Thanks a lots for your help

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants