Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jetty 9.0 embedded and RestEasy 3.0 keeps throwing NoSuchMethodError

Today I had the idea to build a very simple web application, which would be powered by a REST backend. Since I wanted a very lightweight server I started looking at Jetty. And since I wanted to try another JAX-RS implementation than Jersey I looked at RestEasy. I thought those 2 would be easy to implement. I was wrong...

I imported the basic Jetty server and servlet dependencies since I thought that were the only server requirements for a basic (REST only) Jetty server (I alto tried to use the webapp dependency; this gave the same errors).

<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-server</artifactId>
    <version>9.0.0.RC0</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-servlet</artifactId>
    <version>9.0.0.RC0</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-servlets</artifactId>
    <version>9.0.0.RC0</version>
    <scope>compile</scope>
</dependency>

Then I imported the basic RestEasy dependencies.

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jaxrs</artifactId>
    <version>3.0.1.Final</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jaxb-provider</artifactId>
    <version>3.0.1.Final</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>async-http-servlet-3.0</artifactId>
    <version>3.0.1.Final</version>
    <scope>compile</scope>
</dependency>

Main method:

public class ExampleActivator {
    public static void main(String args[]) throws Exception {
        Server server = new Server(8080);
        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
        context.setContextPath("/");
        ServletHolder h = new ServletHolder(new HttpServlet30Dispatcher());
        h.setInitParameter("javax.ws.rs.Application", "packages.ExampleResources");
        context.addServlet(h, "/*");
        server.setHandler(context);
        server.start();
        server.join();
    }
}

ExampleResources:

public class ExampleResources extends Application {

    private static final ImmutableSet services = ImmutableSet.of(
            ExampleResourceImpl.class
    );

    @Override
    public Set<Class<?>> getClasses() {
        return services;
    }
}

ExampleResourceImpl:

@Path("activities")
public class ExampleResourceImpl {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getAll() {
        return "Hello World";
    }
}

When I go to the webapge I get the following trace:

250 [main] INFO org.eclipse.jetty.server.Server - jetty-9.0.0.RC0
911 [main] INFO org.jboss.resteasy.spi.ResteasyDeployment - Deploying javax.ws.rs.core.Application: class packages.ExampleResources
939 [main] INFO org.jboss.resteasy.spi.ResteasyDeployment - Adding class resource packages.ExampleResourceImpl from Application class packages.ExampleResources
1005 [main] INFO org.eclipse.jetty.server.handler.ContextHandler - started o.e.j.s.ServletContextHandler@702ab48{/,null,AVAILABLE}
1037 [main] INFO org.eclipse.jetty.server.ServerConnector - Started ServerConnector@465ed596{HTTP/1.1}{0.0.0.0:8080}
6315 [qtp84346444-13] WARN org.eclipse.jetty.servlet.ServletHandler - Error for /activities
java.lang.NoSuchMethodError: org.jboss.resteasy.specimpl.BuiltResponse.getHeaders()Ljavax/ws/rs/core/MultivaluedMap;
    at org.jboss.resteasy.core.ServerResponseWriter.setDefaultContentType(ServerResponseWriter.java:195)
    at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:46)
    at org.jboss.resteasy.core.SynchronousDispatcher.writeResponse(SynchronousDispatcher.java:411)
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:376)
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:179)
    at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:220)
    at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
    at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:671)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:448)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1070)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:375)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1004)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:136)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
    at org.eclipse.jetty.server.Server.handle(Server.java:449)
    at org.eclipse.jetty.server.HttpChannel.run(HttpChannel.java:246)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:265)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.run(AbstractConnection.java:240)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:589)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:520)
    at java.lang.Thread.run(Thread.java:722)

Normally this would mean that I forgot a dependency, however I really have no clue what's going on.

like image 862
Wouter Avatar asked Jul 12 '13 15:07

Wouter


2 Answers

I just stumbled upon the same issue. The solution was to add the jaxrs-api explicitly as the first dependency in the list of dependencies.

<dependencies>
  <!-- jaxrs-api is the very first dependency -->
  <dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>jaxrs-api</artifactId>
    <version>3.0.4.Final</version>
  </dependency>
  <!-- here come the other depdendencies -->
</dependencies> 

Jackson uses the jsr311-api that provides the same Response class that is used by the BuiltResponse class. Unfortunately, this Response does not contain the getHeaders() method. So even though the dependency is resolved, it is using a wrong class. If somehow the Jackson dependency gets before the Resteasy one, then the exception above will be raised.

like image 115
allprog Avatar answered Nov 06 '22 18:11

allprog


I had the very same problem. First of all it was working using JAX-RS 2 and then it was migrated to JAX-RS 3, so I thought it had something to do with that. After failing in trying to get JBoss use JAX-RS 3 from app via Maven and jboss-deployment-structure.xml, I tried upgrading JBoss modules, which can be done using the following procedure:

3.1. Upgrading Resteasy Within JBoss AS 7 Resteasy is bundled with JBoss AS 7. You will likely have the need to upgrade Resteasy in AS7. The Resteasy distribution comes with a zip file called resteasy-jboss-modules-3.0.1.Final.zip. Unzip this file while with the modules/ directory of the JBoss AS7 distribution. This will overwrite some of the existing files there.

Source: http://docs.jboss.org/resteasy/docs/3.0.1.Final/userguide/pdf/resteasy-reference-guide-en-US.pdf

Hope it helps!

like image 22
Guatom Avatar answered Nov 06 '22 16:11

Guatom