Moxy, JSON and Jersey 2.0 does not deserialize plain String array - json

In my current setup I use Jersey 2.0 with MOXy as discribed in jersey docs. I rely completely on the
“Auto-Discoverable Features”, so I do not use any extra configuration or JAXB annotation.
My task is to deserialize an array of strings on the server side. The client is sending the JSON message:
["foo","bar"]
And on the server side the following method header should deserialize it:
#POST
#Path("/stringArray")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response stringArray(List<String> stringList) {
...
}
Problem:
The content of stringList is {null,null}, so the amount of elements is always correct, but the strings are set to null.
The same with a small wrapper class is working. Here the class:
public static class Data {
public List<String> stringList;
}
Changing methode signature to stringArray(Data data) and changing the JSON message to:
{"stringList": ["foo","bar"]}
What is the difference between the two approaches and how can I get the plain string array working?
Update:
The described problem is fixed by answer from #Blaise. But the closely related problem of serializing a List of POJOs does still not work. Message:
[org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException:
MessageBodyWriter not found for media type=application/json,
type=class java.util.ArrayList, genericType=class
java.util.ArrayList.]
The only solution I found is again using a small wrapper class containing the List...

The issue you are seeing is due to a bug in EclipseLink JAXB (MOXy):
http://bugs.eclipse.org/412336
This bug has been fixed in the EclipseLink 2.5.1 and 2.6.0 streams. You can download a nightly build starting July 5, 2013 from the following link:
http://www.eclipse.org/eclipselink/downloads/nightly.php

Related

Jersey Web Service

I am using Jersey Rest Service. I am getting clients requests in json and getting java object out of it. Everything works fine. However, is there anyway I can get the exact json that was pass from client without even converting to java object.
Issue is json request contents just two parameters and below ObjectMapper converts back to Json but with null values. To ignore, I have to put #JsonInclude(Include.NON_NULL) on each pojo class. If I can get just client json, then it would be good.
ObjectMapper mapper=new ObjectMapper();
String jsonString= mapper.writeValueAsString(body);
Keep the following in your resource method:
#Consumes("application/json")
public Response fn(String payload){} //Notice the payload of type string.
That way the payload will be just a String. I am still not sure why you want it this way, but it should work.

JSON encoding using produces={"application/json; charset=UTF-8"} and ObjectMapper

I am trying to develop a microservice using Spring MVC and Spring Boot. In my service I am giving result back as JSON encoded format. Currently I added action like:
#RequestMapping("/checkUsers")
public String checkLogin() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
List<Users> useObj = (List<Users>) userRepo.findAll();
return(mapper.writeValueAsString(useObj));
}
And now I found the other options through the following method
produces={"application/json; charset=UTF-8"}
Here I am not sure which method is properly using for encoding the data into JSON format in Spring. How can I proceed?
Why don’t you just use
ResponseEntity
And return
new ResponseEntity<String>(“your message”, HttpStatus.OK);
#RequestMapping(method = GET, value = "my/random/uri", produces = "application/json;charset=UTF-8")
Here produces attribute inside my #RequestMapping annotation is the producible media types of the mapped request. The format is a single media type or a sequence of media types, with a request only mapped if mentioned one matches one of these media types. and here, my #RequestMapping annotation is already serving my purpose of encoding.
Now somewhere from Spring Boot documentation:
Spring Boot is a brand new framework designed to simplify the bootstrapping and development of a new Spring
application. The framework takes an opinionated approach to
configuration, freeing developers from the need to define boilerplate
configuration.
Please don't kill the purpose of Spring Boot. :)
Additionally, I would suggest you use org.springframework.http.MediaType class. It has got all encoding types you'll ever require. Happy coding.
Please let me know if you face any difficulty while going with suggested approach.
If you use #RestController on your controller, all request mappings will produce application/json by default.
Also, there is no need to to the object mapping yourself, just return the object without mapping and let Spring/Jackson do its thing.
#RestController
public class UsersController {
// #RequestMapping("/checkUsers")
// There is an even simpler and more concise
#GetMapping("/checkUsers")
public List<User> checkLogin() throws JsonProcessingException {
return userRepo.findAll();
}
}

Jersey / Jackson Unsupported Media Type (for XML requests)

I have spent two days on this with no luck. I have a project that uses jersey and jackson. It was working fine with JSON requests and tried to add XML also, after adding a couple of jars, it worked also with XML.
The problem was that for requests with no parameters (neither JSON nor XML), the API was retrieving XML instead JSON (we want JSON by default).
My code for requests looks like this:
#POST
#Produces({"application/json", "application/xml"})
#Consumes({"application/json", "application/xml"})
public TokenResponse authenticateUser(Credentials credentials) {//code here}
In another post a saw that this is a Jetty bug that is resolved in version 2.16, so I decided to migrate to 2.51.1 with no luck. The JSON request works fine, but when I send the xml post (with postman) the server returns an "Unsupported Media Type" error.
I have also tried with version jersey 2.17 because it works with the same jackson libraries than 2.7 and the result is the same than before.
I am not using maven so here it is a copy of the libraries I have used for the three cases:
1.- JSON and XML works but XML is always returned by default:
2.- JSON works but XML requests returns Unsupported Media Type
3.- JSON works but XML requests returns Unsupported Media Type
Thank you in advance
Finally, instead of updating the libraries I have decided to use the version I had already and add the solution below to #Produces annotation
How to set to default to json instead of xml in jersey?
Setting a qs factor to each media type as mentioned in this answer should work. It can take values between 0 (undesirable) and 1 (highly desirable):
#Produces({ "application/json; qs=1", "application/xml; qs=.5" })
If you don't want to change every single #Produces annotation, you can use a filter to add the Accept: application/json header if it's not present.
#Provider
#PreMatching
public class DefaultAcceptHeaderFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
MultivaluedMap<String, String> headers = requestContext.getHeaders();
if (!headers.containsKey(HttpHeaders.ACCEPT)) {
headers.putSingle(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);
}
}
}
It will ensure that your resource methods will produce JSON even when the Accept header is not sent by the client.

Way to Consume Json request as Json object in Jersey Rest Service

Hi I tried googling around but cannot find solution that I want to achieve.
Example to map json to java object we do
#POST
#Consumes(application/json)
#Produces(application/json)
public Response createUpdateDeleteManualClinicalData(MyJavaPojo definedPojo) {
// this maps any json to a java object, but in my case I am dealing with generic json structure
}
What I want to achieve is Keep it as json object itself
public Response createUpdateDeleteManualClinicalData(JSONObject json)
Work around: I can get data as plain text and convert that to json. But its an overhead from my side which I want to avoid.
Edit: I am open to using any Json library like JsonNode etc... as far as I get Json object Structure directly without the overhead of String to Json from my side. This should be common usage or am I missing some core concept here.
It was a straight solution that I happened to overlooked... my bad.
Jersey is way smarter than I thought... curious to know what magic happens under the layers
#POST
#Consumes(application/json)
#Produces(application/json)
public Response createUpdateDeleteManualClinicalData(JsonNode jsonNode) {
//jsoNode body casted automatically into JsonNode
}
What is the web.xml configuration you are using? Is it something similar to here web.xml setup gists for Jersey1 and Jackson2?
If you are using the same configuration as web.xml setup gists for Jersey1 and Jackson2, then you may do as below. This is a possible alternative than using JSONObject
#POST
#Path("/sub_path2")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Map<String,Object> saveMethod( Map<String,Object> params ) throws IOException {
// Processing steps
return params;
}

REST API with JSON representations using Apache CXF without Spring

I want to support both XML and JSON representations of Resources in my REST API. I have no choice but to use CXF implementation of Jax-RS without using Spring. I am using JAXB to marshall and unmarshall objects. I have the following methods defined that return different representations of the same resource.
#GET
#Produces({MediaType.APPLICATION_XML, MediaType.WILDCARD})
#ElementClass(response = MyList.class)
public Response listXML(){
MyList list = getList();
return Response.status(
Response.Status.FOUND).
entity(list).type(MediaType.APPLICATION_XML).build();
}
#GET
#Produces({MediaType.APPLICATION_JSON})
#ElementClass(response = MyList.class)
public Response listJson(){
MyList list = getList();
return Response.status(
Response.Status.FOUND).
entity(list).type(MediaType.APPLICATION_JSON).build();
}
This works fine for the XML representation. But if I set the Accept header of my HTTP request to application/json I get the following message.
No message body writer has been found for response class MyList.
What am I missing here? The MyList class is generated by JAXB from XSDs and has all the necessary annotations Looks like I need to configure CXF to use a JSON provider. I haven't been able to find good documentation on configuring the JSON provider in the web.xml for a webapplication that doesn't use Spring. If anyone has got this work, please guide me.
I got it figured out. I needed to configure JSONProvider as one of initparams for NonSpringServlet in the deployment descriptor. This wasn't working for me before as I was missng the cxf extensions library and the jettison library. These dependencies don't get automatically pulled by maven or gradle if you only have a dependency on cxf front end jars.