使用JSON对象数组执行Post时的MessageBodyProviderNotFoundException

时间:2013-10-03 15:00:13

标签: java json rest post jersey-2.0

我正在创建我的第一个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:找不到媒体类型= application / json的MessageBodyReader”: enter image description here

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

感谢您的时间:)

5 个答案:

答案 0 :(得分:1)

我找到了避免预期解决方案的方法。我只是使用Strings并使用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);
    }
    .....

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

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

  • MOXy - 通过MOXy的JSON绑定支持是自Jersey 2.0以来在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的媒体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
  • 球衣实体过滤-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);
}

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

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

答案 3 :(得分:1)

MessageBodyProviderNotFoundException的典型原因是您尝试序列化为JSON的类未正确形成。

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

答案 4 :(得分:0)

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

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

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