Jersey Restful Web服务 - MessageBodyProviderNotFoundException

时间:2013-12-05 05:07:08

标签: jaxb jersey

我是Java Web Services的新手,我正在努力解决一个基本问题。

在找到一堆过时的例子后,我设法得到了一些使用XML的东西,但是当我要求它返回JSON时,相同的代码不会工作。

最初我认为它是一个缺少的JSON格式化程序,但是JAXB应该处理从POJO到JSON的转换,所以我不相信这就是问题。

Tomcat中抛出的错误是:

javax.servlet.ServletException: org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json, type=class resttest.model.Todo, genericType=class resttest.model.Todo

WEB.XML

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  id="WebApp_ID" version="2.5">
  <display-name>testtest</display-name>
  <servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>jersey.config.server.provider.packages</param-name>        
      <param-value>resttest.jaxb;resttest.model</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app> 

Todo.java

package resttest.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Todo {

    public Todo(){};

  private String summary;
  private String description;

  public String getSummary() {
    return summary;
  }
  public void setSummary(String summary) {
    this.summary = summary;
  }
  public String getDescription() {
    return description;
  }
  public void setDescription(String description) {
    this.description = description;
  } 
}

TodoResource.Java

package resttest.jaxb;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import resttest.model.Todo;

@Path("/todo")
public class TodoResource {

  @GET
  @Produces("application/json")
  public Todo getTodo() {
    Todo todo = new Todo();
    todo.setSummary("This is my first todo");
    todo.setDescription("This is my first todo");
    return todo;
  }

} 

为什么没有返回JSON并抛出错误的任何想法?

3 个答案:

答案 0 :(得分:0)

我自己搜索了很多回复,这就是我最终做的事情。除了TodoResource类之外,还需要一个扩展Application的类,以及下面的MOXyJsonContextResolver类等类来实现ContextResolver接口。这些有助于定义Jersey上下文以及选定的Json转换器和Json输出的可选自定义。将类放在与资源类相同的包中,Jersey会找到它。 MOXy现在是Jersey(我使用2.5.1)的默认设置,也是唯一可以在没有收到错误的情况下工作的json转换器。另外,请确保您的构建或maven pom.xml(jersey-media-moxy-2.5.1.jar)中包含MOXy jar。

注意:我的应用程序的web.xml中没有任何内容。那是在旧的文档示例中,而不是Jersey 2.5.1。

@javax.ws.rs.ApplicationPath("webresources")
public class ApplicationConfig extends Application {

public ApplicationConfig() {
    this.initMethods();
}

@Override
public Set<Class<?>> getClasses() {
    Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
    addRestResourceClasses(resources);
    return resources;
}

private void initMethods() {
    try {
        ...some classes you might need instantiated, etc, for your resource class
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private void addRestResourceClasses(Set<Class<?>> resources) {
    resources.add(MOXyJsonContextResolver.class);
}

}

这是我用来自定义Json响应的MOXyJsonContextResolver.class:

public class MOXyJsonContextResolver implements ContextResolver<MoxyJsonConfig>  {
private final MoxyJsonConfig config;

public MOXyJsonContextResolver() {

    config = new MoxyJsonConfig()
            .setAttributePrefix("")
            .setValueWrapper("value")
            .property(JAXBContextProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
}

@Override
public MoxyJsonConfig getContext(Class<?> objectType) {
    return config;
}
}

答案 1 :(得分:0)

您忘记添加属性:@XmlAccessorType(XmlAccessType.FIELD)

实施例: @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Todo { ...

答案 2 :(得分:0)

您在todo类的课程级别提到了@XmlRootElement。仅当您希望以@XmlRootElement格式生成回复时才需要xml,并且在@Path类的方法级别提供TodoResource,这是一个很好的做法。 在方法级别提及@Produces(MediaType.APPLICATION_JSON)。希望这对你有用!