【问题标题】:MessageBodyProviderNotFoundException when executing a Post with an JSON array of objects使用 JSON 对象数组执行 Post 时出现 MessageBodyProviderNotFoundException
【发布时间】:2013-10-03 15:00:12
【问题描述】:

我正在创建我的第一个 Web 服务,所以我可能遗漏了一些非常简单的东西。 我在 Eclipse Kepler 中使用 Jersey 2.x 在 Tomcat 上没有 Maven 创建了一个 Web 服务,它适用于没有参数的“@GET”请求(从浏览器和客户端应用程序测试),但我遇到了“@POST”问题(代码如下)。这实际上是一个过滤条件非常复杂的get请求。

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String getFilteredPictures(ArrayList<FilterOption> filters)
{
    PictureProvider provider = new PictureProvider();
    ArrayList<PictureInfo> pictures;
    try
    {
        pictures = provider.getPictures(filters);
        Gson gson = new Gson();
        return gson.toJson(pictures);
    }
    catch (SQLException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return null;
    }
}

我创建了一个虚拟客户端,只是为了看看上面的方法是否有效:

HttpClient httpclient = new DefaultHttpClient();
    Gson gson = new Gson();
    HttpPost request = new HttpPost(SERVICE_URI + picturesServiceEndPoint);
     //create dummy data
    ArrayList<FilterOption> filters = new ArrayList<>();
    ArrayList<String> options = new ArrayList<>();
    options.add("Black");
    filters.add(new FilterOption("Color", options));
    StringEntity postParam = StringEntity(gson.toJson(filters), "UTF-8");
    postParam.setContentType("application/json");

    request.setEntity(postParam);
    request.setHeader("Accept", "application/json");
    try
    {
        HttpResponse response = httpclient.execute(request);
        HttpEntity entity = response.getEntity();
        if (entity != null)
        {
            //obtain results..

        }
    }
    catch (ClientProtocolException e)
    {
        e.printStackTrace();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }

当我运行客户端时,服务器会抛出以下异常“.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json”:

我怀疑问题在于它无法将 JSON 转换为我的 POJO 对象,因此我在 web.xml 中放置了一个 init 参数,但它没有效果。另外,我尝试只发送一个FilterOption对象,认为ArrayList太复杂了,但还是没有效果。

感谢您的宝贵时间:)

【问题讨论】:

  • 请附上FilterOption的代码。它有 JAXB 注释吗?
  • 不,它没有注释。
  • 阅读球衣文档第 9 章:[支持通用媒体类型表示][1]

标签: java json rest post jersey-2.0


【解决方案1】:

我找到了避免预期解决方案的方法。我只是使用字符串并使用 gson 库解析它们:

@POST
// @Consumes(MediaType.APPLICATION_JSON)
// @Produces(MediaType.APPLICATION_JSON)
public String getFilteredPictures(String jsonFilters)
{
    PictureProvider provider = new PictureProvider();
    ArrayList<PictureInfo> pictures = null;
    ArrayList<FilterOption> filters = null;
    if (jsonFilters != null)
    {
        Type collectionType = new TypeToken<ArrayList<FilterOption>>()
        {}.getType();
        filters = gson.fromJson(jsonFilters, collectionType);
    }
    .....

【讨论】:

    【解决方案2】:

    通过实现 MessageBodyWriter 和 MessageBodyReader 2 个接口,您仍然可以保留方法的签名、媒体类型,并仍然使用 GSON 来编组/解组。

    我手头没有自己项目的代码示例,但以下看起来不错: http://eclipsesource.com/blogs/2012/11/02/integrating-gson-into-a-jax-rs-based-application/

    【讨论】:

      【解决方案3】:

      Jersey JSON 支持作为一组扩展模块提供,其中每个模块都包含 Feature 的实现,需要将其注册到您的 Configurable 实例(客户端/服务器)中。有多个框架支持 JSON 处理和/或 JSON 到 Java 的绑定。下面列出的模块通过将各个 JSON 框架集成到 Jersey 中来提供对 JSON 表示的支持。目前,Jersey 集成了以下模块来提供 JSON 支持:

      • MOXy - 自 Jersey 2.0 以来,通过 MOXy 的 JSON 绑定支持是在您的 Jersey 应用程序中支持 JSON 绑定的默认和首选方式。当 JSON MOXy 模块位于类路径上时,Jersey 将自动发现该模块并通过 MOXy 在您的应用程序中无缝启用 JSON 绑定支持。 (请参阅第 4.3 节“自动发现的功能”。)
      • 用于 JSON 处理的 Java API (JSON-P)
      • 杰克逊
      • 抛弃

      有关更多信息,请阅读球衣文档的chapter 9

      莫西:

      Moxy 是 json 媒体支持的建议方法。 MOXy 媒体模块是您不需要在客户端/服务器中显式注册其功能 (MoxyJsonFeature) 的模块之一 可配置,因为当您将 jersey-media-moxy 模块添加到您的类路径时会自动发现和注册此功能.

      要将 MOXy 用作您的 JSON 提供程序,您需要将 jersey-media-moxy 模块添加到您的 pom.xml 文件中:

      <dependency>
         <groupId>org.glassfish.jersey.media</groupId>
         <artifactId>jersey-media-moxy</artifactId>
         <version>2.15</version>
      </dependency>
      

      如果您不使用 Maven,请确保拥有所有需要的依赖项。见jersey-media-moxy dependencies
      您需要将这些 jar 文件添加到您的项目中,以便通过 jersey-media-moxy 支持 json 媒体类型:

      • jersey-media-moxy-2.15.jar
      • org.eclipse.persistence.core-2.5.0-rc2.jar
      • org.eclipse.persistence.antlr-2.5.0.jar
      • org.eclipse.persistence.moxy-2.5.0.jar
      • jersey-entity-filtering-2.3.1.jar

      用法:

      一些普通的类:

      public class MyJAXBBean{
      
         private String name = "jack";
         private int id = 12;
      
         public MyJAXBBean() {
      
         }
      
         public String getName() {
             return this.name;
         }
      
         public void setName(String name) {
             this.name = name;
         }
      
         public int getId() {
             return this.id;
         }
      
         public void setId(int id) {
             this.id = id;
         }
      }
      

      还有一个用于运行球衣客户端示例的主类:

       public static void main(String[] args) {
          //ClientConfig cc = new ClientConfig().register(new JacksonFeature());
          Client client = ClientBuilder.newClient();
          WebTarget target = client.target("http://localhost:8084/myhost/test");
      
          Form form = new Form();
          form.param("x", "foo");
          form.param("y", "bar");
      
          MyJAXBBean bean;
          bean = target.request(MediaType.APPLICATION_JSON_TYPE)
                  .post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE),
                          MyJAXBBean.class);
          System.out.println(bean);
      }
      

      服务器的json响应(http://localhost:8084/myhost/test)必须是以下格式:

       {"name":"haleh", "id":3}
      

      【讨论】:

        【解决方案4】:

        MessageBodyProviderNotFoundException 的一个典型原因是您尝试序列化为 JSON 的类的格式不正确。

        就我而言,我缺少一个无参数构造函数。在我添加了一个空的无参数构造函数后,一切正常。

        【讨论】:

          【解决方案5】:

          只有告诉 JAX-RS 如何执行此操作,JAX-RS 才能将 JSON 与 FilterOption 实例相互转换。

          一种常见的方法是为此使用 JAXB:

          @XmlRootElement
          class FilterOption {
              // members, getters, setters, constructors
          }
          

          【讨论】:

          • 我添加了注释,但我得到了同样的异常:-(
          • 感谢您的回答,我确信为了启用 JSON 解析,我遗漏了一些东西。在我发现问题之前,我会手动执行解析。
          猜你喜欢
          • 1970-01-01
          • 2016-10-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-05
          • 2015-06-22
          相关资源
          最近更新 更多