2

I'm using spring 3.0.0.

I have an endpoint that returns an object that I want to be serialized to JSON. When the request comes in with Accept: application/json, it works correctly. The request is currently coming in with */* as the Accept value. Unfortunately I don't have control over the request, otherwise I would change that. When */* is received, it throws a HttpMediaTypeNotAcceptableException exception.

Is there a way to map this accept pattern to application/json?

This is very similar to another question, but the key difference is I need to have the Accept header be */*. Spring's Json not being resolved with appropriate response

Here's what my controller looks like:

@RequestMapping(value = "/v1/endpoint", method = RequestMethod.POST)
@ResponseBody
public EndpointResponse runEndpoint(@RequestBody String jsonData) {

    ObjectMapper mapper = new ObjectMapper();
    EndpointRequest opRequest = null;
    EndpointResponse opResponse = null;

    try {

        opRequest = mapper.readValue(jsonData, EndpointRequest.class);

        //....do stuff



    } catch (JsonParseException e) {
        return handleException(opResponse, e);
    } catch (JsonMappingException e) {
        return handleException(opResponse, e);
    } catch (IOException e) {
        return handleException(opResponse, e);
    }

    return opResponse;
}

Thanks!

Community
  • 1
  • 1
Matt Dimich
  • 81
  • 1
  • 2
  • 7
  • 1
    Have you tried adding a headers="Accept=/" argument in your runEndpoint method? Here's an example: http://krams915.blogspot.com/2011/02/spring-3-rest-web-service-provider-and.html – chris Mar 15 '11 at 23:53
  • @chris Thanks for the idea. I gave it a shot and still got the HttpMediaTypeNotAcceptableException. It makes sense though. The headers param on the @RequestMapping is for mapping the request to a specific Controller method but doesn't affect the mapping of Response converters to Accept mime types. – Matt Dimich Mar 16 '11 at 15:09

3 Answers3

2

From everything I've gathered today there are 2 options to get around this issue.

  1. Write a BeanPostProcessor that will update the supported mime types on the MappingJacksonConverter to accept /. (using the supportedMimeTypes property just doesn't work....see https://jira.springsource.org/browse/SPR-6214

  2. Here's the solution I'm going with for now. It's not pretty, but neither is setting an Accept header of / when you are expecting application/json everytime. I ended up adding the ServletResponse object to my method and using the old school way of writing directly to the output stream to bypass the message converters and get my response returned.


@RequestMapping(value = "/v1/endpoint", method = RequestMethod.POST)
public void runEndpoint(@RequestBody String jsonData,
ServletResponse response) {

    ObjectMapper mapper = new ObjectMapper();
    EndpointRequest opRequest = null;
    EnpointResponse opResponse = null;
    StringWriter sw = new StringWriter();

    try {

        opRequest = mapper.readValue(jsonData, EndpointRequest.class);

        opResponse = ...do stff...

        mapper = new ObjectMapper();

        mapper.writeValue(sw, opResponse);

        response.setContentType("application/json");
        response.getOutputStream().write(sw.toString().getBytes());

        } catch (JsonParseException e) {
        handleException(opResponse, e, response);
        } catch (JsonMappingException e) {
        handleException(opResponse, e, response);
        } catch (IOException e) {
        handleException(opResponse, e, response);
    }
}

If you have anything more elegant, I'd love to see it!

Vivin Paliath
  • 94,126
  • 40
  • 223
  • 295
Matt Dimich
  • 81
  • 1
  • 2
  • 7
1

I just ran into this same issue. I'm not sure if its more elegant but what I've chosen to do is to just return a string, and convert the object to Json myself. I decided to use Gson for the JSON library.

@Controller
public class NewAbstractController  {

   @RequestMapping(value = "/simple", method = RequestMethod.GET)
   public @ResponseBody String SayHello()
   {
       Foo foo = new Foo();
       foo.Name = "Chris";
       foo.age = 30;

       Gson gson = new Gson();
       return gson.toJson(foo);
   }

   public class Foo implements Serializable
   {
       public String Name;
       public Integer age;
   }

}
developresource
  • 422
  • 4
  • 8
0

Include these dependencies to your pom.xml

 <dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.9.3</version>
 </dependency>

 <dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.3</version>
  </dependency>
Venugopal Madathil
  • 2,031
  • 3
  • 34
  • 44