获取“MessageBodyWriter not found for media type=application/json”试图通过 JAX-RS Web 服务发送 JSON 对象
Posted
技术标签:
【中文标题】获取“MessageBodyWriter not found for media type=application/json”试图通过 JAX-RS Web 服务发送 JSON 对象【英文标题】:Obtaining "MessageBodyWriter not found for media type=application/json" trying to send JSON object through JAX-RS web service 【发布时间】:2014-01-12 18:26:04 【问题描述】:我正在尝试通过 JAX-RS Web 服务发送 JSON 对象。 我的文件 web.xml 是:
<servlet>
<description>JAX-RS Tools Generated - Do not modify</description>
<servlet-name>JAX-RS Servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>it.notifire</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Servlet</servlet-name>
<url-pattern>/jaxrs/*</url-pattern>
</servlet-mapping>
模拟我要发送的对象的类是:
public class GPSCoordinate
private float latitudine;
private float longitudine;
public float getLatitudine()
return latitudine;
public void setLatitudine(float latitudine)
this.latitudine = latitudine;
public float getLongitudine()
return longitudine;
public void setLongitudine(float longitudine)
this.longitudine = longitudine;
根类资源是:
@Path("position")
public class Position
@Context
private UriInfo context;
@GET
@Produces(MediaType.APPLICATION_JSON)
public GPSCoordinate gethtml()
GPSCoordinate coord = new GPSCoordinate();
coord.setLatitudine(90.45f);
coord.setLongitudine(34.56f);
return coord;
现在,当我尝试访问该服务时,我将浏览器指向以下链接
http://localhost:8080/Notifire/jaxrs/position
我收到以下错误:
消息 org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json
在我的 WEB-INF/lib 文件夹中,我有 jersey JAX-RS 实现的最新版本 (jaxrs-ri-2.5.jar) 和 jersey-json.jar 存档。
任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:尝试将Genson 添加到您的类路径中,它将自动启用 JSON 支持。
Genson 是一个用于 json 和 java/scala 的数据绑定和流媒体库。它实现了 JAX-RS 的 MessageBodyReader/Writer 扩展点,让 jersey 能够自动检测 Genson 并将其用于 Json 解析/写入。
您可以找到更多关于Gensons integration with JaxRS (jersey & cie) 的信息。
【讨论】:
它是一个json的数据绑定和流式库。它还实现了 JAX-RS 的扩展点 MessageBodyReader/Writer 并使用 Java 服务加载器机制声明其 impl,允许 jersey(和其他)自动检测 Genson 并将其用于 Json 解析/写入。 你知道如何对 XML 做同样的事情吗?我需要从技术上理解你在说什么,你能推荐一本书或教程而不是泽西的用户指南(v2.5.1)吗?当我开始阅读它时,我迷路了! 如果你想生成 xml,here 是一个简单的例子,如何用球衣做到这一点。关于 Genson 是如何与球衣连接的,你可以阅读this,这是 java 提出的提供扩展点的基本机制 非常感谢。它对我有用。太棒了..很大的帮助 非常感谢。我仍然不明白为什么这有效,并且所有其他具有“自动发现功能”的库都不起作用,即使我尝试使用 maven 并自己在 web.xml 中注册类...【参考方案2】:这就是我解决问题的方法。
使用杰克逊。添加了这些罐子
将这个类添加到我的项目中。代码的关键行标记为 IMPORTANT。
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; <-- IMPORTANT
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
//@javax.ws.rs.ApplicationPath("webresources")
public class MyApplicationConfig extends Application
@Override
public Set<Class<?>> getClasses()
Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
//addRestResourceClasses(resources);
//resources.add(MultiPartFeature.class);
//resources.add(JettisonFeature.class);
return resources;
@Override
public Set<Object> getSingletons()
final Set<Object> instances = new HashSet<Object>();
instances.add(new JacksonJsonProvider()); <--------- IMPORTANT
return instances;
/**
* Do not modify addRestResourceClasses() method.
* It is automatically populated with
* all resources defined in the project.
* If required, comment out calling this method in getClasses().
*/
private void addRestResourceClasses(Set<Class<?>> resources)
//resources.add(org.glassfish.jersey.media.multipart.MultiPartProperties.Feature.MultiPartContextResolver.class);
//resources.add(org.glassfish.jersey.media.multipart.MultiPartProperties.Feature.MultiPartContextResolver.class);
【讨论】:
【参考方案3】:Jersey 支持“自动发现”功能,JSON 支持就是其中之一。为了启用它,你需要在你的路径中添加一个兼容的库,根据the docs
然而,虽然推荐的 jersey-media-json-processing
库由于某种原因在我的案例中未被识别,但 jersey-media-moxy
有:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.15</version>
</dependency>
2.15 是撰写本文时的最新版本。访问 maven central artifact page 查找当前版本。
【讨论】:
感谢您的建议。它解决了我的问题。我看到这个依赖在项目中添加了一些 org.eclipse.persistence.* 依赖。这些是必需的吗? 我浏览了代码。它使用 MOXyJsonProvider 类和该包中的其他类。所以我想这很好。 @Taher - 不客气 :) 至于依赖项 - 它们是 moxy 和 antlr 的传递依赖项 - 查看依赖项列表:mvnrepository.com/artifact/org.glassfish.jersey.media/… 查看包 org.eclipse.*,我的第一直觉告诉我,我是否添加了一些多余的 jar(这可能是 IDE 特定的,因为我使用 Eclipse 进行开发),但随后进行了一些挖掘以找到依赖项。也浏览了清除所有内容的依赖项列表。一直在尝试几件事,并找到了另一个使用 json-jackson 的替代解决方案。转到https://jersey.java.net/documentation/2.5.1/user-guide.html#json
您需要完成您的课程.... JAXB 需要它,例如:
@XmlRootElement
public class MyJaxbBean
@XmlElement(name="king")
public String name;
@XmlTransient
public int age;
// several lines removed
【讨论】:
【参考方案5】:我的根本原因略有不同。我花了一些时间调试 Jersey 源代码,结果发现由于我的 JAXB 类中缺少默认构造函数,它无法构造 JAXBContext
。它发生在搜索合适的 MessageBodyWriter 期间,但未处理异常。
这里是对应的代码sn -p (MOXyJsonProvider:324):
try
Set<Class<?>> domainClasses = getDomainClasses(genericType);
return getJAXBContext(domainClasses, annotations, mediaType, null);
catch(JAXBException e)
return null;
因此,如果您在 POM 中有 Moxy JSON 依赖项,请仔细检查您的 JAXB 类是否有效。
我正在使用的版本:Jersey 2.19、Moxy 2.6.0。
【讨论】:
【参考方案6】:使用客户端配置注册 JacksonJsonProvier 类,然后创建 Client 对象,这对我有用。下面是代码。
ClientConfig config = new ClientConfig();
config.register(JacksonJsonProvider.class);
Client client = ClientBuilder.newClient(config);
【讨论】:
我认为这是大多数情况下的问题。如果自动注册不起作用,您应该尝试手动注册。【参考方案7】:通过添加所有必需的杰克逊罐子,它对我有用。 添加了这些罐子
jackson-annotations-2.8.7.jar, jackson-core-2.8.7.jar jackson-databind-2.8.7.jar jackson-jaxrs-base-2.8.7.jar jackson-jaxrs-json-provider-2.8.3.jar jackson-module-jaxb-annotations-2.8.7.jar【讨论】:
以上是关于获取“MessageBodyWriter not found for media type=application/json”试图通过 JAX-RS Web 服务发送 JSON 对象的主要内容,如果未能解决你的问题,请参考以下文章