I hope someone can help me as I banged my head on the wall for several days on a problem that seems simple and which has been documented in other streams on the Internet.
I use the Smart GWT client (3.0) in conjunction with the Spring 3.1 server and using JSON for communication (with Jackson API 1.9).
The problem is that when I try to save the date from my SmartGWT client and go to the server, I get the following exception:
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors Field error in object 'comment' on field 'dateAdded': rejected value [2012-06-27T10:57:47+0100]; codes [typeMismatch.comment.dateAdded,typeMismatch.dateAdded,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [comment.dateAdded,dateAdded]; arguments []; default message [dateAdded]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'dateAdded'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type java.util.Date for value '2012-06-27T10:57:47+0100'; nested exception is java.lang.IllegalArgumentException] at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:110)
I saw this problem in several other posts, but most of them are related to the fact that it did not format the date in the correct format, but I tried various formats: - yyyy-MM-dd - yyyy-MM-dd'T'HH: mm : ssZ - yyyyMMddHHmmssZ (as suggested here: http://code.google.com/p/usersapi/issues/detail?id=8 )
So, in my code, I did the following:
- Configuring CustomObjectMapper:
`public class CustomObjectMapper extends ObjectMapper {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); public CustomObjectMapper() { super(); configure(Feature.WRITE_DATES_AS_TIMESTAMPS, false); setDateFormat(formatter); getDeserializationConfig().setDateFormat(formatter); }
} `
- Spring application context:
`
<mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"> <constructor-arg ref="jaxbMarshaller" /> <property name="supportedMediaTypes" value="application/xml"/> </bean> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="objectMapper" ref="jacksonObjectMapper" /> <property name="supportedMediaTypes" value="application/json" /> </bean> </mvc:message-converters> </mvc:annotation-driven> <context:component-scan base-package="com.jpmorgan.creditriskreporting.server" /> <bean id="marshallingConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"> <constructor-arg ref="jaxbMarshaller" /> <property name="supportedMediaTypes" value="application/xml"/> </bean> <bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="supportedMediaTypes" value="application/json" /> <property name="objectMapper" ref="jacksonObjectMapper" /> </bean> <bean id="jacksonObjectMapper" class="com.jpmorgan.creditriskreporting.server.util.CustomObjectMapper" /> <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> <property name="messageConverters"> <list> <ref bean="marshallingConverter" /> <ref bean="jsonConverter" /> </list> </property> </bean>
`
`import java.util.Date;
@JsonAutoDetect public class Comment {
private int id; private String comment; private Date dateAdded; public Comment() {} public Comment(int id) { this.id = id; }
...
//@JsonSerialize(using=JsonDateSerializer.class) -- I had previously tried to use these custom Date serializer class public Date getDateAdded() { return dateAdded; } //@JsonDeserialize(using=JsonDateDeserializer.class) public void setDateAdded(Date dateAdded) { this.dateAdded = dateAdded; }
`
EDIT:
This may be a problem because when I use @RequestBody it works from my integration tests, however my abstract RestDataSource in SmartGWT only works with @ModelAttribute, so I'm not sure how to proceed.
@RequestMapping(value="/", method=RequestMethod.POST) public @ResponseBody Comment createNewComment2(@ModelAttribute Comment comment) { log.info("calling createComment with comment: {}", comment); comment.setDateAdded(new Date()); Comment added = commentDao.create(comment); log.info("created comment: {}", added); return commentDao.get(comment);
}
So, I can get the data from the server, and the date is displayed in SmartGWT in order. This is only when I do the addition of data that occurs to me. Using the Smart GWT Developer Console:
{ "dataSource":"CommentDS", "operationType":"add", "componentId":"isc_DynamicForm_1", "data":{ "userAdded":"sharper", "dateAdded":"2012-06-27T10:57:47+0100", "comment":"sample" }, "callback":{ "target":[DynamicForm ID:isc_DynamicForm_1], "methodName":"saveEditorReply" }, "showPrompt":true, "prompt":"Saving form...", "oldValues":{ }, "clientContext":{ }, "requestId":"CommentDS$6272" }
Any help on this is greatly appreciated.
Cheers, Steve