- 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