Spring Ajax @ResponseBody with Null Values

I have about fifty controllers that use the @ResponseBody annotation.

Like this:

@RequestMapping(value = "/someUrl.controller", method = RequestMethod.GET) public @ResponseBody Object getObject(@RequestParam("id") Long id) { Object object = provider.getObject(id); return object; } 

The getObject method returns null several times. The problems are that on the client side I get an empty response instead of null .

In the initial implementation, we have a custom JsonView object that works like a wrapper without the @ResponseBody annotation.

Like this:

 @RequestMapping(value = "/someUrl.controller", method = RequestMethod.GET) public JsonView<Object> getObject(@RequestParam("id") Long id) { Object object = provider.getObject(id); return new JsonView(object); } 

So it worked fine.

I found some solution in How do you redefine a null serializer in Jackson 2.0? but unfortunately it only works for fields in POJO.

Do you have any ideas how to work in it?

Thanks in advance!

+6
source share
3 answers

This is not a trivial problem.

Spring has a common template in which, if the handler method returns null , it should indicate that the handler has already dealt with the creation and writing of the corresponding content of the response and that no further action is required on the front panel.

Spring applied this pattern in its RequestResponseBodyMethodProcesser (implementation of HandlerMethodReturnValueHandler for @ResponseBody ). It checks if the return value is null . It sets the request as processed. If the return value is not null , it attempts to serialize it using the appropriate HttpMessageConverter .

One option is to create your own @ResponseBodyNull annotation and the corresponding HandlerMethodReturnValueHandler , which does the same thing except handles null . Note that you cannot reuse the code from RequestResponseBodyMethodProcess , because some HttpMessageConverters will not be able to use null .

Another similar option is to override RequestResponseBodyMethodProcessor to accept null (with the restrictions mentioned above) and register it explicitly with RequestMappingHandlerMapping , overwriting HandlerMethodReturnValueHandler s by default. You must do this carefully (i.e. register the same ones) if you do not want to lose functionality.

The best solution, IMO, would be to not deal with null in the response body. If getObject nothing, it seems to me 404. Set the appropriate response code and voila!

You can always introduce an HttpServletResponse in your handler method and do something like

 Object object = getObject(..); if (object == null) { response.getWriter().print("null"); // also set the content type to application/json } return object; 

Assuming you knew this should be serialized in JSON.

+6
source

You can return a ResponseEntity and indicate the HTTP status for the error when the object is null:

 @RequestMapping(value = "/someUrl.controller", method = RequestMethod.GET) public ResponseEntity<Object> getObject(@RequestParam("id") Long id) { Object object = provider.getObject(id); if (object == null ) { return new ResponseEntity<Object> (HttpStatus.BAD_REQUEST); // Or any other error status } else { return new ResponseEntity<Object> (object, HttpStatus.OK); } } 

This way, your client will be able to find out when the object has a zero response status check.

If you really need to return a null value, you can configure Jackson to serialize it ( tkuty code):

 <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper"> <bean class="com.fasterxml.jackson.databind.ObjectMapper"> <property name="serializationInclusion"> <value type="com.fasterxml.jackson.annotation.JsonInclude.Include">NON_NULL</value> </property> </bean> </property> </bean> </mvc:message-converters> </mvc:annotation-driven> 

Hope this helps you.

+2
source

Firstly, I advise you not to write like this:

 @RequestMapping(value = "/someUrl.controller", method = RequestMethod.GET) public @ResponseBody Object getObject(@RequestParam("id") Long id) { /* */ } 

Make it a standard code. try the following:

 @RequestMapping(value = "/someUrl.controller", method = RequestMethod.GET) @ResponseBody public Object getObject(@RequestParam("id") Long id) { Object object = provider.getObject(id); return object; } 

I have experience with a high-quality scanner, so you can avoid errors detected by the scanner. About your problem, you can try Transformer or addScala () to return the POJO. I ran into this problem and made a deal! Good luck.

-3
source

Source: https://habr.com/ru/post/974765/


All Articles