2016-06-09 139 views
4

我正在使用Java Jersey框架(使用Maven),並使用IntelliJ作爲我的IDE。我遇到了這種運行時異常,只有當我嘗試從命令行運行代碼(使用maven編譯,然後使用java -jar)時纔會發生,但在IntelliJ中運行時卻不是這樣,這很奇怪。MessageBodyProviderNotFoundException從命令行運行jar時

我有一些Java代碼,將努力使一個HTTP GET一些遠程URL,並嘗試讀取返回的JSON到一些龍目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指定的球衣,媒體JSON - 傑克遜依賴:

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

而這正是我試圖readEntity()到我的POJO類:

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

    @JsonProperty("id") 
    private Integer id; 

    ...Other params... 
} 

就像我之前提到的,奇怪的是,當我嘗試在命令行中運行這只是發生像這樣但在IntelliJ運行時沒有錯誤:

mvn clean package 
java -jar target/NameOfJar.jar 

我在這裏錯過了一些明顯的東西嗎?我在網上查看過類似問題的其他人,但尚未找到解決方案。

感謝 IS

回答

9

如果你看看jersey-media-json-jackson罐子裏面,你會看到一個文件

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

這個文件的內容應該是一個類的單個全名實現的名稱該文件,即

org.glassfish.jersey.jackson.internal.JacksonAutoDiscoverable 

該文件由Jersey auto-discoverable mechanism用於自動註冊功能w沒有我們必須明確註冊它們。簡而言之,它的工作原理是,所有具有應該自動註冊組件的Jersey模塊/ jar應該具有位於jar中的上述命名文件,其內容是可自動發現組件的名稱。然後澤西將使用Service Loader pattern加載文件中指定的類並註冊它們。

創建超級罐子時造成的問題是您只能擁有一個文件的副本,您不能有重複。那麼如果我們有多個包含上述文件的罐子呢?那麼這些文件中只有一個會被包含在uber jar中。哪一個?誰知道,但只有一個幸運的贏家。所以對於其餘的罐子,他們的自動發現機制從來沒有啓動。這是傑克遜功能的情況下,自動發現的登錄JacksonFeature。您可以嘗試明確註冊您的應用程序,並且您應該看到它現在可以正常工作。

但是可能有這個文件的其他罐子/模塊呢?正因爲如此,在創建超級罐子時,應該使用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,這是連接服務文件的內容。

+0

Jersey + Grizzly + Moxy,這個作品完美! – Alexandre