2

I'm writing a Java EE REST application (it runs under Glassfish 4.1) and I'm having problems reading a simple key-value JSON list. I'm trying to produce and consume a JSON using a POJO class, producing works fine, but consuming is not working. Let's get to the code. The POJO class I use for produce and consume JSON is like this:

public class Transport {
  protected Integer id;
  protected String name;
  protected Map<String, String> fields;
  // ...getters and setters...
}

The REST resource import those libraries (I've put here the relevant ones):

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;

The method who produces the JSON works fine, here it is:

@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("test")
public Response testGet() {
  Transport sct = new Transport();
  sct.setId(1);
  sct.setName("test");
  HashMap<String, String> t1 = new HashMap();
  t1.put("aaa", "bbb");
  t1.put("bbb", "ccc");
  t1.put("ccc", "ddd");
  sct.setFields(t1);
  // createOkResponse is a class method that return Response type
  return createOkResponse(sct);
}

so I correctly obtain this output:

{
  "id": 1,
  "name": "test",
  "fields": {
     "aaa": "bbb",
     "ccc": "ddd",
     "bbb": "ccc"
  }
}

The method who consume the JSON, using the same POJO:

@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("test")
public Response testPut(Transport sct) {
  Map<String, String> fields = sct.getFields();
  // this code throws a NullPointerException at fields.entrySet() 
  // because fields is always null
  //for (Entry<String, String> field : fields.entrySet()) {
  //  LOG.log(Level.INFO, "*** field: {0} = {1}", new Object[]{field.getKey(), field.getValue()});
  //}
  return createOkResponse(sct);
}

Consuming the service with the same JSON above will result in an sct object with id and name properties set, but with fields property null, so the response of the method is:

{
  "id": 1,
  "name": "test",
  "fields": null
}

it's like the {"aaa": "bbb", "ccc": "ddd", "bbb": "ccc"} JSON object is being ignored. I've tried googling around but I don't understand what is wrong with my code, and I've seen no errors or warnings in the glassfish log. Any idea? Thanks.

moretti.fabio
  • 1,128
  • 13
  • 32
  • Not 100% sure, but the problem may be with how MOXy (the default JSON provider) handles Maps. You can try to disable MOXy, so that Jersey uses Jackson, and see what happens. Try to configure the property [`jersey.config.server.disableMoxyJson`](https://jersey.java.net/apidocs/2.22/jersey/org/glassfish/jersey/server/ServerProperties.html#MOXY_JSON_FEATURE_DISABLE) to `true`. – Paul Samsotha Jun 08 '16 at 03:55
  • Hi @peeskillet, changing MOXy for Jackson do the trick, so thank you! Anyway, is there any way to read this JSON with MOXy? It seems weird to me it can produce a JSON that cannot read. – moretti.fabio Jun 08 '16 at 13:56
  • You can try [this maybe](http://stackoverflow.com/a/29324520/2587435) – Paul Samsotha Jun 08 '16 at 14:07
  • @peeskillet would you like to put your first comment as an aswer, maybe adding the link from the second comment, so I can accept it? Thanks – moretti.fabio Jun 08 '16 at 18:25

1 Answers1

2

You can use an XmlAdapter, as mentioned in this post. The problem is the way that MOXy handles Maps. It uses JAXB under the hood, which was meant to be used for XML, and XML doesn't map very well to Maps (or key/value) pairs.

For this reason, instead of using MOXy for JSON (which is the default JSON provider in Glassfish), I would recommend using Jackson. Jackson should also be included in Glassfish 4.1. But you will need to disable MOXy, so the Jackson can register itself. To disable MOXy, just set the Jersey property jersey.config.server.disableMoxyJson to true.

Community
  • 1
  • 1
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720