MessageBodyWriter not found for media type=application/json
Asked Answered
S

14

82

I am facing issues while consuming JAX-RS services as JSON.

Below I have added my code.

This is my service class:

//Sets the path to base URL + /hello
@Path("/hello") 
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class Hello {

    @GET
    @Produces("application/json")
    public Student getStudent() {

        Student s = new Student();
        s.first_name = "Test First Name !!!";
        s.last_name = "Test Last Name!!!";

        return s;
    }

Student class which I am trying to get from service:

@XmlRootElement
public class Student implements Serializable {

    public String first_name;
    public String last_name;

    public String getFirst_name() {
        return first_name;
    }

    public void setFirst_name(String first_name) {
        this.first_name = first_name;
    }

    public String getLast_name() {
        return last_name;
    }

    public void setLast_name(String last_name) {
        this.last_name = last_name;
    }

    public Student()
    {
        first_name = "Fahad";
        last_name = "Mullaji";
    }
}

Web XML on service side.

<?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"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>com.vogella.jersey.first</display-name>
    <servlet>
        <servlet-name>Jersey REST Service</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <!-- Register resources and providers under com.vogella.jersey.first package. -->
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.vogella.jersey.first</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>Jersey REST Service</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app> 

I don't know how to fix this issue. I am using SOAP UI for testing JSON response but I guess that it should not matter.

Many places I read that I need to add the code below. But I don't know where. I am not using Maven for building.

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

Server is looking for function to parse Student object to JSON but it is not able to find function or jar file for it. I have added jar of Genson, Moxy, RESTEasy and Jackson but I think that's the problem. I think I am missing mapping somewhere.

Staford answered 5/10, 2014 at 21:9 Comment(2)
How are you building?Sunnysunproof
I followed vogella.com/tutorials/REST/article.html . He has not mentioned anything about building service by MAVEN or ANT. Should i be using anything for building. Thanks for replying.Staford
T
134

I was able to fix it by install jersey-media-json-jackson

Add the dependency to pom.xml

<dependency>
  <groupId>org.glassfish.jersey.media</groupId>
  <artifactId>jersey-media-json-jackson</artifactId>
  <scope>runtime</scope>
</dependency>
Tenement answered 19/3, 2015 at 5:17 Comment(5)
Thank you! Others, don't forget to add the version.Tillford
Pick the latest version: mvnrepository.com/artifact/org.glassfish.jersey.media/…Incretion
Why did this solution work. Why should I just put this into my pom blindly.Wacky
Note that Glassfish/Payara uses MOXy as JSON serializer by default and this overwrites the default behaviorLeatri
The OP specifically said they are not using Maven. The correct answer to the question would show all the jars that are needed. And then add as an extra point for Maven users, they could use this dependency. Then also explain why these are needed, i.e. explaining about entity providers.Row
N
63

You've to create empty constructor because JAX-RS initializes the classes... Your constructor must have no arguments:

@XmlRootElement
public class Student implements Serializable {

    public String first_name;
    public String last_name;

    public String getFirst_name() {
        return first_name;
    }

    public void setFirst_name(String first_name) {
        this.first_name = first_name;
    }

    public String getLast_name() {
        return last_name;
    }

    public void setLast_name(String last_name) {
        this.last_name = last_name;
    }

    public Student()
    {
        first_name = "Fahad";
        last_name = "Mullaji";
    }


 public Student()
    {
    }
}
Nordstrom answered 17/11, 2015 at 12:11 Comment(9)
I've the same issue with my code and is resolved by adding an empty constructorNordstrom
Brilliant! Why this is not the accepted answer is beyond me.Cripps
this should be the correct answer. Anyway, do you mind explaining why we need an empty constructor here?Undistinguished
@Undistinguished I'm not 100% sure, but the way in which I think the writer prints the object is constructing it with the empty constructor and via reflection finding all method properties and calling "getX" upon them. That's why if you don't have the empty constructor it doesn't work, and if you don't have getters the property in question would not be printed.Fireplace
do we need xmlroot for json response?Piperidine
Yeah @xmlRootElement is for jsonNordstrom
In my case was not necessary the @XmlRootElement. Just an empty constructor on the main class and nested classes (properties)Gorga
This works for me without adding jersey-media-json-jacksonMnemosyne
Doesn't make any sense -1. The OP already had a no-arg constructor. It's right above the one you added.Row
K
20

I was in the same situation where
- I was not using Maven or Ant,
- I finished this Vogella tutorial on Jersey,
- and I was getting the MessageBodyWriter error when trying to use @Produces(MediaType.APPLICATION_JSON).

This answer by @peeskillet solves the problem - you have to use the Jackson *.jar files that are available from the FasterXML Jackson Download page. You'll need the core files as well as the jaxrs files.

I added them to my WebContent/WEB-INF/lib folder where I have my Jersey *.jar files per the above tutorial, and made the small change to the web.xml file below (again, as originally shared by @peeskillet):

<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
    your.other.package.here, com.fasterxml.jackson.jaxrs.json 
</param-value>

The important part being com.fasterxml.jackson.jaxrs.json.

Kaila answered 24/6, 2015 at 19:59 Comment(6)
I think I am having the same problem I need to fix but I am not sure "your.other.package.here," refers to?Stanfield
The name of the package or packages where your Java service controllers and end points are defined. For example, I could have a "login" package with a class inside that routes for logins. So "your.other.package.here" would be "login"Kaila
You sir deserve a trophy. Thank you for mentioning the part: your.other.package.here,com.fasterxml.jackson.jaxrs.json It was exactly what I was missing.Abott
thank you so much. you saved next week( I spend two days to upgrade jersey from 1 to 2 with weblogic)Wink
This is what worked for me. The code version of it is something like: ResourceConfig jerseyConfig = new ResourceConfig(); jerseyConfig.packages("com.dataminr.eawatcher", "com.fasterxml.jackson.jaxrs.json"); ServletContainer servletContainer = new ServletContainer(jerseyConfig);Pitchdark
Still struggling with a Weblogic 12.1 to 12.2 upgrade, this is exactly what I needed!Outflow
R
17

Uncommenting the below code helped

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

which was present in pom.xml in my maven based project resolved this error for me.

Rockel answered 30/9, 2015 at 5:4 Comment(1)
Minus 1 as the OP specifically says they are not using Maven.Row
S
13

Below should be in your pom.xml above other jersy/jackson dependencies. In my case it as below jersy-client dep-cy and i got MessageBodyWriter not found for media type=application/json.

<dependency>
  <groupId>org.glassfish.jersey.media</groupId>
  <artifactId>jersey-media-json-jackson</artifactId>
  <version>2.25</version>
</dependency>
Smokejumper answered 13/3, 2017 at 8:58 Comment(4)
thanks, this worked for me. after that go to project settings and select all jar files and select add to web-inf/lib folder and rebuild. (using intellij) :)Roede
Minus 1 as the OP specifically says they are not using Maven.Row
plus 1 since I had the same problem using Maven and the omilus solution solved my problemCanny
plus 1 because only this works for me.. I can re-produce the issue with jettyVersion: '9.4.30.v20200611'/'9.4.6.v20170531' and jerseyVersion = '2.28'.Metalanguage
U
9

To overcome this issue try the following. Worked for me.

Add following dependency in the pom.xml

<dependency>
  <groupId>org.glassfish.jersey.media</groupId>
  <artifactId>jersey-media-json-jackson</artifactId>
  <version>2.25</version>
</dependency>

And make sure Model class contains no arg constructor

 public Student()
    {
    }
Unify answered 26/2, 2018 at 0:23 Comment(3)
Minus 1 as the OP specifically says they are not using Maven and the OP already has a no-arg constructor.Row
This dependency solves my issue. I am using Maven.Alloway
Paul Samsotha you are wrong it has no-arg constructor if there is no other parameter constructor. you should say plus one.Saker
S
2

I think may be you should try to convert the data to json format. It can be done by using gson lib. Try something like below.

I don't know it is a best solutions or not but you could do it this way.It worked for me

example : `

@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Response info(@HeaderParam("Accept") String accept) {
    Info information = new Info();
    information.setInfo("Calc Application Info");
    System.out.println(accept);
    if (!accept.equals(MediaType.APPLICATION_JSON)) {
        return Response.status(Status.ACCEPTED).entity(information).build();
    } else {
        Gson jsonConverter = new GsonBuilder().create();
        return Response.status(Status.ACCEPTED).entity(jsonConverter.toJson(information)).build();
    }
}
Sadye answered 21/1, 2016 at 13:56 Comment(2)
While this probably works, it's not a very elegant solution. The work of converting the Java objects to JSON can be done by Jersey (that's the whole point of using such a framework), so don't do it yourself.Puce
How to return Map in Response?Maceio
O
1

In my experience this error is pretty common, for some reason jersey sometimes has problems parsing custom java types. Usually all you have to do is make sure that you respect the following 3 conditions:

  1. you have jersey-media-json-jackson in you pom.xml if using maven or added to your build path;
  2. you have an empty constructor in the data type you are trying to de-/serialize;
  3. you have the relevant annotation at the class and field level for your custom data type (xmlelement and/or jsonproperty);

However, I have ran into cases where this just was not enough. Then you can always wrap you custom data type in a GenericEntity and pass it as such to your ResponseBuilder:

GenericEntity<CustomDataType> entity = new GenericEntity<CustomDataType>(myObj) {};
return Response.status(httpCode).entity(entity).build();

This way you are trying to help jersey to find the proper/relevant serialization provider for you object. Well, sometimes this also is not enough. In my case I was trying to produce a text/plain from a custom data type. Theoretically jersey should have used the StringMessageProvider, but for some reason that I did not manage to discover it was giving me this error:

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

So what solved the problem for me was to do my own serialization with jackson's writeValueAsString(). I'm not proud of it but at the end of the day I can deliver an acceptable solution.

Oxonian answered 12/3, 2020 at 15:2 Comment(1)
Yeah this it you have an empty constructor in the data type you are trying to de-/serializeSaker
H
1

My preferred alternative to pulling in the jersey-media-json-jackson dependency other answers are mentioning is to instead register JacksonJsonProvider with your Jersey ResourceConfig:

import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import org.glassfish.jersey.server.ResourceConfig;

...

ResourceConfig myResourceConfig = new ResourceConfig();
myResourceConfig.register(JacksonJsonProvider.class);

The Javadoc on JacksonJsonProvider explains:

Basic implementation of JAX-RS abstractions (MessageBodyReader,
MessageBodyWriter) needed for binding JSON ("application/json") 
content to and from Java Objects ("POJO"s).

Actual data binding functionality is implemented by ObjectMapper:
mapper to use can be configured in multiple ways:

 By explicitly passing mapper to use in constructor
 By explictly setting mapper to use by setMapper
 By defining JAX-RS Provider that returns ObjectMappers.
 By doing none of above, in which case a default mapper instance is
    constructed (and configured if configuration methods are called)

The last method ("do nothing specific") is often good enough; explicit passing
of Mapper is simple and explicit; and Provider-based method may make sense
with Depedency Injection frameworks, or if Mapper has to be configured differently
for different media types.

Note that the default mapper instance will be automatically created if
one of explicit configuration methods (like configure)
is called: if so, Provider-based introspection is NOT used, but the
resulting Mapper is used as configured.

Note: version 1.3 added a sub-class (JacksonJaxbJsonProvider) which
is configured by default to use both Jackson and JAXB annotations for configuration
(base class when used as-is defaults to using just Jackson annotations)

(as it suggests, you can alternatively use JacksonJaxbJsonProvider).

Hickox answered 9/5, 2022 at 6:54 Comment(0)
H
0

Ensure that you have following JARS in place: 1) jackson-core-asl-1.9.13 2) jackson-jaxrs-1.9.13 3) jackson-mapper-asl-1.9.13 4) jackson-xc-1.9.13

Hodeida answered 24/4, 2020 at 9:51 Comment(0)
P
0

You have to convert the response to JSON using Gson.toJson(object).

For example:

return Response.status(Status.OK).entity(new Gson().toJson(Student)).build();
Prairie answered 4/11, 2020 at 8:7 Comment(0)
N
0

Can confirm, that I had this exact error for about a week-long, I added the dependency listed above and lombok, @Data. What this does is insert all getters, setters, empty constructor, and complete constructors. More-or-less, if you are working with a big JSON response it can cause a massive problem. Also, this ensures that the other classes that you built if objects are coming or dates are parsed correctly. LET THE COMPUTER DO THE WORK.

Nordrheinwestfalen answered 29/6, 2022 at 19:17 Comment(0)
L
0
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>3.1.0-M8</version>
</dependency>

This worked for me.

Letti answered 12/10, 2022 at 6:47 Comment(0)
E
0

Had the same issue, but nothing of the above helped.

In my case, to get rid of this error, I had to make sure that the return type of a getter method matches the declaration.

Does not work:

public class Example{
    private int id;

    public Example(){
    }

    public Integer getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

}

Does work:

public class Example{
    private int id;

    public Example(){
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

}
Epsomite answered 21/2, 2023 at 12:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.