【问题标题】:Obtaining "MessageBodyWriter not found for media type=application/json" trying to send JSON object through JAX-RS web service获取“MessageBodyWriter not found for media type=application/json”试图通过 JAX-RS Web 服务发送 JSON 对象
【发布时间】: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 存档。

任何帮助将不胜感激。

【问题讨论】:

    标签: java json web-services rest jax-rs


    【解决方案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 的替代解决方案。 org.glassfish.jersey.mediajersey-media-json-jackson2.17
      【解决方案4】:

      转到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

          【讨论】:

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