JAX-RS: "RESTEASY002005: 执行 GET 失败 org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure

JAX-RS: "RESTEASY002005: Failed executing GET org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure

我创建了一个简单的服务,使我能够侦听传入的 REST 请求,然后执行任务,return 任务的输出作为自定义 object (MyObject ).

当我从 IntelliJ 执行此服务时它运行得很好 [我假设 jaxrs jar 是从 InteliJ 的内部存储库加载的] 但是当我从命令行执行 jar 时失败。异常情况如下:

[ERROR] RESTEASY002005: Failed executing GET /myapp/getVal
org.jboss.resteasy.core.NoMessageBodyWriterFoundFailure: Could not find MessageBodyWriter for response object of type: com.myproject.model.MyObject of media type: application/json
    at org.jboss.resteasy.core.ServerResponseWriter.lambda$writeNomapResponse(ServerResponseWriter.java:104) ~[myapp-jar-with-dependencies.jar:na]
    at org.jboss.resteasy.core.interception.ContainerResponseContextImpl.filter(ContainerResponseContextImpl.java:398) ~[myapp-jar-with-dependencies.jar:na]
    at org.jboss.resteasy.core.ServerResponseWriter.executeFilters(ServerResponseWriter.java:205) ~[myapp-jar-with-dependencies.jar:na]
    at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:82) ~[myapp-jar-with-dependencies.jar:na]
    at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:56) ~[myapp-jar-with-dependencies.jar:na]
    at org.jboss.resteasy.core.SynchronousDispatcher.writeResponse(SynchronousDispatcher.java:528) ~[myapp-jar-with-dependencies.jar:na]
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:459) ~[myapp-jar-with-dependencies.jar:na]
    at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke(SynchronousDispatcher.java:229) ~[myapp-jar-with-dependencies.jar:na]
    at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess[=12=](SynchronousDispatcher.java:135) ~[myapp-jar-with-dependencies.jar:na]
    at org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:355) ~[myapp-jar-with-dependencies.jar:na]
    at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:138) ~[myapp-jar-with-dependencies.jar:na]
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:215) ~[myapp-jar-with-dependencies.jar:na]
    at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:227) ~[myapp-jar-with-dependencies.jar:na]
    at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56) ~[myapp-jar-with-dependencies.jar:na]
    at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51) ~[myapp-jar-with-dependencies.jar:na]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:867) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:542) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1345) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:480) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1247) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.server.Server.handle(Server.java:502) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.io.ChannelEndPoint.run(ChannelEndPoint.java:118) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765) ~[myapp-jar-with-dependencies.jar:na]
    at org.eclipse.jetty.util.thread.QueuedThreadPool.run(QueuedThreadPool.java:683) ~[myapp-jar-with-dependencies.jar:na]

我的代码片段如下:

parent pom:

<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.myproject</groupId>
  <artifactId>myapp</artifactId>
  <packaging>pom</packaging>
  <version>1.4-SNAPSHOT</version>
  <name>My Application</name>
  <description>My Application</description>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <maven-compiler-plugin.version>3.2</maven-compiler-plugin.version>
    <maven-assembly-plugin.version>2.4</maven-assembly-plugin.version>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <sonar.jacoco.reportPath>${coverage.reports.dir}/jacoco-unit.exec</sonar.jacoco.reportPath>
    <sonar.jacoco.itReportPath>${coverage.reports.dir}/jacoco-it.exec</sonar.jacoco.itReportPath>
    <sonar.jacoco.agent.jar>${basedir}/target/jacoco-jars/jacocoagent.jar</sonar.jacoco.agent.jar>
    <jacoco.reports.unit.dir>${basedir}/target/jacoco-reports/unit</jacoco.reports.unit.dir>
    <jacoco.reports.it.dir>${basedir}/target/jacoco-reports/it</jacoco.reports.it.dir>
    <coverage.reports.dir>${basedir}/target/coverage-reports</coverage.reports.dir>
    <sonar.dynamic>reuseReports</sonar.dynamic>
    <guice.version>4.1.0</guice.version>
    <java.version>1.8</java.version>
    <log4j.version>1.2.17</log4j.version>
    <jetty.version>9.4.14.v20181114</jetty.version>
    <resteasy.version>3.6.2.Final</resteasy.version>
    <maven.build.timestamp.format>yyyyMMdd'T'HHmm</maven.build.timestamp.format>
  </properties>
  <scm>
    <!-- My scm -->
  </scm>
  <repositories>
    <!-- My repositories -->
  </repositories>
  <modules>
    <module>myChild</module>
  </modules>
  <dependencies>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-core</artifactId>
      <version>1.1.3</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.1.3</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>log4j-over-slf4j</artifactId>
      <version>1.7.7</version>
    </dependency>
  </dependencies>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-servlet</artifactId>
        <version>${jetty.version}</version>
      </dependency>
      <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jaxrs</artifactId>
        <version>${resteasy.version}</version>
      </dependency>
      <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-guice</artifactId>
        <version>${resteasy.version}</version>
      </dependency>
      <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jackson2-provider</artifactId>
        <version>${resteasy.version}</version>
      </dependency>
      <dependency>
        <groupId>com.google.inject.extensions</groupId>
        <artifactId>guice-multibindings</artifactId>
        <version>${guice.version}</version>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <build>
    <finalName>myapp</finalName>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3.2</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <mainClass>com.myproject.main.mainClass</mainClass>
            </manifest>
          </archive>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-release-plugin</artifactId>
        <version>2.5.3</version>
        <configuration>
          <localCheckout>true</localCheckout>
          <autoVersionSubmodules>true</autoVersionSubmodules>
        </configuration>
      </plugin>

      <plugin>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.18.1</version>
        <configuration>
          <argLine>-Dfile.encoding=${project.build.sourceEncoding} ${argLine}</argLine>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.8.3</version>
        <configuration>
          <destFile>${basedir}/target/coverage-reports/jacoco-unit.exec</destFile>
          <dataFile>${basedir}/target/coverage-reports/jacoco-unit.exec</dataFile>
          <append>true</append>
        </configuration>
        <executions>
          <execution>
            <id>agent-for-ut</id>
            <goals>
              <goal>prepare-agent</goal>
            </goals>
          </execution>
          <execution>
            <id>jacoco-site</id>
            <phase>package</phase>
            <goals>
              <goal>report</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

我的 child pom:

<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">

    <parent>
        <groupId>com.myproject</groupId>
        <artifactId>myapp</artifactId>
    <version>1.4-SNAPSHOT</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.myproject.myapp</groupId>
    <artifactId>myChildApp</artifactId>
    <packaging>jar</packaging>
    <name>myChildApp</name>

    <dependencies>
        <dependency>
            <groupId>commons-cli</groupId>
            <artifactId>commons-cli</artifactId>
            <version>1.3.1</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jaxrs</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-guice</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jackson2-provider</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
    </dependencies>
</project>

我的 REST API 代码如下:


@Path("/myapp")
@Singleton
public class MyResource {

    @GET
    @Path("/getVal")
    @Produces(MediaType.APPLICATION_JSON)
    public MyObject getVal(@QueryParam("id") @NonNull String id) throws Exception {
        try {
            return getMyObjData(id);
        } catch(IllegalArgumentException e) {
            throw new Exception(e.getMessage());
        }
    }
}

我浏览了几个类似问题的链接,但 none 帮助了我。例如:

RestEasy: Could not find MessageBodyWriter for response object of type: java.util.ArrayList of media type: application/json

根据我使用 IntelliJ 进行的调试以及 运行 命令行上的 jar,在我看来,我尝试构建的 jar 不依赖于 jaxrs(如果我没记错的话)即使我已经将它们添加到我的 pom.因此,我不确定如何处理这个问题。有人可以帮我解决这个问题吗?

更新:

根据评论,我更新了我的 parent 和 child pom,如下所示:

Parent pom

<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.myproject</groupId>
  <artifactId>myapp</artifactId>
  <packaging>pom</packaging>
  <version>1.4-SNAPSHOT</version>
  <name>My Application</name>
  <description>My Application</description>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <maven-compiler-plugin.version>3.2</maven-compiler-plugin.version>
    <maven-assembly-plugin.version>2.4</maven-assembly-plugin.version>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <sonar.jacoco.reportPath>${coverage.reports.dir}/jacoco-unit.exec</sonar.jacoco.reportPath>
    <sonar.jacoco.itReportPath>${coverage.reports.dir}/jacoco-it.exec</sonar.jacoco.itReportPath>
    <sonar.jacoco.agent.jar>${basedir}/target/jacoco-jars/jacocoagent.jar</sonar.jacoco.agent.jar>
    <jacoco.reports.unit.dir>${basedir}/target/jacoco-reports/unit</jacoco.reports.unit.dir>
    <jacoco.reports.it.dir>${basedir}/target/jacoco-reports/it</jacoco.reports.it.dir>
    <coverage.reports.dir>${basedir}/target/coverage-reports</coverage.reports.dir>
    <sonar.dynamic>reuseReports</sonar.dynamic>
    <guice.version>4.1.0</guice.version>
    <java.version>1.8</java.version>
    <log4j.version>1.2.17</log4j.version>
    <jetty.version>9.4.14.v20181114</jetty.version>
    <resteasy.version>3.6.2.Final</resteasy.version>
    <maven.build.timestamp.format>yyyyMMdd'T'HHmm</maven.build.timestamp.format>
  </properties>
  <scm>
    <!-- My scm -->
  </scm>
  <repositories>
    <!-- My repositories -->
  </repositories>
  <modules>
    <module>myChild</module>
  </modules>
  <dependencies>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-core</artifactId>
      <version>1.1.3</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.1.3</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>log4j-over-slf4j</artifactId>
      <version>1.7.7</version>
    </dependency>
  </dependencies>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-servlet</artifactId>
        <version>${jetty.version}</version>
      </dependency>
      <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jaxrs</artifactId>
        <version>${resteasy.version}</version>
      </dependency>
      <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-guice</artifactId>
        <version>${resteasy.version}</version>
      </dependency>
      <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jackson2-provider</artifactId>
        <version>${resteasy.version}</version>
      </dependency>
      <dependency>
        <groupId>com.google.inject.extensions</groupId>
        <artifactId>guice-multibindings</artifactId>
        <version>${guice.version}</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3.2</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
          <localCheckout>true</localCheckout>
          <autoVersionSubmodules>true</autoVersionSubmodules>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-release-plugin</artifactId>
        <version>2.5.3</version>
        <configuration>
          <localCheckout>true</localCheckout>
          <autoVersionSubmodules>true</autoVersionSubmodules>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.8.3</version>
        <configuration>
          <destFile>${basedir}/target/coverage-reports/jacoco-unit.exec</destFile>
          <dataFile>${basedir}/target/coverage-reports/jacoco-unit.exec</dataFile>
          <append>true</append>
        </configuration>
        <executions>
          <execution>
            <id>agent-for-ut</id>
            <goals>
              <goal>prepare-agent</goal>
            </goals>
          </execution>
          <execution>
            <id>jacoco-site</id>
            <phase>package</phase>
            <goals>
              <goal>report</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-checkstyle-plugin</artifactId>
        <version>3.0.0</version>
        <executions>
          <execution>
            <id>validate</id>
            <phase>validate</phase>
            <configuration>
              <configLocation>google_checks.xml</configLocation>
              <encoding>UTF-8</encoding>
              <consoleOutput>true</consoleOutput>
              <failsOnError>true</failsOnError>
              <linkXRef>false</linkXRef>
            </configuration>
            <goals>
              <goal>check</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

Child pom:

<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">

    <parent>
        <groupId>com.myproject</groupId>
        <artifactId>myapp</artifactId>
    <version>1.4-SNAPSHOT</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.myproject.myapp</groupId>
    <artifactId>myChildApp</artifactId>
    <packaging>jar</packaging>
    <name>myChildApp</name>

    <dependencies>
        <dependency>
            <groupId>commons-cli</groupId>
            <artifactId>commons-cli</artifactId>
            <version>1.3.1</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jaxrs</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-guice</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jackson2-provider</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
    </dependencies>

<build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.1</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <filters>
                <filter>
                  <artifact>*:*</artifact>
                  <excludes>
                    <exclude>META-INF/*.SF</exclude>
                    <exclude>META-INF/*.DSA</exclude>
                    <exclude>META-INF/*.RSA</exclude>
                  </excludes>
                </filter>
              </filters>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                  <mainClass>com.myproject.main.mainClass</mainClass>
                </transformer>
              </transformers>
              <createDependencyReducedPom>false</createDependencyReducedPom>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

即使经过上述一组更改,我仍然看到相同的错误。

问题类似于 where the services files (used to autoregister providers) are excluded from the fat jar built with the maven-assembly-plugin. The 是使用maven-shade-plugin,它有一个转换器将所有服务文件的内容连接到一个单独的uber jar文件中。

经过几个小时的调试,我找到了问题所在。从上面的 pom 文件中可以看出,我正在为 DI 使用 Google Guice。 在使用 Guice 时,我们需要绑定 JacksonProvider,如下所示:

绑定(JacksonJsonProvider.class)

它在我的 IDE 上为我工作的原因是因为 IDE 正在从其本地存储库(类路径)加载必要的依赖项。

这解决了我的问题。