smartgwt restdatasource json日期验证

smartgwt restdatasource json日期验证,json,rest,date,smartgwt,Json,Rest,Date,Smartgwt,我正在使用Spring3.2MVC控制器和SpringWS创建一个RESTfulWeb服务。Spring控制器接受一个对象,正确地向数据库提交更新文件,然后将JSON返回到前端。为JSON的消息转换设置Spring上下文。我对这些进行了单元测试,所以我知道Spring控制器正在工作,并且正在相应地归档数据 当我从web服务获取数据/JSON时,会出现错误,实际上是一个警告: 10:05:08.906[ERROR[Phonebook]10:05:08.902:XRP3:WARN:RestDataS

我正在使用Spring3.2MVC控制器和SpringWS创建一个RESTfulWeb服务。Spring控制器接受一个对象,正确地向数据库提交更新文件,然后将JSON返回到前端。为JSON的消息转换设置Spring上下文。我对这些进行了单元测试,所以我知道Spring控制器正在工作,并且正在相应地归档数据

当我从web服务获取数据/JSON时,会出现错误,实际上是一个警告:

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 be a 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 be a date."}
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:105)
at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:293)
at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:547)
at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:364)
at java.lang.Thread.run(Thread.java:662)
下面是我的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 up FETCH to use GET requests
    OperationBinding fetch = new OperationBinding();
    fetch.setOperationType(DSOperationType.FETCH);
    fetch.setDataProtocol(DSProtocol.GETPARAMS);
    DSRequest fetchProps = new DSRequest();
    fetchProps.setHttpMethod("GET");
    fetch.setRequestProperties(fetchProps);

    // set up ADD to 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 up UPDATE to 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 up REMOVE to use DELETE
    OperationBinding remove = new OperationBinding();
    remove.setOperationType(DSOperationType.REMOVE);
    DSRequest removeProps = new DSRequest();
    removeProps.setHttpMethod("DELETE");
    remove.setRequestProperties(removeProps);

    // apply all the 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 the values for the 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);
    // ================================================================================

    // get the user position id which comes from the UI
    // the name of this field from the UI 'userPositionId'
    String userPositionId = JSOHelper.getAttribute(jso, Constants.USER_POSITION_ID);

    // create a small JavaScriptObject to be used for the position
    // the JSON string would look like {"id":x} x = userPositionId
    Map mapPositionId = new HashMap();
    mapPositionId.put("id", userPositionId);
    JavaScriptObject jsoPositionId = JSOHelper.convertMapToJavascriptObject(mapPositionId);

    // This creates the new JSON attribute:
    // ... , "position":{"id":x}
    JSOHelper.setAttribute(jso, "position", jsoPositionId);

    // remove the 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");
}

}
我可以确认我正在发送数据/JSON。我必须做一点小小的改变来添加一个我正在发送回来的属性。我相信这就是我们的目的。 接收更新的Spring MVC控制器如下所示:

@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;
}
<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>
我可以确认我得到了一个有效的UserDTO。当我看到你的回答时:

System.out.println("UserDataSource: transformResponse: START");
super.transformResponse(response, request, data);
System.out.println("UserDataSource: transformResponse: FINISH");
我在第一个println中得到错误,我甚至还没有做super.transformResponse。当我看到返回的数据时,这就是我返回的JSON

{
"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
}
所以。。。如何修复数据源或transformResponse以删除此警告?JSON看起来是正确的,唯一的问题是当“userBirthDate”作为一个长的负数返回时,我假定是从纪元开始的毫秒数。我是否可以在JSON/Jackson映射器中进行一些更改,以更改日期的格式

谢谢你的帮助

更新1: 下面提供的帮助非常有用,现在我知道这不是SmartGWT或RestDataSource问题,而是jackson如何在对象中转换java.util.Date。转换将日期更改为负数,并且应采用其他格式。我使用的是Spring 3.2,使用的是旧的Jackson 1.9.14。但现在,我升级到Jackson 2,我的pom.xml现在使用:

<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>

这就是迄今为止的进展

来自验证错误-defaultErrorMessage:“必须是日期”

由于birthdateField是DataSourceDateField,因此您的
UserDTO.userBirthDate
必须是
java.util.Date
或类似文件,并且具有
Date getUserBirthDate()

常量。必须将用户的出生日期设置为
“userBirthDate”

如果以上都没有问题,那是因为java.util.Date对象默认序列化为JSON。
请检查以下内容,以了解更多信息。
(不要使用静态SimpleDataFormat)

使用以下日期格式(例如-2013-05-09T00:00:00)时,SmartGWT效果最佳。
yyyy-MM-dd'HH:MM:ss

System.out.println()
不能在SmartGWT/GWT中使用,因为客户端代码转换为JavaScript并在浏览器中运行,而没有JVM


在这种情况下,您可能不需要使用
transformResponse()

谢谢您的帮助。您最初列出的假设是正确的。您提供的链接非常有用,事实证明,它是在配置Jackson2Mapper,以返回返回的日期为yyyy MM dd,而不是时间戳。所以,谢谢你的帮助,这非常有用。@tjholmes66你应该接受这个答案,所以Sithsu获得了一些声誉。
<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>
 "userBirthDate":"1966-11-03T00:00:00-0500"