SmartGWT RestDataSource JSON响应文本似乎不是标准响应格式

时间:2013-10-26 03:10:18

标签: json rest smartgwt

我有一个基于Web的应用程序,包含GWT 2.5.1,SmartGWT 4.0,Spring 3.2.3.Release和Hibernate 4.1。前端使用SmartGWT RestDataSource将数据传递给RESTful Web服务,这是一个Spring MVC Controller,它使用Java将数据传递到前端。

Controller经过单元测试并且运行良好,我使用GET传回JSON中的数据,控制器调用后端,获取我的数据,然后将UserEntity返回给JSON格式的RestDataSource。

错误是: [错误] [TestAdmin] - 22:01:22.432:XRP8:WARN:RestDataSource:restLoginDS:RestDataSouce transformResponse():JSON响应文本似乎不是标准响应格式。

我做了很多谷歌搜索,并在这个网站上看,我可以找到有类似问题的人,但没有好的解决方案。

这是RestDataSource:

public class LoginDataSource extends RestDataSource
{
private static LoginDataSource instance = null;

public static LoginDataSource getInstance()
{
    if (instance == null)
    {
        instance = new LoginDataSource("restLoginDS");
    }
    return instance;
}

private LoginDataSource(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; // "userId":"1",

private DataSourceTextField usernameField; // "username":"myusername",
private DataSourceTextField passwordField; // "password":"mypassword",

private DataSourceBooleanField userActiveField; // "active":true,

private DataSourceTextField fullnameField; // "fullname":"Thomas Holmes",
private DataSourceDateField birthdateField; // "birthdate":"1960-10-30",
private DataSourceTextField emailField; // "email":"myemail@test.net",
private DataSourceTextField cellPhoneField; // "cellPhone":"111-222-1234"

private DataSourceIntegerField updatedByField; // "updatedBy":1,
private DataSourceDateField updatedDateField; // "updatedDate":"2013-01-01",
private DataSourceIntegerField createdByField; // "createdBy":1,
private DataSourceDateField createdDateField; // "createdDate":"2013-01-01",

private DataSourceTextField securityQuestion1Field; // "securityQuestion1":"peanuts",
private DataSourceTextField securityAnswer1Field; // "securityAnswer1":"linus"

protected void init()
{
    System.out.println("init: START");

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

    usernameField = new DataSourceTextField(Constants.USER_USERNAME, Constants.TITLE_USER_USERNAME);
    usernameField.setCanEdit(false);

    passwordField = new DataSourceTextField(Constants.USER_PASSWORD, Constants.TITLE_USER_PASSWORD);
    passwordField.setCanEdit(false);

    userActiveField = new DataSourceBooleanField(Constants.USER_ACTIVE, Constants.TITLE_USER_ACTIVE);

    fullnameField = new DataSourceTextField(Constants.USER_FULLNAME, Constants.TITLE_USER_FULLNAME);

    birthdateField = new DataSourceDateField(Constants.USER_BIRTHDATE, Constants.TITLE_USER_BIRTHDATE);

    emailField = new DataSourceTextField(Constants.USER_EMAIL, Constants.TITLE_USER_EMAIL);

    cellPhoneField = new DataSourceTextField(Constants.USER_CELL_PHONE, Constants.TITLE_USER_CELL_PHONE);

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

    updatedByField = new DataSourceIntegerField(Constants.USER_UPDATED_BY, Constants.TITLE_USER_UPDATED_BY);
    updatedDateField = new DataSourceDateField(Constants.USER_UPDATED_DATE, Constants.TITLE_USER_UPDATED_DATE);
    createdByField = new DataSourceIntegerField(Constants.USER_CREATED_BY, Constants.TITLE_USER_CREATED_BY);
    createdDateField = new DataSourceDateField(Constants.USER_CREATED_DATE, Constants.TITLE_USER_CREATED_DATE);

    System.out.println("init: FINISH");
    setFields(userIdField, usernameField, passwordField, userActiveField, emailField, cellPhoneField,
        fullnameField, birthdateField, securityQuestion1Field, securityAnswer1Field, updatedByField,
        updatedDateField, createdByField, createdDateField);

    // setFetchDataURL(getServiceRoot() + "/userId/{id}");
    // setFetchDataURL(getServiceRoot() + "/contactId/{id}");
    setAddDataURL(getServiceRoot() + "/create");
    setUpdateDataURL(getServiceRoot() + "/update");
    setRemoveDataURL(getServiceRoot() + "/remove/{id}");
}

protected String getServiceRoot()
{
    return "rest/login/";
}

protected String getPrimaryKeyProperty()
{
    return "userId";
}

/*
 * Implementers can override this method to create a different override.
 */
@SuppressWarnings("rawtypes")
protected void postProcessTransform(DSRequest request)
{
    System.out.println("LoginDataSource: postProcessTransform: START");

    StringBuilder url = new StringBuilder(getServiceRoot());
    System.out.println("LoginDataSource: postProcessTransform: url=" + url);

    Map dataMap = request.getAttributeAsMap("data");
    System.out.println("LoginDataSource: postProcessTransform: dataMap=" + dataMap.toString());
    if (request.getOperationType() == DSOperationType.FETCH && dataMap.size() > 0)
    {
        if (dataMap.get(Constants.USER_USERNAME) != null && dataMap.get(Constants.USER_PASSWORD) != null)
        {
            url.append("user/" + dataMap.get(Constants.USER_USERNAME));
            url.append("/pwd/" + dataMap.get(Constants.USER_PASSWORD));
        }
        else if (dataMap.get(Constants.USER_USERNAME) != null && dataMap.get(Constants.USER_PASSWORD) == null)
        {
            url.append("user/" + dataMap.get(Constants.USER_USERNAME));
            url.append("/pwd/" + dataMap.get(Constants.USER_PASSWORD));
        }
        else if (dataMap.get(Constants.USER_EMAIL) != null)
        {
            url.append("email/" + dataMap.get(Constants.USER_EMAIL));
        }
    }
    System.out.println("LoginDataSource: postProcessTransform: url=" + url.toString());
    request.setActionURL(URL.encode(url.toString()));
}

@Override
protected Object transformRequest(DSRequest dsRequest)
{
    // now post process the request for our own means
    postProcessTransform(dsRequest);

    System.out.println("LoginDataSource: transformRequest: START");
    dsRequest.setContentType("application/json");
    JavaScriptObject jso = dsRequest.getData();

    String jsoText = JSON.encode(jso);
    System.out.println("LoginDataSource: transformRequest: START: jsoText=" + jsoText);

    // this code is used only when there is a password change, otherwise this will be skipped
    String userPassword = JSOHelper.getAttribute(jso, Constants.USER_NEW_PASSWORD);
    if (userPassword != null)
    {
        // This creates the new JSON attribute:
        // ... , "position":{"id":x}
        JSOHelper.setAttribute(jso, "password", userPassword);

        // remove the JSON Attribute: ... , "userPassword":"newPassword"
        JSOHelper.deleteAttribute(jso, Constants.USER_NEW_PASSWORD);
    }

    System.out.println("LoginDataSource: transformRequest: FINISH: url=" + dsRequest.getActionURL());

    String s1 = JSON.encode(jso);
    System.out.println("LoginDataSource: transformRequest: FINISH: s1=" + s1);
    return s1;
}

protected void transformResponse(DSResponse response, DSRequest request, Object jsonData)
{
    System.out.println("LoginDataSource: transformResponse: START");
    JavaScriptObject jsObj = (JavaScriptObject) jsonData;
    String jsoText1 = JSON.encode(jsObj);
    System.out.println("LoginDataSource: transformResponse: jsoText=" + jsoText1);

    System.out.println("LoginDataSource: transformResponse: jsonData=" + jsonData.getClass());

    for (String attr : response.getAttributes())
    {
        System.out.println("LoginDataSource: transformResponse: attr=" + attr + " value="
            + response.getAttribute(attr));
    }

    super.transformResponse(response, request, jsonData);
}
}

错误出现在线上: super.transformResponse(response,request,jsonData);

我知道从Controller返回的数据是JSON数据,如下所示:

{
"userId":1, 
"username":"my_username", 
"password":"my_password", 
"active":true, 
"fullname":"Thomas Holmes", 
"birthdate":"1960-10-13", 
"email":"test@test.net", 
"cellPhone":"111-222-1234", 
"updatedBy":1, 
"updatedDate":"2013-01-01", 
"createdBy":1, 
"createdDate":"2013-01-01", 
"securityQuestion1":"peanuts", 
"securityAnswer1":"linus"
}

我测试过这些名称与json数据中的数据源字段匹配。 我们应该能够通过检查上面的数据源字段来看到它。 我还使用JUnit和Jackson Mapper 2.0进行了单元测试,JSON字符串数据可用于创建UserDTO对象和UserEntity对象。

我非常了解SmartClient文档,该文档介绍了从控制器返回的数据以及它必须与所需格式匹配的方式。这是一个SmartGWT RestDataSource,我查看了看起来不错的响应。

在transformResponse代码中:

for (String attr : response.getAttributes())
{
System.out.println("transformResponse: attr=" + attr + " value="
+ response.getAttribute(attr));
}

哪个收益率:

transformResponse: jsonData=class  com.google.gwt.core.client.JavaScriptObject$
transformResponse: attr=data value=[object Object]
transformResponse: attr=startRow value=0
transformResponse: attr=status value=0
transformResponse: attr=endRow value=1
transformResponse: attr=totalRows value=1
transformResponse: attr=httpResponseCode value=200
transformResponse: attr=transactionNum value=0
transformResponse: attr=clientContext value=null
transformResponse: attr=httpHeaders value=[object Object]
transformResponse: attr=context value=[object Object]

看起来“Object jsonData”是一个JavaScriptObject。 最终,在JavascriptObject中返回的JSON,我想转换为UserDTO对象。

所以,如果我可以删除这个错误并解决这个很棒的目标。

谢谢!

UPATE

我一直在测试它,我终于有一个小测试应用程序,我认为显示Isomorphic打破了SmartGWT中的RestDataSource。我这样说是因为我的应用程序在事先工作,现在它不起作用。

我确认这一切都是100%有效的JSON数据。在网上进行各种测试。

test1.json:   {"userId":1}
test2.json:   {"userId":"1"}
test3.json:   [{"userId":1}]
test4.json:   [{"userId":"1"}]

然后我隔离到一个非常小的应用程序进行测试。这类似于SmartGWT Showcase上的内容。

public class TestApp implements EntryPoint
{
    private DataSourceIntegerField userIdField;

    public void onModuleLoad()
    {
    RestDataSource dataSource = new RestDataSource();
    dataSource.setDataFormat(DSDataFormat.JSON);
    dataSource.setDataURL("data/single_user.json");

    // set the values for the datasource
    userIdField = new DataSourceIntegerField("userId", "User Id");
    userIdField.setPrimaryKey(true);
    userIdField.setCanEdit(false);

    dataSource.setFields(userIdField);

    ListGrid grid = new ListGrid();
    grid.setDataSource(dataSource);
    grid.setWidth100();
    grid.setHeight(150);
    grid.setAutoFetchData(true);
    grid.draw();
    }
}

在每种情况下,我都会收到相同的错误消息:

[ERROR] [SoccerAdmin] - 15:20:55.945:XRP6:WARN:RestDataSource:isc_RestDataSource_0:RestDataSouce transformResponse(): JSON response text does not appear to be in standard response format.

但是,如果我从RestDataSource更改为DataSource,那么我对TransformResponse没有任何问题。

我想也许我不知道TransformResponse应该用RestDataSource做什么,但我确实阅读了SmartClient Docs以了解它的价值。

如果我找到一个很好的解决方法,那么我会发一个答案。

1 个答案:

答案 0 :(得分:0)

最终我将LoginDataSource从扩展RestDataSource更改为扩展DataSource,我的所有问题都消失了。

根据文档,我的回复数据是完整和准确的。 此外,我的实际数据是一个有效的JSON对象,并针对多个站点进行了验证。

不确定他对SmartGWT RestDataSource的错误是什么,但我觉得这是一个错误...除非他们能解释为什么不是。

希望这有助于其他人!