【问题标题】:Gradle jar with jersey dependencies produces MessageBodyReader not found for media type=application/json具有球衣依赖关系的 Gradle jar 为 media type=application/json 生成 MessageBodyReader not found
【发布时间】:2016-03-05 12:50:39
【问题描述】:

我编写了一个 Jersey 客户端,它与 3rd 方服务通信,如果我从 Eclipse 运行它就可以工作,但如果我运行 jar,它会抛出 MessageBodyProviderNotFoundException文件。

我的 build.gradle:

// Apply the java plugin to add support for Java
apply plugin: 'java'

version = '1.0'

// In this section you declare where to find the dependencies of your project
repositories {
    jcenter()
}

//create a single Jar with all dependencies
task createJar(type: Jar) {
    manifest {
        attributes 'Implementation-Title': 'MeteorDesk Whatsapp Images Parser',  
            'Implementation-Version': version,
            'Main-Class': 'controller.ImagesParser'
    }
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    with jar
}

// In this section you declare the dependencies for your production and test code
dependencies {
    compile 'org.slf4j:slf4j-api:1.7.12'

    compile 'org.glassfish.jersey.core:jersey-client:2.22.1'
    compile 'org.glassfish.jersey.containers:jersey-container-servlet-core:2.22.1'
    compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.22.1'
    compile 'com.google.guava:guava:19.0'
    compile 'joda-time:joda-time:2.4'
}

这里有例外:

 org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json, type=class model.login.LoginResult, genericType=class model.login.LoginResult.
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:231)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1085)
    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874)
    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:808)
    at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:326)
    at org.glassfish.jersey.client.InboundJaxrsResponse$1.call(InboundJaxrsResponse.java:115)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:419)
    at org.glassfish.jersey.client.InboundJaxrsResponse.runInScopeIfPossible(InboundJaxrsResponse.java:267)
    at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:112)
    at controller.MeteorDeskService.login(MeteorDeskService.java:42)

我从遇到完全相同问题的人那里读到this post,他的解决方案是改用 Maven,所以我也尝试使用 Maven,但遇到了同样的异常。

我还可以在生成的 jar 中看到 MessageBodyReader.class。

有人知道为什么会这样吗?

【问题讨论】:

  • 我猜 META-INF/services 文件在您创建 fat jar 时会相互覆盖。 META-INF/services 文件是 Jersey 加载许多自动注册功能的方式,包括 Jackson。如果是这种情况,我想是这样,您可以将JacksonFeature 显式注册为Client。 META/services 问题的解决方案是在创建 fat jar 时使用 shade 插件。使用 shade,您可以将同名文件的内容组合在一起,这样它们就不会相互覆盖。我不确定Gradle。我真的不会用它
  • 我指的 META-INF/services 文件是 org.glassfish.jersey.internal.spi.AutoDiscoverable 文件。不同的 jar 具有相同的文件,它用于自动加载特定于该 jar 的功能。也许您可以创建一个 Gradle 任务来将文件合并为一个。我不知道该怎么做。或者像我提到的那样注册JacksonFeature。但我不确定是否还有其他功能可能会丢失。但如果你只使用客户端,我想这应该不是问题
  • @peeskillet 我花了一段时间,但最后我使用了 maven 的阴影插件,现在它可以工作了。你在同一周救了我两次,我至少欠你一杯啤酒!
  • ????干杯!您能否发布您的解决方案作为结束问题的答案,以便其他人受益。我会发布一个答案,但我希望它与阴影示例一起完成,但我没有时间。我相信你的解决方案也会节省其他人的时间:-)

标签: java gradle jersey gradle-eclipse


【解决方案1】:

正如@peeskillet 建议的那样,使用 Maven Shade 插件 就可以了,这就是我添加到 pom.xml 中的内容:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.4.3</version>
            <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>your main class here</mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

【讨论】:

    【解决方案2】:

    对于在 gradle 本身中寻找解决方案的人,请使用 Shadow plugin。 在 build.gradle 中添加以下行。

    buildscript {
            repositories {
            maven {
                url "https://plugins.gradle.org/m2/"
            }
        }
        dependencies {
            classpath "com.github.jengelman.gradle.plugins:shadow:1.2.4"
        }
    }
    apply plugin: "com.github.johnrengelman.shadow"
    
    shadowJar {
        baseName = '__Title__'
        mergeServiceFiles()    //For Merging Service Descriptor Files
    }
    

    【讨论】:

    • 谢谢,它帮助了我。以防万一其他人遇到同样的问题,我通过仅将 shadowJar { mergeServiceFiles() } 添加到 build.gradle 来解决它。看起来像插件id "com.github.johnrengelman.shadow" version "4.0.3" 没有它会以错误的方式阴影。
    • 这很有帮助!
    【解决方案3】:

    +1 啤酒给@peeskillet。与构建阴影 jar 的 JMH 性能基准的 maven 构建有相同的问题。这是 pom.xml 的相关部分:

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.2</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <finalName>${uberjar.name}</finalName>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>org.openjdk.jmh.Main</mainClass>
                                </transformer>
                            </transformers>
                            <filters>
                                <filter>
                                    <!-- Shading signed JARs will fail without this. http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar -->
                                    <artifact>*:*</artifact>
                                    <excludes>
                                        <exclude>META-INF/*.SF</exclude>
                                        <exclude>META-INF/*.DSA</exclude>
                                        <exclude>META-INF/*.RSA</exclude>
                                    </excludes>
                                </filter>
                            </filters>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
    

    【讨论】:

      猜你喜欢
      • 2014-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-02
      • 1970-01-01
      • 2013-06-21
      • 2019-04-05
      相关资源
      最近更新 更多