球衣 + 火花 javax.ws.rs.core.UriBuilder.uri
Jersey + Spark javax.ws.rs.core.UriBuilder.uri
我正在使用 Jersey 2 + spring 开发 Restful 服务。在同一个项目中,我依赖于 Spark 2.0.11。但是一旦将 spark 依赖项添加到项目中,就会在调用 Restful 服务时抛出以下异常。异常:
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>
我知道问题出在 UriBuilder 的定义冲突上 class(在许多包含的库中都有)。所以任何建议。
实际上 Spark 2.0 带来了球衣 2.x 和
[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
球衣-spring 带来球衣 1.x,
两者都有一些共同的 classes,但实现方式不同。
现在,让我们看看错误
java.lang.AbstractMethodError: javax.ws.rs.core.UriBuilder.uri(Ljava/lang/String;)Ljavax/ws/rs/core/UriBuilder;
所以它说它遇到了 UriBuilder
实例的抽象方法。通常 Java 编译器不允许创建具有抽象 classes(具有抽象方法)的实例。所以你可以清楚地得出结论,编译时使用的 class 和 运行-time 是不同的。让我们看看 class 在 运行 时是如何改变的,看看 javax.ws.rs.core.UriBuilder.fromUri
方法跟踪的源代码:
public static UriBuilder fromUri(URI uri) {
return newInstance().uri(uri);
}
这需要
protected static UriBuilder newInstance() {
return RuntimeDelegate.getInstance().createUriBuilder();
}
使用以下方法解决:
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;
}
它正在调用 RuntimeDelegate.findDelegate()
,这将创建 RuntimeDelegate 的实现,而后者又将用于创建 UriBuilder
。由于 class 路径在 运行 时不匹配,它解析为 com.sun.jersey.api.uri.UriBuilderImpl
(来自 jersey 1),它没有抽象方法 public abstract UriBuilder uri(String uriTemplate);
的实现(因为它被引入从 2.0)。为了避免这种情况,我刚刚做了
RuntimeDelegate.setInstance(new org.glassfish.jersey.internal.RuntimeDelegateImpl());
在应用程序开始时。这反过来为 org.glassfish.jersey.uri.internal.JerseyUriBuilder
(非抽象 class)创建了正确的实现。它实际上在 RuntimeDelegate
中设置了名为 cachedDelegate
的静态成员。
由于只是 URI 解析,不同的库可能会起作用。给定的 class 与 jersey 1 和 jersey 2 完全兼容。如果有人为此找到任何其他库,请告诉我。
我正在使用 Jersey 2 + spring 开发 Restful 服务。在同一个项目中,我依赖于 Spark 2.0.11。但是一旦将 spark 依赖项添加到项目中,就会在调用 Restful 服务时抛出以下异常。异常:
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>
我知道问题出在 UriBuilder 的定义冲突上 class(在许多包含的库中都有)。所以任何建议。
实际上 Spark 2.0 带来了球衣 2.x 和
[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
球衣-spring 带来球衣 1.x, 两者都有一些共同的 classes,但实现方式不同。
现在,让我们看看错误
java.lang.AbstractMethodError: javax.ws.rs.core.UriBuilder.uri(Ljava/lang/String;)Ljavax/ws/rs/core/UriBuilder;
所以它说它遇到了 UriBuilder
实例的抽象方法。通常 Java 编译器不允许创建具有抽象 classes(具有抽象方法)的实例。所以你可以清楚地得出结论,编译时使用的 class 和 运行-time 是不同的。让我们看看 class 在 运行 时是如何改变的,看看 javax.ws.rs.core.UriBuilder.fromUri
方法跟踪的源代码:
public static UriBuilder fromUri(URI uri) {
return newInstance().uri(uri);
}
这需要
protected static UriBuilder newInstance() {
return RuntimeDelegate.getInstance().createUriBuilder();
}
使用以下方法解决:
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;
}
它正在调用 RuntimeDelegate.findDelegate()
,这将创建 RuntimeDelegate 的实现,而后者又将用于创建 UriBuilder
。由于 class 路径在 运行 时不匹配,它解析为 com.sun.jersey.api.uri.UriBuilderImpl
(来自 jersey 1),它没有抽象方法 public abstract UriBuilder uri(String uriTemplate);
的实现(因为它被引入从 2.0)。为了避免这种情况,我刚刚做了
RuntimeDelegate.setInstance(new org.glassfish.jersey.internal.RuntimeDelegateImpl());
在应用程序开始时。这反过来为 org.glassfish.jersey.uri.internal.JerseyUriBuilder
(非抽象 class)创建了正确的实现。它实际上在 RuntimeDelegate
中设置了名为 cachedDelegate
的静态成员。
由于只是 URI 解析,不同的库可能会起作用。给定的 class 与 jersey 1 和 jersey 2 完全兼容。如果有人为此找到任何其他库,请告诉我。