简体   繁体   中英

Jersey Restful Web Service - MessageBodyProviderNotFoundException

I'm new to Java Web Services and I'm struggling with a basic problem.

After finding a bunch of outdated examples I managed to get something working with XML however the same code wont work when I ask it to return JSON.

Initially I thought it was a missing JSON formatter but JAXB should be taking care of the conversion from POJO to JSON so I don't believe that's the problem.

The error being thrown within Tomcat is:

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;
  }

} 

Any ideas why the JSON isn't being returned and the error thrown?

I searched a lot of the responses myself and this is what I ended up doing. In addition to your TodoResource class, you need a class that extends Application, and class such as the MOXyJsonContextResolver class below to implement the ContextResolver interface. These help define the Jersey context along with a selected Json converter and optional customizations to the Json output. Put the classes in the same package as your resource class and Jersey will find it. MOXy is now the default for Jersey (I use 2.5.1) and the only json converter that I could get working without receiving your error. Also, make sure you have the MOXy jar included in your build or maven pom.xml (jersey-media-moxy-2.5.1.jar).

Note: nothing is in my application's web.xml. That was in the older documentation examples and not needed as of 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);
}

}

And here is the MOXyJsonContextResolver.class that I used to customize the Json response:

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;
}
}

You forgot to add the attribute: @XmlAccessorType(XmlAccessType.FIELD)

Example: @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Todo { ...

You have mentioned @XmlRootElement at class level in todo class. @XmlRootElement is only required if you want to produce your response in xml format, and also provide @Path at method level in TodoResource class, its a good practice. mention @Produces(MediaType.APPLICATION_JSON) at method level. Hope this will work for you!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM