2

I'm trying to run a Jersey REST Service using a Jetty Server. When I run in IntelliJ I get the following error:

java.lang.NoSuchMethodError: javax.ws.rs.core.Application.getProperties()Ljava/util/Map;
    at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:309)
    at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:338)
    at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:171)
    at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:363)
    at javax.servlet.GenericServlet.init(GenericServlet.java:244)
    etc...
    at service.WebserviceRunner.start(WebserviceRunner.java:37)

If I run the same project in Eclipse It runs fine. Why would the IDE Make a difference?


WebserviceRunner.java

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.webapp.WebAppContext;
import org.glassfish.jersey.server.ServerProperties;
import org.glassfish.jersey.servlet.ServletContainer;

public class WebserviceRunner {

    private Server server;
    private int port;
    private String host;

    public WebserviceRunner(String host, int port) {
        this.server = new Server(port);
        this.host = host;
        this.port = port;
    }

    public void start() throws Exception {
        HandlerCollection handlers = new HandlerCollection();
        WebAppContext handler = new WebAppContext();

        handler.setContextPath("/");
        handler.setResourceBase("./");
        handler.setClassLoader(Thread.currentThread().getContextClassLoader());

        ServletHolder restServlet = handler.addServlet(ServletContainer.class,  "/*");
        restServlet.setInitOrder(0);
        restServlet.setInitParameter(ServerProperties.PROVIDER_PACKAGES,"resource");

        handlers.addHandler(handler);

        server.setHandler(handlers);
        server.start();
        System.out.println("API started... at 'http://" + getHostAndPort() + "'");
    }

    private String getHostAndPort() {
        return host + ":" + port;
    }

    public static void main(String[] args) throws Exception {
        new WebserviceRunner("localhost", 8315).start();
    }
}

build.gradle

apply plugin: 'java'
apply plugin: 'jetty'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'war'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.glassfish.jersey.core:jersey-server:2.17'
    compile 'org.glassfish.jersey.containers:jersey-container-servlet-core:2.17'

    compile 'org.javassist:javassist:3.15.0-GA'
    compile 'javax.ws.rs:javax.ws.rs-api:2.0.1'
    compile 'javax.inject:javax.inject:1'
    compile 'com.google.code.gson:gson:2.2.2'
    compile 'com.google.guava:guava:10.0'
    compile 'com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.3.0'
    testCompile group: 'junit', name: 'junit', version: '4.11'

    def jettyVersion = '7.2.2.v20101205';
    compile "org.eclipse.jetty:jetty-server:${jettyVersion}"
    compile "org.eclipse.jetty:jetty-webapp:${jettyVersion}"
    compile "org.eclipse.jetty:jetty-servlet:${jettyVersion}"
    compile "org.eclipse.jetty:jetty-servlets:${jettyVersion}"
    compile "org.eclipse.jetty:jetty-annotations:${jettyVersion}"
    compile 'org.mortbay.jetty:jsp-2.1-glassfish:2.1.v20100127'
    compile 'javax.servlet:jstl:1.2'
    compile 'javax.servlet:javax.servlet-api:3.0.1'
}

Note: I think this is something to do with having two different versions of the same Application class on my classpath. Why is this when I'm only importing one?

enter image description here

Eduardo
  • 6,900
  • 17
  • 77
  • 121
  • Do you know whether the one or the other IDE uses Proguard for code obfuscation? This could make a difference .... – Trinimon Apr 26 '15 at 17:09
  • @Trinimon I'm running the default setting on both IDEs, I'm not sure how to find out. I think this is an issue to do with having two versions of a class on the same classpath, Eclipse seems to be picking the right one but not IntelliJ. – Eduardo Apr 26 '15 at 17:18
  • Usually you would find a `proguard` file somewhere within your project. Public methods of imported libraries shouldn't be obfuscated, so you usually add something like `-keep public class * extends javax.ws.rs.core.*`. But looking at the "missing" class I've another idea ... (look answer below) – Trinimon Apr 26 '15 at 17:47
  • @Trinimon I added a screenshot of when i do a Type Search in IntelliJ (sorry about how small it is!), it seems to think theres a couple of Application classes, the javax.ws.rs-api-2.0.1 has a getProperties() Method, the jsr311-api-1.1.1 version doesn't. – Eduardo Apr 26 '15 at 18:07
  • Yes, can see it as well: http://grepcode.com/file/repo1.maven.org/maven2/javax.ws.rs/javax.ws.rs-api/2.0.1/javax/ws/rs/core/Application.java?av=f .... mmmhh - no idea :( – Trinimon Apr 26 '15 at 18:16
  • @Trinimon I wonder if it's a Jersey 2.x thing – Eduardo Apr 26 '15 at 18:19
  • Good question: did you see http://stackoverflow.com/questions/19225618/java-restfull-webservice-jax-rs-implementation-with-jersey-2-3-1-libraries or http://stackoverflow.com/questions/26288116/java-lang-nosuchmethoderror-javax-ws-rs-core-application-getpropertiesljava-u? – Trinimon Apr 26 '15 at 18:56

1 Answers1

2

I ran into this issue yesterday, using Maven, not Gradle. You are correct, the issue is due to having two jars with the same class name in same package: java.ws.rs.core.Application.

I was able to fix it by searching the dependency tree and finding which jar's dependency brings in the jersey version of Application and excluding it using Maven's exclusion tag.

In your case it is pretty obvious: the class loader is seeing two versions of java.ws.rs.core.Application and picking the one from org.glassfish.jersey.core which is not the one you want.

As to why it works in Eclipse and not in IDEA, the class loader does not guarantee the order in which the classes are loaded, using two different class loaders may load classes in different order and if there are duplications that will result in different behavior.

Hamid
  • 90
  • 1
  • 7