Obtaining "MessageBodyWriter not found for media type=application/json" trying to send JSON object through JAX-RS web service

60,362

Solution 1

Try adding Genson to your classpath, it will automatically enable JSON support.

Genson is a data-binding and streaming library for json and java/scala. It implements the extension points MessageBodyReader/Writer of JAX-RS, allowing jersey to automatically detect Genson and use it for Json parsing/writing.

You can find some more infos about Gensons integration with JaxRS (jersey & cie).

Solution 2

Jersey supports 'autodiscoverable' features and JSON support is one of them. In order to enable it, you need to add a compatible library to your path, according to the docs

However, while the recommended jersey-media-json-processing library has not been recognized in my case for some reason, jersey-media-moxy has:

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

2.15 has been the latest version at the time of writing. Visit the maven central artifact page to find the current version.

Solution 3

Register the JacksonJsonProvier class with the client config and then create the Client object, this worked for me. Below is the code.

    ClientConfig config = new ClientConfig();
    config.register(JacksonJsonProvider.class);
    Client client = ClientBuilder.newClient(config);

Solution 4

This is how I solved the issue.

Used Jackson. Added these jars enter image description here

Added this Class to my project. The key lines of the code are marked 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);

}

}

Solution 5

My root cause was slightly different. I spent some time debugging Jersey source code, and it turned out that it fails to construct a JAXBContext due to missing default constructor in my JAXB class. It happens during the search for a suitable MessageBodyWriter, but the exception is not handled.

Here is the corresponding code snippet (MOXyJsonProvider:324):

try {
    Set<Class<?>> domainClasses = getDomainClasses(genericType);
    return getJAXBContext(domainClasses, annotations, mediaType, null);
} catch(JAXBException e) {
    return null;
}

So, if you have the Moxy JSON dependency in POM, double-check that your JAXB classes are valid.

Versions that I'm using: Jersey 2.19, Moxy 2.6.0.

Share:
60,362
amedeo avogadro
Author by

amedeo avogadro

Updated on May 15, 2020

Comments

  • amedeo avogadro
    amedeo avogadro almost 4 years

    I am trying to send a JSON object through a JAX-RS web service. My file web.xml is:

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

    The class that models the object I want to send is:

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

    The root class resource is:

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

    Now, when i try to access the service I point my browser to the following link

    http://localhost:8080/Notifire/jaxrs/position
    

    and i get the following error:

    message org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json

    In my WEB-INF/lib folder I have the last release of jersey JAX-RS implementation (jaxrs-ri-2.5.jar) and the jersey-json.jar archive.

    Any help would be much appreciated.