rest - smartgwt restdatasource json date validation -


i using spring 3.2 mvc controller , spring-ws create restful web-service. spring controller accepts object files update database correctly , returns json front-end. spring context set message converts json. have unit tests these, know spring controllers working , filing data accordingly.

the error, warning, comes when data/json web-service:

10:05:08.906[error[phonebook]10:05:08.902:xrp3:warn:restdatasource:restuserds:restuserds.userbirthdate:value:-99187200000 failed on validator  {type:"isdate",typecastvalidator:true,_generated:true,defaulterrormessage:"must date."}  com.smartgwt.client.core.jsobject$sgwt_warn:    10:05:08.902:xrp3:warn:restdatasource:restuserds:restuserds.userbirthdate: value: -99187200000 failed on validator: {type: "isdate",typecastvalidator: true,_generated: true,defaulterrormessage: "must date."} @ sun.reflect.nativeconstructoraccessorimpl.newinstance0(native method) @ sun.reflect.nativeconstructoraccessorimpl.newinstance(nativeconstructoraccessorimpl.java:39) @ sun.reflect.delegatingconstructoraccessorimpl.newinstance(delegatingconstructoraccessorimpl.java:27) @ java.lang.reflect.constructor.newinstance(constructor.java:513) @ com.google.gwt.dev.shell.methodadaptor.invoke(methodadaptor.java:105) @ com.google.gwt.dev.shell.methoddispatch.invoke(methoddispatch.java:71) @ com.google.gwt.dev.shell.oophmsessionhandler.invoke(oophmsessionhandler.java:172) @ com.google.gwt.dev.shell.browserchannelserver.reacttomessages(browserchannelserver.java:293) @ com.google.gwt.dev.shell.browserchannelserver.processconnection(browserchannelserver.java:547) @ com.google.gwt.dev.shell.browserchannelserver.run(browserchannelserver.java:364) @ java.lang.thread.run(thread.java:662) 

so, here userdatasource:

package com.opensource.restful.client.datasource;  import java.util.hashmap; import java.util.map; import com.google.gwt.core.client.javascriptobject; import com.opensource.restful.shared.constants; import com.smartgwt.client.data.dsrequest; import com.smartgwt.client.data.dsresponse; import com.smartgwt.client.data.operationbinding; import com.smartgwt.client.data.restdatasource; import com.smartgwt.client.data.fields.datasourcebooleanfield; import com.smartgwt.client.data.fields.datasourcedatefield; import com.smartgwt.client.data.fields.datasourceintegerfield; import com.smartgwt.client.data.fields.datasourcetextfield; import com.smartgwt.client.types.dsdataformat; import com.smartgwt.client.types.dsoperationtype; import com.smartgwt.client.types.dsprotocol; import com.smartgwt.client.util.jsohelper; import com.smartgwt.client.util.json;  public class userdatasource extends restdatasource { private static userdatasource instance = null;  public static userdatasource getinstance() {     if (instance == null)     {         instance = new userdatasource("restuserds");     }      return instance; }  private userdatasource(string id) {     setid(id);     setclientonly(false);      // set fetch use requests     operationbinding fetch = new operationbinding();     fetch.setoperationtype(dsoperationtype.fetch);     fetch.setdataprotocol(dsprotocol.getparams);     dsrequest fetchprops = new dsrequest();     fetchprops.sethttpmethod("get");     fetch.setrequestproperties(fetchprops);      // set add use post requests     operationbinding add = new operationbinding();     add.setoperationtype(dsoperationtype.add);     add.setdataprotocol(dsprotocol.postmessage);     // ===========================================     dsrequest addprops = new dsrequest();     addprops.sethttpmethod("post");     // addprops.setcontenttype("application/json");     add.setrequestproperties(addprops);      // set update use put     operationbinding update = new operationbinding();     update.setoperationtype(dsoperationtype.update);     update.setdataprotocol(dsprotocol.postmessage);     // ===========================================     dsrequest updateprops = new dsrequest();     updateprops.sethttpmethod("put");     // updateprops.setcontenttype("application/json");     update.setrequestproperties(updateprops);      // set remove use delete     operationbinding remove = new operationbinding();     remove.setoperationtype(dsoperationtype.remove);     dsrequest removeprops = new dsrequest();     removeprops.sethttpmethod("delete");     remove.setrequestproperties(removeprops);      // apply operational bindings     setoperationbindings(fetch, add, update, remove);      init(); }  private datasourceintegerfield useridfield; private datasourcebooleanfield useractivefield; private datasourcetextfield usernamefield; private datasourcetextfield passwordfield; private datasourcetextfield firstnamefield; private datasourcetextfield lastnamefield; private datasourcetextfield emailfield; private datasourcetextfield securityquestion1field; private datasourcetextfield securityanswer1field; private datasourcetextfield securityquestion2field; private datasourcetextfield securityanswer2field; private datasourcedatefield birthdatefield;  private datasourceintegerfield positionidfield;  protected void init() {     setdataformat(dsdataformat.json);     setjsonrecordxpath("/");      // set values datasource     useridfield = new datasourceintegerfield(constants.user_id, constants.title_user_id);     useridfield.setprimarykey(true);     useridfield.setcanedit(false);      useractivefield = new datasourcebooleanfield(constants.user_active, constants.title_user_active);      usernamefield = new datasourcetextfield(constants.user_username, constants.title_user_username);     passwordfield = new datasourcetextfield(constants.user_password, constants.title_user_password);      firstnamefield = new datasourcetextfield(constants.user_first_name, constants.title_user_first_name);     lastnamefield = new datasourcetextfield(constants.user_last_name, constants.title_user_last_name);      emailfield = new datasourcetextfield(constants.user_email, constants.title_user_email);      securityquestion1field =         new datasourcetextfield(constants.user_security_question_1, constants.title_user_security_question_1);     securityanswer1field =         new datasourcetextfield(constants.user_security_answer_1, constants.title_user_security_answer_1);     securityquestion2field =         new datasourcetextfield(constants.user_security_question_2, constants.title_user_security_question_2);     securityanswer2field =         new datasourcetextfield(constants.user_security_answer_2, constants.title_user_security_answer_2);      birthdatefield = new datasourcedatefield(constants.user_birthdate, constants.title_user_birthdate);      positionidfield = new datasourceintegerfield(constants.user_position_id, constants.title_user_position_id);     // positionactivefield = new datasourcebooleanfield(constants.user_active, constants.title_user_active);     // positioncodefield;     // positiondescriptionfield;      setfields(useridfield, useractivefield, usernamefield, passwordfield, firstnamefield, lastnamefield,         emailfield, birthdatefield, securityquestion1field, securityanswer1field, securityquestion2field,         securityanswer2field, positionidfield);      setfetchdataurl(getserviceroot() + "/userid/{id}"); // works great     setadddataurl(getserviceroot() + "/create");     setupdatedataurl(getserviceroot() + "/update");     setremovedataurl(getserviceroot() + "/remove"); // works great }  protected string getserviceroot() {     return "rest/users"; }  protected string getprimarykeyproperty() {     return "userid"; }  @override protected object transformrequest(dsrequest dsrequest) {     system.out.println("userdatasource: transformrequest: start");     dsrequest.setcontenttype("application/json");     javascriptobject jso = dsrequest.getdata();      string jsotext = json.encode(jso);      system.out.println("userdatasource: transformrequest: start: jsotext=" + jsotext);     // ================================================================================     // string strdob = jsohelper.getattribute(jso, constants.user_birthdate);     // date datedob = jsohelper.getattributeasdate(jso, constants.user_birthdate);     // jsohelper.setattribute(jso, constants.user_birthdate, datedob.gettime());     // system.out.println("userdatasource: transformrequest: start2: jsotext2=" + jsotext);     // ================================================================================      // user position id comes ui     // name of field ui 'userpositionid'     string userpositionid = jsohelper.getattribute(jso, constants.user_position_id);      // create small javascriptobject used position     // json string {"id":x} x = userpositionid     map mappositionid = new hashmap();     mappositionid.put("id", userpositionid);     javascriptobject jsopositionid = jsohelper.convertmaptojavascriptobject(mappositionid);      // creates new json attribute:     // ... , "position":{"id":x}     jsohelper.setattribute(jso, "position", jsopositionid);      // remove json attribute: ... , "userpositionid":x     jsohelper.deleteattribute(jso, constants.user_position_id);      string s1 = json.encode(jso);     system.out.println("userdatasource: transformrequest: finish: s1=" + s1);     return s1;     // return super.transformrequest(dsrequest); }  protected void transformresponse(dsresponse response, dsrequest request, object data) {     system.out.println("userdatasource: transformresponse: start");     super.transformresponse(response, request, data);     system.out.println("userdatasource: transformresponse: finish"); }  } 

i can confirm sending data/json fine. have make slight change add attribute sending back. , believe purpose of transformrequest. spring mvc controller receiving update looks like:

@requestmapping(value="/update", method=requestmethod.put,produces="application/json", headers="content-type=application/json") public @responsebody userdto updateuser(@requestbody userdto user) {     system.out.println("usercontroller: start: updateuser: user=" + user);     userentity userentity = service.update(user);     userdto userdto = mapping.mappinguser(userentity);     system.out.println("usercontroller: finish: updateuser: userdto=" + userdto);     return userdto; } 

and can confirm getting valid userdto. when @ transformresponse:

system.out.println("userdatasource: transformresponse: start"); super.transformresponse(response, request, data); system.out.println("userdatasource: transformresponse: finish"); 

i error on first println, haven't done super.transformresponse yet. when @ data coming back, json getting back.

{ "userid":1,  "useractive":true,  "position":{     "id":1,      "active":true,      "code":"admin",      "description":"administrator" },  "username":"demo",  "password":"demo",  "otherpassword":null,  "userfirstname":"demoxxx",  "userlastname":"demoxxx",  "useremail":"tom@tomholmes.netxxx",  "usersecurityquestion1":"meaning of life?xxx",  "usersecurityanswer1":"42xx",  "usersecurityquestion2":"aaaxx",  "usersecurityanswer2":"bbbxx",  "userbirthdate":-99100800000,  "contacts":[     {         "contactid":2,          "userid":1,          "prefix":"mr.",          "firstname":"updated_fn",          "middlename":null,          "lastname":"updated_ln",          "suffix":"jr.",          "address1":"123 main street",          "address2":"apt. 456",          "city":"randolph",          "state":"ma",          "zip":"12345-1234",          "companyid":0,          "enteredby":0,          "entereddate":null,          "editedby":0,          "editeddate":null,          "birthdate":null,          "emails":null,          "phones":null,          "links":null     } ],  "userpositionid":null } 

so ... how fix datasource or transformresponse remove warning? json appears correct, , issue "userbirthdate" when comes long negative number, presume milliseconds epoch. there change can make in json/jackson mapper change how dates formatted?

thanks help!

update 1: provided below helpful, , know not smartgwt or restdatasource issue , strictly how jackson converts java.util.date within object. conversion changes dates negative long number , should have format. using spring 3.2 , using old jackson 1.9.14. now, upgraded jackson 2, , pom.xml uses:

<dependency>     <groupid>com.fasterxml.jackson.core</groupid>     <artifactid>jackson-core</artifactid>     <version>2.1.4</version> </dependency> <dependency>     <groupid>com.fasterxml.jackson.core</groupid>     <artifactid>jackson-databind</artifactid>     <version>2.1.4</version> </dependency> <dependency>     <groupid>com.fasterxml.jackson.core</groupid>     <artifactid>jackson-annotations</artifactid>      <version>2.1.4</version> </dependency> 

within spring-servlext.xml:

   <context:component-scan base-package="com.opensource.restful" />  <bean id="jsonhttpmessageconverter" class="org.springframework.http.converter.json.mappingjackson2httpmessageconverter">      <property name="supportedmediatypes" value="application/json"/>         <property name="objectmapper">              <bean class="com.fasterxml.jackson.databind.objectmapper">                  <property name="dateformat">                  <bean class="java.text.simpledateformat">                  <constructor-arg type="java.lang.string" value="yyyy-mm-dd't'hh:mm:ssz"></constructor-arg>                  </bean>                  </property>              </bean>           </property> </bean>  <bean class="org.springframework.web.servlet.mvc.annotation.annotationmethodhandleradapter">   <property name="messageconverters">       <list>         <ref bean="jsonhttpmessageconverter"/>       </list>   </property> </bean>  <mvc:annotation-driven />     

i have been googling few hours , looking solution uses jackson2 mapper within spring configuration, , after make sure bean definitions correct, userbirthdate still coming negative long. sure configuration can tweaked bit way want, date comes iso format: yyyy-mm-dd't'hh:mm:ssz

thanks helping me closer.

update 2: think did it. stated, upgraded jackson2 understand part of spring 3.2, version of spring using.

the spring-servlet.xml using, , work looks like:

<context:component-scan base-package="com.opensource.restful" />  <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="dateformat">                  <bean class="java.text.simpledateformat">                  <constructor-arg type="java.lang.string" value="yyyy-mm-dd't'hh:mm:ssz"></constructor-arg>                  </bean>                  </property>              </bean>           </property>         </bean>     </mvc:message-converters> </mvc:annotation-driven>  <bean id="jsonhttpmessageconverter" class="org.springframework.http.converter.json.mappingjackson2httpmessageconverter">     <property name="supportedmediatypes" value="application/json"/> </bean>  <bean class="org.springframework.web.servlet.mvc.annotation.annotationmethodhandleradapter">   <property name="messageconverters">       <list>         <ref bean="jsonhttpmessageconverter" />       </list>   </property> </bean>   <bean id="resttemplate" class="org.springframework.web.client.resttemplate">     <property name="messageconverters">         <list>         <ref bean="jsonhttpmessageconverter" />         </list>     </property> </bean> 

i had add mappingjackson2httpmessageconverter second time because, it's referenced in resttemplate ... if define once, fine. so, maybe can me define spring-servlet.xml better.

anyway, change works , result json date comes as:

 "userbirthdate":"1966-11-03t00:00:00-0500"    

so, that's progress far.

from validation error - defaulterrormessage:"must date"

since birthdatefield datasourcedatefield, userdto.userbirthdate must java.util.date or similar , have date getuserbirthdate().
, constants.user_birthdate must set "userbirthdate".

if above alright, due default serialization of java.util.date object json.
check following additional information on that.
http://java.dzone.com/articles/how-serialize-javautildate (do not use static simpledateformat)
spring 3.1 json date format
jackson2 json iso 8601 date jodatime in spring 3.2rc1

smartgwt works best when following date format used (e.g.- 2013-05-09t00:00:00).
yyyy-mm-dd't'hh:mm:ss

system.out.println() can not used in smartgwt/gwt client side code converted javascript , run inside browser, without jvm.

you won't need use transformresponse() in case.


Comments

Popular posts from this blog

linux - xterm copying to CLIPBOARD using copy-selection causes automatic updating of CLIPBOARD upon mouse selection -

c++ - qgraphicsview horizontal scrolling always has a vertical delta -