2017-05-12 1 views
2

Ich entwickle einen Restful Service mit Jersey 2 + Feder. Im selben Projekt bin ich auf Spark 2.0.11 angewiesen. Aber sobald dem Projekt die Funkenabhängigkeit hinzugefügt wird, wird die folgende Ausnahme ausgelöst, wenn der Restful-Dienst aufgerufen wird. Die Ausnahme:Jersey + Spark javax.ws.rs.core.UriBuilder.uri

SEVERE: Servlet.service() for servlet [jersey-serlvet] in context with path [/recommender] threw exception [Servlet execution threw an exception] with root cause 
java.lang.AbstractMethodError: javax.ws.rs.core.UriBuilder.uri(Ljava/lang/String;)Ljavax/ws/rs/core/UriBuilder; 
    at javax.ws.rs.core.UriBuilder.fromUri(UriBuilder.java:119) 
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:298) 
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) 
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) 
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:958) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:452) 
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1087) 
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637) 
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
    at java.lang.Thread.run(Thread.java:745) 

pom.xml:

<properties> 
    <org.springframework-version>4.0.0.RELEASE</org.springframework-version> 
    <jersey2.version>2.19</jersey2.version> 
    <jaxrs.version>2.0.1</jaxrs.version> 
    </properties> 
<dependency> 
     <groupId>org.apache.spark</groupId> 
     <artifactId>spark-core_2.11</artifactId> 
     <version>2.0.0</version> 
    </dependency> 

    <!-- https://mvnrepository.com/artifact/org.apache.spark/spark-mllib_2.10 --> 
    <dependency> 
     <groupId>org.apache.spark</groupId> 
     <artifactId>spark-mllib_2.11</artifactId> 
     <version>2.0.0</version> 
    </dependency> 

    <!-- JAX-RS --> 
     <dependency> 
      <groupId>javax.ws.rs</groupId> 
      <artifactId>javax.ws.rs-api</artifactId> 
      <version>${jaxrs.version}</version> 
     </dependency> 
     <!-- Jersey 2.19 --> 
     <dependency> 
      <groupId>org.glassfish.jersey.containers</groupId> 
      <artifactId>jersey-container-servlet</artifactId> 
      <version>${jersey2.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>org.glassfish.jersey.core</groupId> 
      <artifactId>jersey-server</artifactId> 
      <version>${jersey2.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>org.glassfish.jersey.core</groupId> 
      <artifactId>jersey-client</artifactId> 
      <version>${jersey2.version}</version> 
     </dependency> 
    <dependency> 
     <groupId>io.swagger</groupId> 
     <artifactId>swagger-jersey-jaxrs</artifactId> 
     <version>1.5.0</version> 
     <!-- <exclusions> 
     <exclusion> 
      <artifactId>jersey-multipart</artifactId> 
      <groupId>com.sun.jersey.contribs</groupId> 
     </exclusion> 
     </exclusions> --> 
    </dependency> 

    <!-- spring --> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-core</artifactId> 
     <version>${org.springframework-version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-context</artifactId> 
     <version>${org.springframework-version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-web</artifactId> 
     <version>${org.springframework-version}</version> 
    </dependency> 



    <!-- jersey + spring --> 
    <dependency> 
     <groupId>com.sun.jersey.contribs</groupId> 
     <artifactId>jersey-spring</artifactId> 
     <version>1.9</version> 
     <exclusions> 
      <exclusion> 
       <groupId>org.springframework</groupId> 
       <artifactId>spring</artifactId> 
      </exclusion> 
      <exclusion> 
       <groupId>org.springframework</groupId> 
       <artifactId>spring-core</artifactId> 
      </exclusion> 
      <exclusion> 
       <groupId>org.springframework</groupId> 
       <artifactId>spring-web</artifactId> 
      </exclusion> 
      <exclusion> 
       <groupId>org.springframework</groupId> 
       <artifactId>spring-beans</artifactId> 
      </exclusion> 
      <exclusion> 
       <groupId>org.springframework</groupId> 
       <artifactId>spring-context</artifactId> 
      </exclusion> 
      <exclusion> 
       <groupId>org.springframework</groupId> 
       <artifactId>spring-asm</artifactId> 
      </exclusion> 
     </exclusions> 
    </dependency> 

web.xml

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
    id="WebApp_ID" version="2.5"> 
    <display-name>WebApp</display-name> 

    <!-- <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>classpath:applicationContext.xml</param-value> 
    </context-param> --> 

    <listener> 
     <listener-class> 
      org.springframework.web.context.ContextLoaderListener 
     </listener-class> 
    </listener> 

    <servlet> 
     <servlet-name>jersey-serlvet</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.company.recommender.rest.v1</param-value> 
     </init-param> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 

    <servlet> 
     <servlet-name>Jersey2Config</servlet-name> 
     <servlet-class>io.swagger.jaxrs.config.DefaultJaxrsConfig</servlet-class> 
     <init-param> 
      <param-name>api.version</param-name> 
      <param-value>1.0.0</param-value> 
     </init-param> 
     <init-param> 
      <param-name>swagger.api.basepath</param-name> 
      <param-value>http://localhost:8085/recommender/rest/v1</param-value> 
     </init-param> 
     <load-on-startup>2</load-on-startup> 
    </servlet> 

    <servlet-mapping> 
     <servlet-name>jersey-serlvet</servlet-name> 
     <url-pattern>/rest/v1/*</url-pattern> 
    </servlet-mapping> 

</web-app> 

Ich weiß, dass das Problem der Konflikt Definition UriBuilder Klasse ist (es in vielen gefunden ist im Preis inbegriffen Bibliothek) . Also jeder Vorschlag.

Antwort

2

Eigentlich 2.0 bringt mit

[INFO] | +- org.glassfish.jersey.core:jersey-client:jar:2.22.2:compile 
[INFO] | | +- javax.ws.rs:javax.ws.rs-api:jar:2.0.1:compile 

in Jersey 2.x Funken Wo, wie Jersey-Frühling in Jersey 1.x bringt, beide haben einige gemeinsame Klassen, aber Implementierungen sind unterschiedlich.

Nun lassen Sie uns auf der it es abstrakte Methode für UriBuilder Beispiel gestoßen sagen So

java.lang.AbstractMethodError: javax.ws.rs.core.UriBuilder.uri(Ljava/lang/String;)Ljavax/ws/rs/core/UriBuilder; 

Fehler suchen. Im Allgemeinen erlaubt der Java-Compiler keine Instanzen mit abstrakten Klassen (mit abstrakten Methoden) zu erstellen. Sie können also eindeutig feststellen, dass die zur Kompilierungszeit und zur Laufzeit verwendete Klasse anders ist. Mal sehen, wie die Klasse zur Laufzeit geändert wird, werfen Sie einen Blick in den Quellcode von javax.ws.rs.core.UriBuilder.fromUri Methode trace:

public static UriBuilder fromUri(URI uri) { 
    return newInstance().uri(uri); 
} 

die

protected static UriBuilder newInstance() { 
     return RuntimeDelegate.getInstance().createUriBuilder(); 
} 

für Anrufe, die unter Verwendung aufgelöst wird:

public static RuntimeDelegate getInstance() { 

     RuntimeDelegate result = cachedDelegate; 
     if (result == null) { // First check (no locking) 
      synchronized (RD_LOCK) { 
       result = cachedDelegate; 
       if (result == null) { // Second check (with locking) 
        cachedDelegate = result = findDelegate(); 
       } 
      } 
     } 
     return result; 
    } 

Es ruft RuntimeDelegate.findDelegate() auf, wodurch eine Implementierung von RuntimeDelegate erstellt wird, die wiederum zum Erstellen von UriBuilder verwendet wird. Aufgrund der Klassenpfadkonflikte zur Laufzeit löst es sich in com.sun.jersey.api.uri.UriBuilderImpl (aus Trikot 1), die keine Implementierung für die abstrakte Methode public abstract UriBuilder uri(String uriTemplate); hat (seit es von 2.0 eingeführt wurde). Um zu vermeiden, dass ich gerade

RuntimeDelegate.setInstance(new org.glassfish.jersey.internal.RuntimeDelegateImpl()); 

am Anfang der Anwendung getan habe. die wiederum eine korrekte Implementierung für org.glassfish.jersey.uri.internal.JerseyUriBuilder (nicht abstrakte Klasse) erstellen. Es setzt das statische Element cachedDelegate in RuntimeDelegate tatsächlich fest.

Da es nur eine URI-Auflösung ist, könnten verschiedene Bibliotheken funktionieren. Die angegebene Klasse ist vollständig kompatibel zu Jersey 1 und Jersey 2. Wenn jemand andere Bibliotheken dafür findet, lass es mich wissen.