2017-06-21 241 views
0

爲了根據Accept請求頭生成XML和/或JSON響應,我在POM依賴項和Jersey模塊註冊之間掙扎。Jersey + Grizzly HTTP + Jackson(MessageBodyWriter not found for media type = application/xml)

這裏的依賴關係在POM

<properties> 
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
    <jersey.version>2.25.1</jersey.version> 
    <jackson.version>2.8.8</jackson.version> 
</properties> 

<dependencyManagement> 
    <dependencies> 
     <dependency> 
      <groupId>org.glassfish.jersey</groupId> 
      <artifactId>jersey-bom</artifactId> 
      <version>${jersey.version}</version> 
      <type>pom</type> 
      <scope>import</scope> 
     </dependency> 
    </dependencies> 
</dependencyManagement> 

<dependencies> 
    <dependency> 
     <groupId>org.glassfish.jersey.containers</groupId> 
     <artifactId>jersey-container-grizzly2-http</artifactId> 
     <version>${jersey.version}</version> 
    </dependency> 

    <dependency> 
     <groupId>org.glassfish.jersey.media</groupId> 
     <artifactId>jersey-media-jaxb</artifactId> 
     <version>${jersey.version}</version> 
    </dependency> 

    <dependency> 
     <groupId>org.glassfish.jersey.media</groupId> 
     <artifactId>jersey-media-json-jackson</artifactId> 
     <version>${jersey.version}</version> 
    </dependency> 

    <dependency> 
     <groupId>com.fasterxml.jackson.jaxrs</groupId> 
     <artifactId>jackson-jaxrs-json-provider</artifactId> 
     <version>${jackson.version}</version> 
    </dependency> 

    <dependency> 
     <groupId>com.fasterxml.jackson.module</groupId> 
     <artifactId>jackson-module-jaxb-annotations</artifactId> 
     <version>${jackson.version}</version> 
    </dependency> 

    <dependency> 
     <groupId>com.fasterxml.jackson.dataformat</groupId> 
     <artifactId>jackson-dataformat-xml</artifactId> 
     <version>${jackson.version}</version> 
    </dependency> 

    <dependency> 
     <groupId>org.codehaus.woodstox</groupId> 
     <artifactId>woodstox-core-asl</artifactId> 
     <version>4.1.2</version> 
    </dependency> 

    .... 
</dependencies> 

一個簡單註釋豆

@XmlRootElement 
public class SysInfo { 

    @XmlElement 
    private int nrOfProcessors; 

    @XmlElement 
    private long freePhysicalMemorySize; 

    @XmlElement 
    private long totalPhysicalMemorySize; 

    @XmlElement 
    private String javaHome; 
    @XmlElement 
    private String javaVersion; 

    @XmlElement 
    private String osArch; 
    @XmlElement 
    private String osName; 

    @XmlElement 
    private double processCpuLoad; 

    @XmlElement 
    private double systemCpuLoad; 


    public SysInfo() { } 

    public int getNrOfProcessors() { 
     return nrOfProcessors; 
    } 

    public void setNrOfProcessors(int nrOfProcessors) { 
     this.nrOfProcessors = nrOfProcessors; 
    } 

    public long getFreePhysicalMemorySize() { 
     return freePhysicalMemorySize; 
    } 

    public void setFreePhysicalMemorySize(long freePhysicalMemorySize) { 
     this.freePhysicalMemorySize = freePhysicalMemorySize; 
    } 

    public long getTotalPhysicalMemorySize() { 
     return totalPhysicalMemorySize; 
    } 

    public void setTotalPhysicalMemorySize(long totalPhysicalMemorySize) { 
     this.totalPhysicalMemorySize = totalPhysicalMemorySize; 
    } 

    public String getJavaHome() { 
     return javaHome; 
    } 

    public void setJavaHome(String javaHome) { 
     this.javaHome = javaHome; 
    } 

    public String getJavaVersion() { 
     return javaVersion; 
    } 

    public void setJavaVersion(String javaVersion) { 
     this.javaVersion = javaVersion; 
    } 

    public String getOsArch() { 
     return osArch; 
    } 

    public void setOsArch(String osArch) { 
     this.osArch = osArch; 
    } 

    public String getOsName() { 
     return osName; 
    } 

    public void setOsName(String osName) { 
     this.osName = osName; 
    } 

    public double getProcessCpuLoad() { 
     return processCpuLoad; 
    } 

    public void setProcessCpuLoad(double processCpuLoad) { 
     this.processCpuLoad = processCpuLoad; 
    } 

    public double getSystemCpuLoad() { 
     return systemCpuLoad; 
    } 

    public void setSystemCpuLoad(double systemCpuLoad) { 
     this.systemCpuLoad = systemCpuLoad; 
    } 
} 

的相關資源

@Path("/cat") 
public class SystemInfoResource { 

    @GET 
    @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) 
    public SysInfo fetchSystemProperties() throws Exception { 
     SysInfo result = new SysInfo(); 

     try { 
      OperatingSystemMXBean operatingSystemMXBean = 
        (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); 
      result.setProcessCpuLoad(operatingSystemMXBean.getProcessCpuLoad()); 
      result.setSystemCpuLoad(operatingSystemMXBean.getSystemCpuLoad()); 
      result.setTotalPhysicalMemorySize(operatingSystemMXBean.getTotalPhysicalMemorySize()); 
      result.setFreePhysicalMemorySize(operatingSystemMXBean.getFreePhysicalMemorySize()); 
      result.setNrOfProcessors(operatingSystemMXBean.getAvailableProcessors()); 
     } catch (Exception ignore) { 

     } 

     result.setJavaHome(System.getProperty("java.home")); 
     result.setJavaVersion(System.getProperty("java.versione")); 
     result.setOsArch(System.getProperty("os.arch")); 
     result.setOsName(System.getProperty("os.name")); 

     return result; 
    } 
} 

從配置和模塊註冊該片段

this.config = new ResourceConfig(); 
this.config.register(LoggingFeature.class); 
this.config.register(JacksonFeature.class); 

this.config.register(new JacksonObjectMapperProvider()); 
... 
this.config.register(SystemInfoResource.class); 

哪裏JacksonObjectMapperProvider是下面的類

public class JacksonObjectMapperProvider implements ContextResolver<ObjectMapper> { 

    final private ObjectMapper defaultObjectMapper; 

    public JacksonObjectMapperProvider() { 
     defaultObjectMapper = createDefaultMapper(); 
    } 

    @Override 
    public ObjectMapper getContext(Class<?> type) { 
     return defaultObjectMapper; 
    } 

    private static ObjectMapper createDefaultMapper() { 
     ObjectMapper mapper = new ObjectMapper(); 
     mapper.findAndRegisterModules(); 
     mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 
     mapper.enable(SerializationFeature.INDENT_OUTPUT); 

     return mapper; 
    } 
} 

當我打電話與接受= 「應用/ JSON的」 資源一切正常。但是當我指定Accept =「application/xml」時,灰熊迴應以下異常:

giu 21, 2017 12:09:03 PM org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor aroundWriteTo 
GRAVE: MessageBodyWriter not found for media type=application/xml;charset=UTF-8, type=class com.example.dmc.core.models.SysInfo, genericType=class com.example.dmc.core.models.SysInfo. 
2017-06-21 12:09:03 [grizzly-http-server-1] ERROR c.n.d.j.e.DefaultExceptionMapper - Error handling a request: 80fdaf04b7bfc5d1 
javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error 
     at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:90) 
     at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162) 
     at org.glassfish.jersey.logging.LoggingInterceptor.aroundWriteTo(LoggingInterceptor.java:225) 
     at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162) 
     at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1130) 
     at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:711) 
     at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:444) 
     at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:434) 
     at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:329) 
     at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) 
     at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) 
     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:267) 
     at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) 
     at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) 
     at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) 
     at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:384) 
     at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:224) 
     at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:593) 
     at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:573) 
     at java.lang.Thread.run(Unknown Source) 
Caused by: org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/xml;charset=UTF-8, type=class com.example.dmc.core.models.SysInfo, genericType=class com.example.dmc.core.models.SysInfo. 
     at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:247) 
     at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162) 
     at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:106) 
     at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162) 
     at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:86) 
     ... 21 common frames omitted 

任何幫助?

問候, 盧卡

+1

這是一個的[「它的工作在IDE中,但不是在建一個超級一罐」]的(https://開頭計算器.com/q/36687312/2587435)的問題?如果不是,我不確定有什麼問題。它看起來應該起作用。嘗試明確[註冊這兩個活頁夾](https://github.com/jersey/jersey/blob/master/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/JaxbAutoDiscoverable.java#L58 )與你的ResourceConfig –

+0

@peeskillet非常感謝你!手動註冊兩個活頁夾一切正常。如果您將您的評論發佈爲答案,我會發現並接受它。再次感謝。盧卡 –

回答

1

通常它應該只是工作,這意味着所有的JAXB支持所需要的供應商應通過auto-discovery被自動註冊。出於某種原因,自動發現不適用於您。我能想到的唯一的事情會導致它不工作,如果你明確地disable it,或者你正在建造一個超級罐子,和META-INF service files don't get included

在任何情況下,如果您想自己手動註冊供應商(否則該供應商將是registed by the AutoDiscoverable),您可以這樣做。只需註冊JaxbMessagingBinderJaxbParamConverterBinder(如實例 - 不是類)與ResourceConfig

相關問題