【问题标题】:MessageBodyProviderNotFoundException while running jar from command line从命令行运行 jar 时出现 MessageBodyProviderNotFoundException
【发布时间】:2016-10-10 16:23:41
【问题描述】:

我正在使用 Java Jersey 框架(带有 Maven),并使用 IntelliJ 作为我的 IDE。我遇到了这个运行时异常,仅当我尝试从命令行运行代码时(使用 maven 编译然后 java -jar )而不是在 IntelliJ 中运行时发生,这很奇怪。

我有一些 Java 代码会尝试在某个远程 URL 上进行 HTTP GET 并尝试将返回的 JSON 读入一些 Lombok POJO:

String targetUrl = "some valid URL";

WebTarget webTarget = client.target(targetUrl);

Response response = webTarget.request(MediaType.APPLICATION_JSON_TYPE).get();

ParseResponse parseResponse = response.readEntity(ParseResponse.class);

我不知道为什么,但是当它到达执行“readEntity()”方法的最后一行时,我会收到以下错误:

org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=text/json; charset=utf-8

这很奇怪,因为我的 pom.xml 中肯定有 jersey-media-json-jackson 依赖项:

<dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>2.23</version>
</dependency>

这是我试图将Entity()读入的POJO类:

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class ParseResponse {

   @JsonProperty("id")
   private Integer id;

   ...Other params...
}

就像我之前提到的,奇怪的是只有当我尝试像这样在命令行上运行但在 IntelliJ 中运行时没有错误时才会发生这种情况:

mvn clean package
java -jar target/NameOfJar.jar

我在这里错过了什么明显的东西吗?我在网上看过其他有类似问题的人,但没有找到解决方案。

谢谢 是

【问题讨论】:

    标签: java json maven intellij-idea jersey


    【解决方案1】:

    如果您查看jersey-media-json-jackson jar 内部,您应该会看到一个文件

    META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable
    

    这个文件的内容应该是一个实现文件名的类的单个完全限定名,即

    org.glassfish.jersey.jackson.internal.JacksonAutoDiscoverable
    

    Jersey auto-discoverable mechanism 使用此文件自动注册功能,而无需我们显式注册它们。简而言之,它是如何工作的,所有具有应该自动注册的组件的 Jersey 模块/jar 都应该在 jar 中具有上述命名的文件,其内容是自动发现组件的名称。然后 Jersey 将使用 Service Loader pattern 加载文件中命名的类,并注册它们。

    这在创建 uber jar 时导致的问题是您只能拥有一个文件的副本,而不能有重复。那么,如果我们有多个包含上述文件的 jar 文件怎么办?那么只有其中一个文件将包含在 uber jar 中。哪一个?谁知道呢,但只有一位幸运的获胜者。所以对于其余的罐子,它们的自动发现机制永远不会启动。杰克逊功能就是这种情况,自动发现注册JacksonFeature。您可以尝试显式注册您的应用程序,您应该会看到它现在可以工作了。

    但是其他可能有这个文件的 jars/modules 呢?正是出于这个原因,在创建 uber jar 时,您应该使用maven-shade-plugin。这个插件允许您做的是组合文件的内容,以便所有可发现的内容被包含到单个文件中。下面是一个示例用法

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.3</version>
        <configuration>
            <createDependencyReducedPom>true</createDependencyReducedPom>
            <filters>
                <filter>
                    <artifact>*:*</artifact>
                    <excludes>
                        <exclude>META-INF/*.SF</exclude>
                        <exclude>META-INF/*.DSA</exclude>
                        <exclude>META-INF/*.RSA</exclude>
                    </excludes>
                </filter>
            </filters>
        </configuration>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
                <configuration>
                    <transformers>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                            <mainClass>com.example.YourApp</mainClass>
                        </transformer>
                    </transformers>
                </configuration>
            </execution>
        </executions>
    </plugin>
    

    这个例子其实取自Dropwizard's Getting Started。您可以查看它以获得进一步的解释。主要关注ServicesResorceTransformer,它是连接服务文件的部分。

    【讨论】:

      猜你喜欢
      • 2020-12-24
      • 2012-06-20
      • 2016-01-02
      • 2011-06-30
      • 1970-01-01
      • 2012-01-01
      • 2011-06-04
      相关资源
      最近更新 更多