Pertanyaan
Apakah ada cara untuk melakukan deserialisasi JSON menggunakan kerangka AutoBean sehingga kacang yang dihasilkan memiliki parameter tipe yang memengaruhi tipe satu atau lebih anggotanya?
Latar belakang
RPC dengan hasil JSON
Saya menggunakan GWT (RequestBuilder
) untuk melakukan permintaan RPC. Payload JSON yang dikembalikan adalah dalam bentuk berikut:
{
"resultSet": [{...}, {...}, ...], // items requested; say, items 150-160
"totalCount": 15330 // total matching items in DB
}
Objek di resultSet
jenisnya bervariasi tergantung pada RPC spesifik yang saya panggil.
Antarmuka AutoBean
Saya ingin membatalkan serialisasi JSON ini menggunakan AutoBean. Saya mencoba merepresentasikan objek ini sebagai berikut:
interface RpcResults<T> {
List<T> getResultSet();
void setResultSet(List<T> resultSet);
int getTotalCount();
void setTotalCount(int totalCount);
}
Saya juga telah membuat antarmuka yang sesuai yang mewakili setiap jenis objek yang mungkin ada dalam resultSet
. Terakhir, saya mengatur panggilan yang sesuai ke AutoBeanCodex.decode
.
Menjalankan kode
Mencoba menjalankan kode ini dalam mode pengembangan menyebabkan pelacakan tumpukan berikut muncul di konsol:
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)
Berdasarkan jejak tumpukan ini, firasat saya adalah sebagai berikut:
- Jenis penghapusan membuatnya tampak bahwa
RpcResults.getResultSet()
mengembalikanList
mentah. - Deserialiser AutoBean mencoba membuat
Object
instance untuk setiap item diresultSet
. - Kegagalan
Pertanyaan lagi
Apakah saya melewatkan sesuatu di AutoBean API yang memungkinkan saya melakukan ini dengan mudah? Jika tidak, apakah ada titik serangan yang harus saya perhatikan? Apakah ada alternatif yang lebih masuk akal untuk apa yang saya lakukan (selain JSONParser dan JavaScriptObject, yang sudah saya gunakan)?