gwt - 包含类型化成员的参数化 AutoBean 类型

标签 gwt autobean

问题

是否有任何方法可以使用 AutoBean 框架反序列化 JSON,以便生成的 Bean 具有影响其一个或多个成员的类型的类型参数?

背景

带有 JSON 结果的 RPC

我正在使用 GWT (RequestBuilder) 来执行 RPC 请求。返回的 JSON 负载的形式如下:

{
  "resultSet": [{...}, {...}, ...], // items requested; say, items 150-160
  "totalCount": 15330               // total matching items in DB
}

resultSet 中的对象的类型有所不同,具体取决于我调用的特定 RPC。

AutoBean接口(interface)

我想使用 AutoBean 反序列化此 JSON。我试图按如下方式表示该对象:

interface RpcResults<T> {

  List<T> getResultSet();
  void setResultSet(List<T> resultSet);

  int getTotalCount();
  void setTotalCount(int totalCount);

}

我还创建了适当的接口(interface)来表示 resultSet 中可能存在的每种类型的对象。最后,我设置了对 AutoBeanCodex.decode 的适当调用。

运行代码

尝试在开发模式下运行此代码会导致控制台中出现以下堆栈跟踪:

19:44:23.791 [ERROR] [xcbackend] Uncaught exception escaped
java.lang.IllegalArgumentException: The AutoBeanFactory cannot create a java.lang.Object
    at com.google.gwt.autobean.shared.AutoBeanCodex$Decoder.push(AutoBeanCodex.java:240)
    at com.google.gwt.autobean.shared.AutoBeanCodex$Decoder.decode(AutoBeanCodex.java:50)
    at com.google.gwt.autobean.shared.AutoBeanCodex$Decoder.visitCollectionProperty(AutoBeanCodex.java:83)
    at com.citrix.xenclient.backend.client.json.RpcResultsAutoBean.traverseProperties(RpcResultsAutoBean.java:100)
    at com.google.gwt.autobean.shared.impl.AbstractAutoBean.traverse(AbstractAutoBean.java:153)
    at com.google.gwt.autobean.shared.impl.AbstractAutoBean.accept(AbstractAutoBean.java:112)
    at com.google.gwt.autobean.shared.AutoBeanCodex$Decoder.decode(AutoBeanCodex.java:51)
    at com.google.gwt.autobean.shared.AutoBeanCodex.decode(AutoBeanCodex.java:505)
    at com.google.gwt.autobean.shared.AutoBeanCodex.decode(AutoBeanCodex.java:521)
    at com.citrix.xenclient.backend.client.services.JSONResponseResultSetHandler.onResponseReceived(JSONResponseResultSetHandler.java:51)
    at com.google.gwt.http.client.Request.fireOnResponseReceived(Request.java:287)
    at com.google.gwt.http.client.RequestBuilder$1.onReadyStateChange(RequestBuilder.java:395)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:157)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:326)
    at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:207)
    at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:126)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)
    at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
    at com.google.gwt.core.client.impl.Impl.apply(Impl.java)
    at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:214)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:157)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:281)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:531)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:352)
    at java.lang.Thread.run(Thread.java:636)

根据此堆栈跟踪,我的预感如下:

  1. 类型删除使得 RpcResults.getResultSet() 看起来正在返回原始 List
  2. AutoBean 反序列化器尝试为 resultSet 中的每个项目创建 Object 实例。
  3. 失败

再次提问

我是否在 AutoBean API 中遗漏了一些可以让我轻松完成此操作的东西?如果不是,是否有我应该调查的明显攻击点?对于我正在做的事情,是否有更明智的替代方案(除了我已经在使用的 JSONParser 和 JavaScriptObject)?

最佳答案

这并不简单,因为 Java 类型删除。类型T运行时不存在,已被删除为 Object代替任何其他下限。 AutoBeanCodex 需要类型信息才能具体化传入 json 有效负载的元素。此类型信息通常由 AutoBean 实现提供,但由于 T删除,它只知道它包含 List<Object> .

如果您可以在运行时提供类文字,则 getter 可以声明为 Splittable getResultSet()并通过调用AutoBeanCodex.decode(autoBeanFactory, SomeInterfaceType.class, getResultSet().get(index))具体化列表的各个元素。通过使用 Category ,您可以添加 <T> T getResultAs(Class<T> clazz, int index) AutoBean 接口(interface)的方法。这看起来像:

@Category(MyCategory.class)
interface MyFactory extends AutoBeanFactory {
  AutoBean<ResultContainer> resultContainer();
}
interface ResultContainer<T> {
  Splittable getResultSet();
  // It's the class literal that makes it work
  T getResultAs(Class<T> clazz, int index);
}
class MyCategory {
  public static <T> T getResultAs(Autobean<ResultContainer> bean,
      Class<T> clazz, int index) {
    return AutoBeanCodex.decode(bean.getFactory(), clazz,
      bean.as().getResultSet().get(index)).as();
  }
}

关于gwt - 包含类型化成员的参数化 AutoBean 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5307265/

相关文章:

GWT Celltable 重置

java - 向 v-ol3 (Openlayers4) 的 OLMap 添加新监听器

java - GWT 远程过程调用。 onSuccess() 方法何时调用?

java - 任意精度数字和 Javascript,Google Web Toolkit

java - CellTable 中的 GWT TextColumn -> 水平对齐

java - GWT 在外部函数接口(interface)中返回 null

java - Autobean 和 XSS 问题

gwt - api doc是如何生成的@http ://api. highcharts.com/

java - GWT 手动序列化服务器上​​的域对象