Grails REST Client Builder getting JSON deserialization error on processing response from Jersey web service

De openkb
Aller à : Navigation, rechercher

Sommaire

Questions

I have a Jersey web service that produces/consumes JSON, and uses Jackson for POJO serialization/deserialization. I currently have a client based on the Jersey API, and a Groovy client based on the Grails rest-client-builder plugin. While the Jersey client seems to have no problems, my Grails plugin based client is having issues deserializing the response on a post request I m working on. Based on the stack trace, it seems like it s trying to serialize the JSON in the response body to a string for some reason?

org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Can not deserialize instance of java.lang.String out of START_OBJECT token
    at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@239b0f9d; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
    at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@239b0f9d; line: 1, column: 1]
    at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readJavaType(MappingJackson2HttpMessageConverter.java:228)
    at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.read(MappingJackson2HttpMessageConverter.java:220)
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:95)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:795)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:779)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:559)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:520)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:463)

Here is the relevant code for the resource in my Jersey Service

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response addStory(Story s) {

   if (null != s) {
      //underlying DynamoDB client saves data to table
      client.insertStory(s);
      Response resp = Response.status(200).entity(s).build();
      return resp;
   }
   else{
      return Response.status(404).entity("No story data submitted").build();
   }
}

Here is the same for the Jersey API based client- working fine.

public class StoryServiceJerseyClient {
    private static final Logger logger = LogManager.getLogger(StoryServiceJerseyClient.class.getName());
    private  static Client client = ClientBuilder.newClient().register(JacksonFeature.class);
    WebTarget target = client.target("http://localhost:8080/jerseyexample/rest").path("/story");

    public Story createStory(Story s){
        Story storyPersisted = null;
        storyPersisted = target
            .request()
            .post(Entity.entity(s, MediaType.APPLICATION_JSON),
                Story.class);

        return storyPersisted;
    }
}

Now the Grails client. I should note here that the Story class referred to is not the same class as that in the service/client above . For the most part it contains the same code, and exists as a temporary workaround for something else I was checking out. But I don t think this has anything to do with the problem, because everything seems to work fine up until processing the response (so the types seem to successfully be going through serialization and converting correctly). The service saves the data sent to a DynamoDB table, and I see that happening successfully. I don t understand why it s trying to serialize the response to a String, I would think would be trying to create a JSON object since the accept type is "application/json".

def addStory(Story story){
    def restTemplate = new RestTemplate();

    //experimented with adding/removing these/the explicit restTemplate
    //but it hasn t had an effect
    restTemplate.getMessageConverters().add(new  MappingJackson2HttpMessageConverter())
    restTemplate.getMessageConverters().add(new FormHttpMessageConverter())
    restTemplate.getMessageConverters().add(new StringHttpMessageConverter())

    def rest = new RestBuilder(restTemplate)
    def resp = rest.post(STORY_RESOURCE_URI ){
        accept("application/json")
        contentType("application/json")
        body(story)
    }

    def json = resp.json
    return json
}

BuildConfig.groovy

dependencies {
    ...
    compile "com.fasterxml.jackson.core:jackson-databind:2.5.1"
    compile "com.fasterxml.jackson.core:jackson-core:2.5.1"
}

plugins {
    ...
    compile ":rest-client-builder:2.1.0"
}

I m using Grails 2.4.4, and Jersey 2.17.

  UPDATE   

One thing I m also noticing while trying to debug this- none of my references to json content type or message converters seems to make a difference. I m getting the exact same response when I change any combination of the following in the Grails client:

    • don t use RestTemplate at all
    • Use RestTemplate with Only MappingJackson2HttpMessageConverter
    • Remove accept("application/json")
    • Remove contentType("application/json")

None of this seems to matter. Regardless of what I do, the code seems to realize it s getting JSON and tries to deserialize. I m really unclear on why it s trying to deserialize to String though. There s no error visible on the server side, and since the post can d complete, I don t know if/how it s possible to inspect the response I m getting.

Answers

I got the same error in my code (grails version 2.3.11 and rest-client-builder version 2.0.0).

I upgraded the plugin version to "rest-client-builder:2.1.1" and the bug is gone.

Source

License : cc by-sa 3.0

http://stackoverflow.com/questions/29295346/grails-rest-client-builder-getting-json-deserialization-error-on-processing-resp

Related

Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Outils