java - 在jetty应用程序中使用resteasy-jackson-provider时缺少FindAnnotation类

标签 java jackson jetty resteasy fasterxml

我正在尝试在 Jetty 应用程序中使用 RestEasy。我正在使用 Jackson 来序列化/反序列化我的 POJO。我需要序列化是多态的,因为我有处理具有子类型的 POJO 类型的端点。我认为我可以使用 resteasy-jackson-provider 来提供我的 MessageBodyWriter 和 MessageBodyReader 实现。

当我调用端点时,出现以下错误:

java.lang.NoClassDefFoundError: org/jboss/resteasy/util/FindAnnotation
at org.jboss.resteasy.plugins.providers.jackson.ResteasyJacksonProvider.isWriteable(ResteasyJacksonProvider.java:42)
at org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl.resolveMessageBodyWriter(ResteasyProviderFactoryImpl.java:1322)
at org.jboss.resteasy.core.providerfactory.ResteasyProviderFactoryImpl.getMessageBodyWriter(ResteasyProviderFactoryImpl.java:1293)
at org.jboss.resteasy.core.ServerResponseWriter.lambda$writeNomapResponse$2(ServerResponseWriter.java:112)
at org.jboss.resteasy.core.interception.jaxrs.ContainerResponseContextImpl.filter(ContainerResponseContextImpl.java:405)
at org.jboss.resteasy.core.ServerResponseWriter.executeFilters(ServerResponseWriter.java:232)
at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:97)
at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:70)
at org.jboss.resteasy.core.SynchronousDispatcher.writeResponse(SynchronousDispatcher.java:578)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:508)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:252)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:153)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:363)
at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:156)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:238)
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:249)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:60)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:55)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:841)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.Server.handle(Server.java:561)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:334)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:104)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:679)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:597)
at java.base/java.lang.Thread.run(Thread.java:834)

这是我的 POM 文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.foster.app</groupId>
    <artifactId>jettyRestEasyApiService</artifactId>
    <version>3.0.0</version>
    <packaging>jar</packaging>
    <name>Jetty-RESTEasy Api Service</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>        
        <version.jetty>9.4.7.v20170914</version.jetty>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>${version.jetty}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.9</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.9</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-core</artifactId>
            <version>4.2.0.Final</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jackson-provider</artifactId>
            <version>3.9.0.Final</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>JettyRestEasyApiService</finalName>
        <plugins>
            <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.8.1</version>
              <configuration>
                <source>${maven.compiler.source}</source>
                <target>${maven.compiler.target}</target>
              </configuration>
            </plugin>
            <plugin>
               <artifactId>maven-surefire-plugin</artifactId>
               <version>2.19</version>
               <configuration>
                 <skip>true</skip>
               </configuration>
            </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.1.1</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                    <configuration>
                        <archive>
                            <manifest>
                                <mainClass>com.foster.app.resteasy.rest.App</mainClass>
                            </manifest>
                        </archive>
                        <descriptorRefs>
                            <descriptorRef>jar-with-dependencies</descriptorRef>
                        </descriptorRefs>
                    </configuration>
                </execution>
            </executions>
          </plugin>
        </plugins>
    </build>
</project>

这是我的主要类(class):

import java.util.logging.Level;
import java.util.logging.Logger;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher;

public class App {
    private static final Logger LOGGER = Logger.getLogger(App.class.getName());
    private static final String APPLICATION_PATH = "/jetty/resteasy";
    private static final String CONTEXT_ROOT = "/";

private static final Server JETTY_SERVER = new Server(8080);

public App() {}

public static void main(String[] args) throws Exception {
    try {
        new App().run();
    } catch (Exception ex) {
        LOGGER.log(Level.SEVERE, "Application Exception", ex);
        throw ex;
    } finally {
        if (JETTY_SERVER != null) {
            JETTY_SERVER.destroy();
        }
    }
}

public void run() throws Exception {
    final ServletContextHandler context = new ServletContextHandler(JETTY_SERVER, CONTEXT_ROOT);
    final ServletHolder restEasyServlet = new ServletHolder(new HttpServletDispatcher());

    restEasyServlet.setInitParameter("resteasy.servlet.mapping.prefix", APPLICATION_PATH);
    restEasyServlet.setInitParameter("javax.ws.rs.Application", JaxRsActivator.class.getCanonicalName());
    context.addServlet(restEasyServlet, APPLICATION_PATH + "/*");

    final ServletHolder defaultServlet = new ServletHolder(new DefaultServlet());
    context.addServlet(defaultServlet, CONTEXT_ROOT);

    JETTY_SERVER.start();
    LOGGER.log(Level.INFO, "Started Server");
    JETTY_SERVER.join();
    LOGGER.log(Level.INFO, "Joined Server");
}
}

这是我的应用程序类:

import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;

public class JaxRsActivator extends Application {
    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new HashSet<>();
        resources.add(MessageResource.class);
        resources.add(TestResource.class);
        return resources;
    }
}

这是我的 POJO 类:

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import java.io.Serializable;
import java.util.Date;

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "$type")
@JsonSubTypes({
    @JsonSubTypes.Type(
        value = PojoDog.class,
        name = "PojoDog"),
    @JsonSubTypes.Type(
        value = PojoCat.class,
        name = "PojoCat")
})
public abstract class Pojo implements Serializable {
    public String property1;
    public String property2;
    public int property3;
    public Date property4;
}

public class PojoCat extends Pojo {
    public long sebastian;
}
public class PojoDog extends Pojo {
    public String clifford;
}

这是我的端点:

@Path("/test")
public class TestResource {
    @GET
    @Path("pojo")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getPojo() {
        Pojo pojo = new PojoDog();
        pojo.property1 = "Hello";
        pojo.property2 = "World";
        pojo.property3 = 5;
        pojo.property4 = new Date();
        ((PojoDog)pojo).clifford = "I am a dog.";
        return Response.ok(pojo).build();
    }
}

最佳答案

org.jboss.resteasy.util.FindAnnotationresteasy-jaxrs工件的一部分。

查看搜索:

https://search.maven.org/search?q=fc:org.jboss.resteasy.util.FindAnnotation

这让我看到你们有混合的 Resteasy 版本。

        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-core</artifactId>
            <version>4.2.0.Final</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jackson-provider</artifactId>
            <version>3.9.0.Final</version>
        </dependency>

这 100% 无效,您需要在所有地方使用相同的 Resteasy 版本。

因此,我采用了您的代码并进行了一些简单的更改,并且它起作用了。

  1. 我升级到 Jetty 9.4.20.v20190813 .

  2. 升级至 org.jboss.resteasy/resteasy-jackson2-provider/4.2.0.Final

  3. 从 pom 中完全删除了两个 Jackson 依赖项,依赖于它们来自对 resteasy-jackson2-provider

    的传递依赖
        <!-- REMOVED : no point having them here 
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.9</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.9</version>
        </dependency>
        -->
  • 我初始化 ServletContextHandler 的方式略有不同(不要将服务器传递给构造函数,因为这是处理程序树的工作)。
  • final ServletContextHandler context = new ServletContextHandler();
    final ServletHolder restEasyServlet = new ServletHolder(new HttpServletDispatcher());
    
    context.setContextPath(CONTEXT_ROOT);
    
    restEasyServlet.setInitParameter("resteasy.servlet.mapping.prefix", APPLICATION_PATH);
    restEasyServlet.setInitParameter("javax.ws.rs.Application", JaxRsActivator.class.getCanonicalName());
    context.addServlet(restEasyServlet, APPLICATION_PATH + "/*");
    
    final ServletHolder defaultServlet = new ServletHolder("default", DefaultServlet.class); // the name "default" here is important
    context.addServlet(defaultServlet, "/"); // this is not context-root, it's the default url-pattern
    
    HandlerList handlers = new HandlerList();
    handlers.addHandler(context);
    handlers.addHandler(new DefaultHandler()); // to report errors that don't match the root context better
    
    JETTY_SERVER.setHandler(handlers);
    JETTY_SERVER.start();
    

    关于java - 在jetty应用程序中使用resteasy-jackson-provider时缺少FindAnnotation类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57931192/

    相关文章:

    java - 如何检查 HashMap 中的值

    java - Java中局部最终变量的行为

    java - 在 Jersey 2.17 中使用 SelectableEntityFiltering

    java - Riak(Java客户端)突然停止创建二级索引

    java - 如何在 DefaultMutableTreeNode (Java Swing) 中存储 CORBA 对象?

    java - 什么是NullPointerException,我该如何解决?

    java - 使用 jackson-asl 生成 JSON - 空流

    java - 集成测试 DropWizard 应用程序

    java - 将自定义数据从 Jersey Filter 服务传递到 Jersey End-Point 服务

    java - 嵌入式 Jetty 服务器不适用于 Java Vaadin 应用程序