2015-01-09 27 views
5

Wdrażam wojnę Tomcat 7.0.57. Ten kod używa klienta Jersey 2.x do komunikowania się z punktem końcowym Rest i eksponuje własne punkty końcowe Rest przy użyciu CXF (AKA, punkt końcowy wojny).java.lang.ClassNotFoundException: javax.ws.rs.MessageProcessingException

Kiedy trafię jeden z punktów końcowych wojny, kod wydaje się działać i zwraca odpowiedź bez problemu z perspektywy serwera, ale klient otrzymuje odpowiedź 500 zwróconą do niego z tomcat. To jest błąd:

java.lang.ClassNotFoundException: javax.ws.rs.MessageProcessingException 
    org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1720) 
    org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571) 
    org.apache.cxf.jaxrs.impl.ResponseBuilderImpl.build(ResponseBuilderImpl.java:69) 
    org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.processResponse(JAXRSOutInterceptor.java:137) 
    org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.handleMessage(JAXRSOutInterceptor.java:86) 
    org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272) 
    org.apache.cxf.interceptor.OutgoingChainInterceptor.handleMessage(OutgoingChainInterceptor.java:77) 
    org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272) 
    org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) 
    org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:239) 
    org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:248) 
    org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:222) 
    org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:153) 
    org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:167) 
    org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:286) 
    org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:206) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:646) 
    org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:262) 
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 

Co dziwne, ten błąd nie pojawia się w logu tomcat.

Zrobiłem trochę badań i wydaje się, że ta klasa jest częścią jax-rs. W moim maven pom, już uwzględniam tę zależność:

<dependency> 
     <groupId>javax.ws.rs</groupId> 
     <artifactId>javax.ws.rs-api</artifactId> 
     <version>2.0.1</version> 
    </dependency> 

Ale ta zależność nie wydaje się mieć tej klasy. Że klasa jest w tym uzależnienia choć:

<dependency> 
     <groupId>javax.ws.rs</groupId> 
     <artifactId>javax.ws.rs-api</artifactId> 
     <version>2.0-m01</version> 
    </dependency> 

czuję się nieswojo Obniżka, do niższej wersji, która jest kamieniem milowym chociaż. Co ważniejsze, ten słoik nie obejmuje klas, których używam w moim kodzie, takich jak javax.ws.rs.client.ClientBuilder.

Czy ktoś może wyjaśnić, dlaczego otrzymuję ten wyjątek i jak rozwiązać ten problem?


My Obejście

Doszedłem do wniosku, że ma to więcej wspólnego z klientem Jersey i CXF przeszkadzania sobie nawzajem. Zdecydowałem się usunąć klienta z Jersey i zastąpić go klientem CXF. Instrukcje te są znacznie lepsze niż te oficjalne: http://fandry.blogspot.com/2012/06/how-to-create-simple-cxf-based-jax-rs.html

import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; 
import org.apache.cxf.jaxrs.client.WebClient; 
import java.util.ArrayList; 
import java.util.List; 

public class App 
{ 
    public static void main(String[] args) throws Exception { 

    List<Object> providers = new ArrayList<Object>(); 
    providers.add(new JacksonJaxbJsonProvider()); 

    WebClient client = WebClient.create("http://localhost:8080/poc_restapi_cxf/api", providers); 
    client = client.accept("application/json").type("application/json").path("/order").query("id", "1"); 

    Order order = client.get(Order.class); 
    System.out.println("Order:" + order.getCustomerName()); 

    } 
} 

Bardzo podobny API. Właśnie przeszukałem i zastąpiłem niektóre nazwy metod i wszystko działało.

+1

@ Michael-O Ponieważ różni ludzie patrzą na każde –

Odpowiedz

3

Natrafiłem też na ten problem. W przeciwieństwie do twoich wymagań projektowych musiałem sprawić, że Jersey i CXF grały miło.

Ostatecznym problemem jest klasa FactoryFinder, która jest używana przez Jersey w celu uzyskania odpowiedniego delegata czasu pracy (używanego dla różnych obiektów pomocniczych) - to z kolei ma klasę z importem do klasy przestępczej.

Aby obejść ten problem, należy mieć plik w folderze zasobów (zakładając, że zostanie on zaimportowany do folderu ścieżki klasy) ze ścieżką META-INF/services/javax.ws.rs.ext.RuntimeDelegate zawierającą wartość :

org.glassfish.jersey.internal.RuntimeDelegateImpl 

To powinno rozwiązać twój problem.

+0

Naprawiono to dla mnie. Dzięki. – Rusty

+0

zapisano dzień! jak na świecie znalazłeś to rozwiązanie? – spy

0

Dodaj następujący uzależnienia Maven

<dependency> 
<groupId>javax.ws.rs</groupId> 
<artifactId>javax.ws.rs-api</artifactId> 
<version>2.0-m08</version> 
</dependency> 
+0

"Czuję się nieswojo, przechodząc na niższą wersję, która jest kamieniem milowym". –

+2

To rozwiązanie wymieniło tylko jeden problem na inny. Zamiast brakującej klasy wspomnianej przez OP, brakuje teraz javax/ws/rs/NotFoundException – Blamkin86

+0

Otrzymałem ten sam błąd zgłoszony przez @ Blamkin86, java.lang.ClassNotFoundException: javax.ws.rs.NotFoundException –

-1

miałem bardzo podobny problem. Kiedy naprawiłem wyjątek dodając zależność (javax.ws.rs), nie mogłem wtedy użyć javax.ws.rs.client.ClientBuilder. Wprowadziłem następującą zmianę i problem zniknął.

sieć plików.xml

<servlet> 
<servlet-name>Jersey Web Application</servlet-name> 
- <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> 
+ <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> 
<init-param> 
- <param-name>jersey.config.server.provider.packages</param-name> 
+ <param-name>com.sun.jersey.config.property.packages</param-name> 
    <param-value>com.test.test1</param-value> 
</init-param> 
<load-on-startup>1</load-on-startup> 
<servlet>