Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.lang.ClassNotFoundException: javax.ws.rs.MessageProcessingException

I am deploying a war to Tomcat 7.0.57. This code uses Jersey 2.x Client to communicate with a Rest endpoint and exposes its own Rest endpoints using CXF (AKA the war's endpoint).

When I hit one of the war's endpoints, the code seems to work and returns a response without issue from the server's perspective, but the client gets a 500 response returned to it from tomcat. This is the error:

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)

Oddly enough, this error doesn't show up in the tomcat log.

I did a little research and it seems that this class is part of jax-rs. In my maven pom, I'm already including this dependency:

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

But this dependency doesn't seem to have this class. That class is in this dependency though:

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

I feel uncomfortable downgrading to a lower version that's a milestone though. More importantly, that jar does not include classes I'm using in my code like javax.ws.rs.client.ClientBuilder.

Can anyone explain why I'm getting this exception and how to resolve this issue?


My Workaround

I've come to the conclusion that this has more to do with the Jersey Client and CXF interfering with each other. I decided to remove the Jersey Client and replace it with the CXF Client. These instructions are much better than the official ones: 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());

    }
}

Very similar API. I just searched and replaced some method names and everything worked.

like image 429
Daniel Kaplan Avatar asked Nov 10 '22 20:11

Daniel Kaplan


1 Answers

I came across this issue too. Unlike you project requirements meant I had to get Jersey and CXF playing nice.

The ultimate problem is in the FactoryFinder class which is used by Jersey to get the appropriate runtime delegate (used for various subsidiary objects) - this in turn has a class with an import to the offending class.

To get around this you need to have a file in your resource folder (presuming this gets imported to your classpath folder) with the path META-INF/services/javax.ws.rs.ext.RuntimeDelegate that contains the value:

org.glassfish.jersey.internal.RuntimeDelegateImpl

This should solve your issue.

like image 67
Sam Keays Avatar answered Nov 15 '22 12:11

Sam Keays