- To serialize dates as a Unix epoch time - number of millseconds since Jan 1, 1970 (UTC).
- To always use GMT as the timezone, irrespective of the default timezone on the server.
I prefer to see the dates in a string format with ISO-8601 standard. The way to handle this in Spring MVC with version 3.1 of the Spring framework is to provide a custom Jackson ObjectMapper, to handle the date serialization differently. A custom Object Mapper would be along these lines:
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig.Feature;
public class CustomObjectMapper extends ObjectMapper {
public CustomObjectMapper(){
super.configure(Feature.WRITE_DATES_AS_TIMESTAMPS, false);
}
}
Now Spring 3.1 has made it really simple to register this Custom Object Mapper with the Handler Adapters:
<mvc:annotation-driven >
<mvc:message-converters register-defaults="false">
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" >
<property name="objectMapper">
<bean class="org.bk.simplygtd.web.spring.CustomObjectMapper"/>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
Prior to Spring 3.1, a way to register this Custom Object Mapper would have been to write a custom BeanPostProcessor, to iterate through the handler adapters, find the relevant message converter(MappingJacksonHttpMessageConverter) and register the custom object mapper, something along these lines:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
public class CustomObjectMapperBeanPostProcessor implements BeanPostProcessor{
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof AnnotationMethodHandlerAdapter){
AnnotationMethodHandlerAdapter methodHandlerAdapter = (AnnotationMethodHandlerAdapter)bean;
for (HttpMessageConverter<?> messageConverter: methodHandlerAdapter.getMessageConverters()){
if (messageConverter instanceof MappingJacksonHttpMessageConverter){
((MappingJacksonHttpMessageConverter)messageConverter).setObjectMapper(new CustomObjectMapper());
}
}
}
return bean;
}
}
Now the json responses from Spring MVC should be formatted correctly in this format: 2011-12-06T00:00:00.000+0000
If the user interface is using created using Ext-JS, the model for Ext-JS can be customized to use this date format along these lines - date format of 'c' indicates that the date string should be interpreted using ISO-8601 standard:
Ext.define('CUSTOM.model.Proj',{
extend: 'Ext.data.Model',
fields:[{name:'id', type:'string'},{name:'name', type:'string'},
{name:'startDate', type:'date', dateFormat:'c'}, {name:'completedDate', type:'date', dateFormat:'c'},
{name:'isDone', type:'boolean'}, {name:'version', type:'string'}]
});
There is still one problem, when submitting this date Ext-JS still does not format the date string correctly - it would, by default, send the date without the timezone offset(eg. 2011-12-25T00:15:00), which would be interpreted by the JSON deserializer as a GMT date/time. To fix this just have this global function:
Ext.JSON.encodeDate = function(o)
{
return '"' + Ext.Date.format(o, 'c') + '"';
};
Now the dates should be correctly posted to the server with timezone offsets also eg. 2011-12-25T01:15:00-05:00
References:
Jackson JSON Processing: http://jackson.codehaus.org/
Jackson Date Handling FAQ: http://wiki.fasterxml.com/JacksonFAQDateHandling
Some ideas from this blog entry: http://magicmonster.com/kb/prg/java/spring/webmvc/jackson_custom.html
Date type in Ext-JS: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.Date
No comments:
Post a Comment