从命令行运行 jar 时出现 MessageBodyProviderNotFoundException [英] MessageBodyProviderNotFoundException while running jar from command line

查看:36
本文介绍了从命令行运行 jar 时出现 MessageBodyProviderNotFoundException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using the Java Jersey framework(with Maven), and use IntelliJ as my IDE. I have encountered this runtime exception that ONLY happens when I try to run the code from the command line (using maven to compile and then java -jar ) but NOT when running within IntelliJ, which is strange.

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

I have some Java code that will try to make an HTTP GET on some remote URL and try to read the returned JSON into some 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()"方法的最后一行时,我会收到以下错误:

I am not sure why, but when it hits that last line that does the "readEntity()" method, I will get the error below:

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

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

This is strange, because I definitely have the jersey-media-json-jackson dependency specified in my pom.xml :

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

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

and this is my POJO class that I was trying to readEntity() into :

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

   @JsonProperty("id")
   private Integer id;

   ...Other params...
}

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

And like I mentioned before, it is strange that this only happens when I try to run on the command line like this but there is no error when running in IntelliJ:

mvn clean package
java -jar target/NameOfJar.jar

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

Did I miss something obvious here? I have looked at other people with similar issues like this online but haven't found a solution.

谢谢是

推荐答案

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

If you look inside the jersey-media-json-jackson jar you should see a file

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

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

The contents of this file should be a single fully qualified name of a class that implements the name of the file, namely

org.glassfish.jersey.jackson.internal.JacksonAutoDiscoverable

Jersey 自动发现机制使用此文件自动注册功能,无需我们必须明确注册它们.简而言之,它的工作原理是,所有具有应自动注册组件的 Jersey 模块/jar 都应在 jar 中具有上述命名文件,内容是可自动发现的组件的名称.Jersey 然后将使用 Service Loader 模式 加载文件中命名的类,并且注册他们.

This file is used by Jersey auto-discoverable mechanism to automatically register features without us having to explicitly register them. Briefly, how it works, is that all Jersey modules/jars that have components that should be automatically registered, should have the above named file located in the jar, with the contents being the name(s) of the auto-discoverable component. Jersey will then use the Service Loader pattern to load the classes named in the file, and register them.

这在创建 uber jar 时导致的问题是,一个文件只能有一个副本,不能有重复项.那么如果我们有多个带有上述文件的 jar 呢?那么这些文件中只有一个会包含在 uber jar 中.哪一个?谁知道呢,但幸运的赢家只有一位.因此,对于其余的 jar,它们的自动发现机制永远不会启动.这就是您的 Jackson 功能的情况,其中自动发现注册了 JacksonFeature.您可以尝试显式注册您的应用程序,您应该会看到它现在可以工作了.

The problem this causes when creating uber jars is that you can only have one copy of a file, you can't have duplicates. So what if we have multiple jars with the above file? Well only one of those files will be included in the uber jar. Which one? Who knows, but there is only one lucky winner. So for the rest of the jars, their auto-discover mechanism never kicks in. This is the case with your Jackson feature, where the auto-discoverable registers the JacksonFeature. You can try to explicitly register with your application, and you should see that it now works.

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

But what about other jars/modules that may have this file? It's for this reason that when creating uber jars, you should use the maven-shade-plugin. What this plugin allows you to do, is combine the contents of the files so that all the discoverables get included into that one single file. Below is an example usage

<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 的入门.您可以查看它以获得进一步的解释.主要关注 ServicesResorceTransformer,它是连接服务文件的部分.

This example was actually taken from Dropwizard's Getting Started. You can check it out for further explanation. The main part of concern the ServicesResorceTransformer, which is what concatenates the services files.

这篇关于从命令行运行 jar 时出现 MessageBodyProviderNotFoundException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆