嗨,关于以下帖子 -
smartgwt listgrid RestDataSource not populating
我在尝试使用smartGWT和Spring3构建应用时遇到了问题。使用jackson将返回对象转换为json。
从spring控制器返回到客户端的json响应的错误(帖子末尾的完整堆栈跟踪):
16:52:27.094 [ERROR] [utilapp] 16:52:27.092:TMR1:WARN:RestDataSource:isc_ItemListGrid_1_0:RestDataSouce transformResponse():JSON响应文本似乎不是标准响应格式。 com.smartgwt.client.core.JsObject $ SGWT_WARN:16:52:27.092:TMR1:WARN:RestDataSource:isc_ItemListGrid_1_0:RestDataSouce transformResponse():JSON响应文本似乎不是标准响应格式。
只是想知道是否有其他人在此之前遇到过这样的错误,或者有什么暗示可能是这背后的原因非常有用。
Json响应有效负载直接从浏览器点击相应的GET方法url - {"状态":0,"数据":空,"错误":{}," endRow":0," STARTROW":0," totalRows" - 1}
尽管在控制器中设置了这些字段,但所有字段都有默认值。
已定义DSResponse POJO以使json响应与链接上描述的内容同步 - http://www.smartclient.com/smartgwt/javadoc/com/smartgwt/client/data/RestDataSource.html
Web.xml:调度程序servlet条目
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
spring-servlet.xml - (基于注释,因此没有控制器bean只映射到JacksonJsonView)
<context:component-scan base-package="com.khush.util.server.rest" />
<context:component-scan base-package="com.khush.util.server.spring" />
<context:annotation-config/>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="html" value="text/html"/>
<entry key="json" value="application/json"/>
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="prefixJson" value="true"/>
</bean>
</list>
</property>
</bean>
服务器端的Spring控制器 -
@Controller
@RequestMapping("/service*")
public class RPCListService {
@RequestMapping(value="/fetch", method=RequestMethod.POST)
public @ResponseBody DSResponse fetch(@RequestBody String json){
DSResponse dsResponse = new DSResponse();
List<Account> accounts = new ArrayList<Account>();
Account account;
for(int i = 0 ; i < 500 ; i++){
account = new Account();
account.setAccountId(i * 100L);
account.setAccountName("i " + "accountName");
account.setAccountNumber("i " + "accountNumber");
accounts.add(account);
}
dsResponse.setDate(accounts.toArray());
return response;
}
@RequestMapping(value="/get", method=RequestMethod.GET)
@ResponseBody public Object get(@RequestBody String json){
DSResponse dsResponse = new DSResponse();
List<Account> accounts = new ArrayList<Account>();
Account account;
for(int i = 0 ; i < 500 ; i++){
account = new Account();
account.setAccountId(i * 100L);
account.setAccountName("i " + "accountName");
account.setAccountNumber("i " + "accountNumber");
accounts.add(account);
}
dsResponse.setDate(accounts.toArray());
return dsResponse;
}
}
客户端的RestDataSource def -
public class AccountDataSource extends SpringJSONDataSource {
public AccountDataSource(List<DataSourceField> fields) {
super(fields);
setPrettyPrintJSON(true);
}
@Override
protected OperationBinding getFetch() {
OperationBinding fetch = new OperationBinding();
fetch.setOperationType(DSOperationType.FETCH);
fetch.setDataProtocol(DSProtocol.POSTMESSAGE);
DSRequest fetchProps = new DSRequest();
fetchProps.setHttpMethod(httpMethod);
fetch.setRequestProperties(fetchProps);
return fetch;
}
@Override
protected OperationBinding getRemove() {
// TODO Auto-generated method stub
return null;
}
@Override
protected OperationBinding getAdd() {
// TODO Auto-generated method stub
return null;
}
@Override
protected OperationBinding getUpdate() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getUpdateDataURL() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getRemoveDataURL() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getAddDataURL() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getFetchDataURL() {
return "/rest/service/fetch";
}
}
public abstract class SpringJSONDataSource extends RestDataSource {
protected final String httpMethod;
public SpringJSONDataSource(List<DataSourceField> fields){
this(fields, "POST");
}
public SpringJSONDataSource(List<DataSourceField> fields, String httpMethod) {
this.httpMethod = httpMethod;
setDataFormat(DSDataFormat.JSON);
addDataSourceFields(fields);
setOperationBindings(getFetch());
addURLs();
}
private void addURLs() {
if(getUpdateDataURL() != null)
setUpdateDataURL(getUpdateDataURL());
if(getRemoveDataURL() != null)
setRemoveDataURL(getRemoveDataURL());
if(getAddDataURL() != null)
setAddDataURL(getAddDataURL());
if(getFetchDataURL() != null)
setFetchDataURL(getFetchDataURL());
}
private void addDataSourceFields(List<DataSourceField> fields) {
for (DataSourceField dataSourceField : fields) {
addField(dataSourceField);
}
}
protected abstract OperationBinding getFetch();
protected abstract OperationBinding getRemove();
protected abstract OperationBinding getAdd();
protected abstract OperationBinding getUpdate();
public abstract String getUpdateDataURL();
public abstract String getRemoveDataURL();
public abstract String getAddDataURL();
public abstract String getFetchDataURL();
}
帐户和DSResponse对象 -
public class Account implements Serializable {
private static final long serialVersionUID = 1L;
private Long accountId;
private String accountName;
private String accountNumber;
public Account(){
}
public Account(Long accountId){
setAccountId(accountId);
}
public Long getAccountId() {
return accountId;
}
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public String getAccountNumber() {
return accountNumber;
}
public void setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
}
@Override
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("Account Id: ").append(getAccountId()).append(", ");
sb.append("Account Name: ").append(getAccountName()).append(", ");
sb.append("Account Number: ").append(getAccountNumber()).append(", ");
return sb.toString();
}
@Override
public int hashCode(){
final int prime = 31;
int result = 1;
result = prime * result + ((accountName == null) ? 0 : accountName.hashCode());
return result;
}
@Override
public boolean equals(Object obj){
if(this == obj)
return true;
if(obj == null)
return false;
if(!(obj instanceof Account))
return false;
Account other = (Account)obj;
if(accountId == null){
if(other.accountId != null)
return false;
} else if(! accountId.equals(other.accountId))
return false;
if(accountName == null){
if(other.getAccountName() != null)
return false;
}else if(! accountName.equals(other.accountName))
return false;
if(accountNumber == null){
if(other.accountNumber != null)
return false;
}else if(! accountNumber.equals(other.accountNumber))
return false;
return true;
}
}
public class DSResponse implements Serializable{
private static final long serialVersionUID = -4937262101507779477L;
public static int STATUS_FAILURE = -1;
public static int STATUS_LOGIN_INCORRECT = -5;
public static int STATUS_LOGIN_REQUIRED = -7;
public static int STATUS_LOGIN_SUCCESS = -8;
public static int STATUS_MAX_LOGIN_ATTEMPTS_EXCEEDED = -6;
public static int STATUS_SERVER_TIMEOUT = -100;
public static int STATUS_SUCCESS = 0;
public static int STATUS_TRANSPORT_ERROR = -90;
public static int STATUS_VALIDATION_ERROR = -4;
private int status;
private Integer startRow;
private Integer endRow;
private Integer totalRows;
private Object[] data;
private Map errors;
public int getStatus()
{
return status;
}
public void setStatus(int status)
{
this.status = status;
}
public Integer getStartRow()
{
return startRow;
}
public void setStartRow(Integer startRow)
{
this.startRow = startRow;
}
public Integer getEndRow()
{
return endRow;
}
public void setEndRow(Integer endRow)
{
this.endRow = endRow;
}
public Integer getTotalRows()
{
return totalRows;
}
public void setTotalRows(Integer totalRows)
{
this.totalRows = totalRows;
}
public Object[] getData()
{
return data;
}
public void setData(Object[] data)
{
this.data = data;
}
public Map getErrors()
{
return errors;
}
public void setErrors(Map errors)
{
this.errors = errors;
}
public DSResponse()
{
status = STATUS_SUCCESS;
errors = new HashMap();
startRow = 0;
endRow = 0;
totalRows = -2;
}
public DSResponse(int status)
{
this.status = status;
errors = new HashMap();
startRow = 0;
endRow = 0;
totalRows = -1;
}
}
完成堆栈跟踪:
09:24:58.896 [错误] [utilapp] 09:24:58.894:TMR0:WARN:RestDataSource:isc_AccountDataSource_0:RestDataSouce transformResponse():JSON响应文本似乎不是标准响应格式。 com.smartgwt.client.core.JsObject $ SGWT_WARN:09:24:58.894:TMR0:WARN:RestDataSource:isc_AccountDataSource_0:RestDataSouce transformResponse():JSON响应文本似乎不是标准响应格式。 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) 在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.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:338) 在com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:219) 在com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136) 在com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:571) 在com.google.gwt.dev.shell.ModuleSpace.invokeNativeVoid(ModuleSpace.java:299) 在com.google.gwt.dev.shell.JavaScriptHost.invokeNativeVoid(JavaScriptHost.java:107) at com.smartgwt.client.data.DataSource.transformResponse(DataSource.java) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在java.lang.reflect.Method.invoke(Method.java:597) 在com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103) 在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.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:338) 在com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:219) 在com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136) 在com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:571) 在com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:279) 在com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91) 在com.google.gwt.core.client.impl.Impl.apply(Impl.java) 在com.google.gwt.core.client.impl.Impl.entry0(Impl.java:242) at sun.reflect.GeneratedMethodAccessor50.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在java.lang.reflect.Method.invoke(Method.java:597) 在com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103) 在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:619)
谢谢!
答案 0 :(得分:0)
根据您的评论,您的回复中没有数据。您的回复是否与指定的格式here完全匹配?
我建议它可能不匹配,因为您的错误消息是
JSON响应文本似乎不是标准响应格式
下一步该怎么做?也许尝试将一些非常简单的对象转换为JSON以查看问题是否与您的Account对象有关?在响应中只使用一个Account对象尝试一下?或者发布您的帐户对象代码?
答案 1 :(得分:0)
通过定义一个简单的java对象(用作Spring控制器的返回类型)来实现它的排序,它实现了Serializable接口和一个名为'response'的Map类型的变量,并将json响应的内容添加到该映射作为键值配对和它奏效了。
感谢