27

after trying to figure out what's my problem I finally decided to ask you how to solve my problem. I've seen different people with the same problem and I tried all the things they were adviced to do but nothing helped with my issue. So basically I'm having a RESTful Service which I build using Jersey. For my client I would like to return an object in JSON Format. I read through different tutorials and decided that it makes sense to use jersey-json-1.8 library. I added everything to my project as usual and tried to run it but each time I'm calling the service (via get request atm.) I'm getting HTTP Error Code 500 (internal server error) and my server responds that no message body writer could be found. If I'm returning XML it works just fine and everything is great. I also tried copying jersey-json-1.8.jar to my Tomcat lib folder because I had to do this with the mysql lib I'm using but it didn't help either. I would be really glad if you could help me out to get this stuff working! If you need any more information just leave a comment and I'll provide it as quickly as humanly possibly :)

My project setup is: 3 Different packages 1. My RESTfulServices 2. My Java Work where i handle SQL connections etc. 3. A package where I store all my models that I need to work with and that I want to return in JSON Format (in my example a route for a testdrive)

A Tomcat Webserver IDE: Eclipse I'm using Maven

No matter what or how I'm trying to return the Object it just won't work and I'm constantly getting the error message :

Mapped exception to response: 500 (Internal Server Error)
javax.ws.rs.WebApplicationException: com.sun.jersey.api.MessageException: A message body writer for Java class com.mykong.models.Teststrecke, and Java type class com.mykong.models.Teststrecke, and MIME media type application/json was not found

EDIT: Here's my JSON Service Method

@Path("/hellojson")
public class JSONService {


    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public ArrayList<Route> getJSONMsg()  
    {

        Route ts = new Route();
        ts.setId(1);
        ts.setName("HelloWorld");


        Route ts2 = new Route();
        ts2.setId(2);
        ts2.setName("HelloWorld");


        ArrayList<Route> availRoutes = new ArrayList<Route>();
        availRoutes.add(ts);
        availRoutes.add(ts2);


        return availRoutes;


    }
}
dhartwich
  • 398
  • 2
  • 6
  • 16

9 Answers9

50

Try adding Genson library to your classpath http://owlike.github.io/genson/. It is a json<>java streaming and databinding api. It integrates well with jersey, to get you running you need 0 configuration. Jersey detects that the library is in your classpath and enables json mapping by delegating to Genson.

Community
  • 1
  • 1
eugen
  • 5,856
  • 2
  • 29
  • 26
  • 4
    +1 for the solution. But I really wonder why this is not documented. I am really annoyed with jearsey for not documenting this. – Akshay Jun 05 '14 at 04:13
  • 1
    @Akshay I agree. Jersey is the first software project that truly makes me angry when I try to use it. Their documentation is terrible. The first two chapters (yes, they need "chapters"!) are on setting up Maven. – Brandon Dec 16 '14 at 00:27
  • 2
    jersey-json is not required when using genson. One may also remove @Consumes:(MediaType.APPLICATION_JSON) from method definition. – Mohit Gupta Aug 11 '17 at 20:00
16

Include this dependencies in your POM.xml and run Maven -> Update

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-json</artifactId>
    <version>1.18.1</version>
</dependency>
<dependency>
   <groupId>com.owlike</groupId>
   <artifactId>genson</artifactId>
   <version>0.99</version>
</dependency>
borchvm
  • 3,533
  • 16
  • 44
  • 45
12

Adding below dependency solved my issue. As per @eugen I tried adding Genson dependency which helped get rid of the exception, however my server was throwing 400 bad request for some reason. It seems like Genson was not able to stream the json request properly. But below dependency worked fine. Hope it helps others as this problem was driving me nuts!

<dependency>
  <groupId>com.fasterxml.jackson.jaxrs</groupId>
  <artifactId>jackson-jaxrs-json-provider</artifactId>
  <version>2.3.0</version>
</dependency>
nilesh
  • 14,131
  • 7
  • 65
  • 79
3

Moving jersey-json dependency to the top of the pom.xml solved this problem for me.

<dependencies>
  <dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-json</artifactId>
    <version>1.18.1</version>
  </dependency>

  <!-- other dependencies -->

</dependencies>
supercobra
  • 15,810
  • 9
  • 45
  • 51
2

Check under Maven Dependencies in the Package Explorer, if you don't see that or jersey-bundle-1.8.jar, then you probably have specified just jersey-server. Change the dependency in pom.xml to jersey-bundle and it should work.

Anthony
  • 1,513
  • 11
  • 17
1

Jersey 2.4: I faced this problem too and posting this incase it helps someone. I picked this up from the Jersey API Specification for JSON Integration : (https://jersey.java.net/documentation/latest/user-guide.html#json)

I used Jettison to integration with Jersey with JSON. But even after adding all the libraries I got the error: A message body writer for Java Class and MIME mediatype application/json was not found

Its all about adding the right libraries and also registering features> I added one extra library in addition to all the others that Jersey provides: jersey-media-json-jettison-2.4.jar. And added the below code to register Jettison Feature.

   public class MyApplication extends ResourceConfig{
      public MyApplication() {
          register(JettisonFeature.class);
          packages("org.XXX.XXX.XXX");   
    }
Jasmine
  • 37
  • 1
  • 6
1

This question was asked a while ago, but for those reading, note that jersey servlet container has it's own POJO mapper.

Enable it by adding the following to your web.xml

<init-param>
    <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
    <param-value>true</param-value>
</init-param>

I did notice some discrepancies in how jersey and genson map objects. For example, if a class has a field of type A which is set to an instance of B, which extends A, genson will not properly serialize B, while jersey does.

allenwoot
  • 891
  • 1
  • 8
  • 16
  • Genson can serialize it "properly", by default it uses compile time information. To use runtime information use GensonBuilder.useRuntimeType(true) see http://owlike.github.io/genson/Documentation/Configuration/ – eugen Aug 31 '14 at 00:15
  • Thanks for the info. What are the benefits of using genson over jersey's mapper? – allenwoot Aug 31 '14 at 03:55
  • First there is no jersey mapper, it's just a module that uses jackson. The main reason why people moved to it, is that it just works with jersey out of box. You should have a look at the website to see if there are features that interest you and judge by yourself of the benefits :) Quicklist: support constructors with arguments encouraging immutability, jaxb annotations, scala, implements jsr353, ser/de of polymorphic types (without loosing the concrete class in deser), great configurability and modularity to plugin new components, and others... – eugen Aug 31 '14 at 12:33
0

Remove @Produces(MediaType.APPLICATION_JSON); and use JSONLibraries.zip file to convert your data to and from JSON. It is working perfectly.The problem with above code is that it is using maven and and jackson combination. So APPLICATION_JSON cannot be found when you are using only jersey. I worked with to/from JSON conversion stuff, It gave me same error, I tried with this solution and it was working properly.

Code:

@Path("/hellojson")
public class JSONService {

    @GET
    public ArrayList<Route> getJSONMsg()  
    {

        Route ts = new Route();
        ts.setId(1);
        ts.setName("HelloWorld");

        Route ts2 = new Route();
        ts2.setId(2);
        ts2.setName("HelloWorld");

        ArrayList<Route> availRoutes = new ArrayList<Route>();
        availRoutes.add(ts);
        availRoutes.add(ts2);

        return JSONObject.fromObject(availRoutes.toString()));
    }
}
MuchMore
  • 168
  • 1
  • 4
MankitaP
  • 57
  • 1
  • 1
  • 7
0

The above issue will be solved by using the jackson library instead of the genson.

    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>1.9.0</version>
    </dependency>


    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.2</version>
    </dependency>

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

As in my case genson was giving an empty json in the response but will be fine if we are converting the json to string.But will create an undesirable output because in the response you will get a string not a json.So better to go with the jackson library which will do it very easily.

Note: Jackson will convert your response to the json only if the class is implementing the Serializable Interface.So if you are sending JSONObject, then better to send the List of JSONObject.

Prakhar Agrawal
  • 153
  • 1
  • 6