24

i configure my messageconverter as Jackson's then

class Foo{int x; int y}

and in controller

@ResponseBody
public Foo method(){
   return new Foo(3,4)
}

from that i m expecting to return a JSON string {x:'3',y:'4'} from server without any other configuration. but getting 404 error response to my ajax request

If the method is annotated with @ResponseBody, the return type is written to the response HTTP body. The return value will be converted to the declared method argument type using HttpMessageConverters.

Am I wrong ? or should I convert my response Object to Json string myself using serializer and then returning that string as response.(I could make string responses correctly) or should I make some other configurations ? like adding annotations for class Foo

here is my conf.xml

<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">

  <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
  <list>
    <ref bean="jacksonMessageConverter"/>
  </list>
</property>

StaxMan
  • 113,358
  • 34
  • 211
  • 239
dupdup
  • 772
  • 1
  • 6
  • 14
  • good to mention I dont use views or modelmap i have a js UI – dupdup Feb 14 '10 at 10:59
  • for now im serializing my objects to string and post these strings to the client – dupdup Feb 18 '10 at 01:50
  • checkout [here](http://stackoverflow.com/questions/16909742/spring-3-2-0-web-mvc-rest-api-and-json2-post-requests-how-to-get-it-right-onc) if you are migrating to the new spring 3.2. – AmirHd Jun 05 '13 at 11:45

8 Answers8

22

You need the following:

  1. Set annotation-driven programming model: put <mvc:annotation-driven /> in spring.xml
  2. Place jaskson jar (Maven artifactId is org.codehaus.jackson:jackson-mapper-asl) in classpath.
  3. Use as the following:

    @RequestMapping(method = { RequestMethod.GET, RequestMethod.POST })
    public @ResponseBody Foo method(@Valid Request request, BindingResult result){
    return new Foo(3,4)
    }
    

This works for me.

Please note, that

  1. @ResponseBody is applied to return type, not to the method definition.
  2. You need @RequestMapping annotation, so that Spring will detect it.
uthark
  • 5,333
  • 2
  • 43
  • 59
  • 1
    The key part here, I think, is that the OP doesn't have a RequestMapping. Providing that, as you suggest, is important. – GaryF Sep 21 '10 at 16:00
  • 1
    @ResponseBody is applied to return type - this was my issue, thanks! – ebelisle Oct 11 '11 at 03:19
  • For testing your post requests with Curl or upgrading to spring 3.2 checkout [here](http://stackoverflow.com/questions/16909742/spring-3-2-0-web-mvc-rest-api-and-json2-post-requests-how-to-get-it-right-onc). – AmirHd Jun 05 '13 at 11:48
  • 2
    @ResponseBody can be placed either before or after the public identifier. In either place, it is part of the method signature, not related to the return type. (@ResponseBody is a @Target(ElementType.METHOD) annotation.) – squid314 Dec 16 '14 at 19:42
3

This worked for me:

@RequestMapping(value = "{p_LocationId}.json", method = RequestMethod.GET)
protected void getLocationAsJson(@PathVariable("p_LocationId") Integer p_LocationId,
     @RequestParam("cid") Integer p_CustomerId, HttpServletResponse response) {
        MappingJacksonHttpMessageConverter jsonConverter = 
                new MappingJacksonHttpMessageConverter();
        Location requestedLocation = new Location(p_LocationId);
        MediaType jsonMimeType = MediaType.APPLICATION_JSON;
        if (jsonConverter.canWrite(requestedLocation.getClass(), jsonMimeType)) {
        try {
            jsonConverter.write(requestedLocation, jsonMimeType,
                                   new ServletServerHttpResponse(response));
            } catch (IOException m_Ioe) {
                // TODO: announce this exception somehow
            } catch (HttpMessageNotWritableException p_Nwe) {
                // TODO: announce this exception somehow
            }
        }
}

Note that the method doesn't return anything: MappingJacksonHttpMessageConverter#write() does the magic.

Boris Brudnoy
  • 2,405
  • 18
  • 28
3

The MessageConverter interface http://static.springsource.org/spring/docs/3.0.x/javadoc-api/ defines a getSupportedMediaTypes() method, which in case of the MappingJacksonMessageCoverter returns application/json

public MappingJacksonHttpMessageConverter() {
    super(new MediaType("application", "json", DEFAULT_CHARSET));
}

I assume a Accept: application/json request header is missing.

Sven Haiges
  • 2,636
  • 5
  • 42
  • 54
2

A HTTP 404 error just means that the resource cannot be found. That can have 2 causes:

  1. Request URL is wrong (client side error or wrong URL in given link/button).
  2. Resource is not there where you expect it is (server side error).

To fix 1, ensure you're using or providing the correct request URL (casesensitive!). To fix 2, check the server startup logs for any startup errors and fix them accordingly.

This all goes beyond the as far posted code and information.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • hmm I havent think that simply. however my request handled with the method and also as i said before I could return String. And it is also ajax request may be i hould mention before. I think a spring guy will get my problem thx for your answer – dupdup Feb 14 '10 at 10:21
1

I found that I need jackson-core-asl.jar too, not only jackson-mapper-asl.jar

ricor
  • 11
  • 1
0

In addition to the answers here..

if you are using jquery on the client side, this worked for me:

Java:

@RequestMapping(value = "/ajax/search/sync") 
public ModelAndView sync(@RequestBody Foo json) {

Jquery (you need to include Douglas Crockford's json2.js to have the JSON.stringify function):

$.ajax({
    type: "post",
    url: "sync", //your valid url
    contentType: "application/json", //this is required for spring 3 - ajax to work (at least for me)
    data: JSON.stringify(jsonobject), //json object or array of json objects
    success: function(result) {
        //do nothing
    },
    error: function(){
        alert('failure');
    }
});
0

This is just a guess, but by default Jackson only auto-detects public fields (and public getters; but all setters regardless of visibility). It is possible to configure this (with version 1.5) to also auto-detect private fields if that is desired (see here for details).

StaxMan
  • 113,358
  • 34
  • 211
  • 239
0

I guess that 404 is not related to your HttpMessageConverter. I had same 404-issue and the reason was that I forgot that only requests matching <url-pattern> are sent to DispatcherServlet (I changed request mapping from *.do to *.json). Maybe this is your case also.

Aleksey Otrubennikov
  • 1,121
  • 1
  • 12
  • 26