In my spring webapp, I have an ajax servlet that answer json (using jackson):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<context:component-scan base-package="com.myapp.ajax" />
<util:list id="messageConvertersList">
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</util:list>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters" ref="messageConvertersList" />
</bean>
<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
</mvc:interceptor>
</mvc:interceptors>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver" />
<bean id="handlerExceptionResolver" class="com.myapp.ajax.AjaxExceptionHandlerResolver">
<property name="exceptionHandler">
<bean class="com.myapp.ajax.AjaxExceptionHandler" />
</property>
<property name="messageConverters" ref="messageConvertersList" />
</bean>
I have the following ajax service:
@RequestMapping(value = "getLoggedUser")
@ResponseBody
public DtoUser getLoggedUser() {
return authenticationService.getLoggedUser();
}
When the user is logged in it returns something like:
{ userName : "jojo", email : "[email protected]", firstName : "John", lastName : "Doe" }
When the user is not logged in, the expected behavior is to return
null
But it returns an empty response which is not a valid JSON response (and additionally with a bad Content-type header)
Why is this happening ?
Do I have solutions to obtain the expected behaviour ?
When the user is not logged in, the expected behavior is to return null
That's my expected behaviour because in both Java and Javascript/JSON, null is a valid value, which have a different mean than nothing, empty or error/exception.
I would expect that Spring answer the null response instead of handling it specifically.
In that case, the expected convertion for null (Java) would be null (JSON)
My expected conversion table:
Java Exception => HTTP Error Code
null => null
empty map / object => {}
void => no response
Why is this happening ?
For Spring, a controller returning null mean "No response" and not "a response which value is null". This rule applies to all controller methods including ones with @ResponseBody annotation.
This allow to write manually to the response without having something appended to the response later:
if (mySpecialCase) {
Writer writer = response.getWriter();
writer.write("my custom response");
return null;
} else {
return myObject;
}
So when returning null Spring write nothing to the response, nor Content-type header nor body.
Do I have solutions to obtain the expected behaviour ?
I made the following dirty hack: add a filter on my ajax path that write null to the response when no response have been commited.
public class AjaxEmptyResponseFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response);
if (!response.isCommitted()) {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
Writer writer = response.getWriter();
writer.write("null");
writer.close();
response.flushBuffer();
}
}
}
This solution handle methods answering null and method answering nothing (void) the same way.
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