I have about fifty controllers that use @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;
}
Some times getObject method return null
. The issues is that on client side I get empty response instead of null
.
In the initial implementation we have custom JsonView
object that works as wrapper without @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 was working fine.
I have found some solution at How do you override the null serializer in Jackson 2.0? but unfortunatly it works only for fields in the POJOs.
Have you any ideas how in it can be handled?
Thanks in advance!
This is not a trivial problem to solve.
Spring has a common pattern in which if a handler method returns null
, it is meant to indicate that the handler has already dealt with producing and writing the appropriate response content and that no further action is necessary on the front.
Spring has applied this pattern in its RequestResponseBodyMethodProcesser
(the HandlerMethodReturnValueHandler
implementation for @ResponseBody
). It checks if the return value is null
. It sets the request as handled. If the return value is not null
, it attempts to serialize it with an appropriate HttpMessageConverter
.
One option is to create your own @ResponseBodyNull
annotation and a corresponding HandlerMethodReturnValueHandler
which does the same except also handles null
. Note that you can't necessarily reuse the code from RequestResponseBodyMethodProcess
because some HttpMessageConverters
would fail trying to use null
.
Another similar option is to override RequestResponseBodyMethodProcessor
to accept null
(with the limitations stated above) and register it explicitly with your RequestMappingHandlerMapping
, overwriting the default HandlerMethodReturnValueHandler
s. You have to do this carefully (ie. register the same ones), unless you want to lose functionality.
The better solution, IMO, would be to not deal with null
in the response body. If getObject
doesn't return anything, that seems like a 404 to me. Set the appropriate response code and voila!
You can always inject the HttpServletResponse
into 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 that this had to be serialized to JSON.
You can return a ResponseEntity and specify the HTTP status to an 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);
}
}
In this way your client will be able to know when the object is null checking the response status.
If you actually need the null value returned you can configure Jackson to serialize it (code from tkuty):
<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>
I hope this help you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With