GWTのシリアル化ポリシーホワイトリストにタイプを追加するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/138099

質問

GWTのシリアライザは java.io.Serializable のサポートを制限していますが、セキュリティ上の理由から、サポートするタイプのホワイトリストがあります。たとえば、このFAQエントリは、シリアル化するすべての型を「シリアル化ポリシーホワイトリスト」に含める必要があり、リストはコンパイル時に生成されるが、コンパイラがホワイトリストの内容を決定する方法を説明していないことを示しています。

生成されたリストには、 java.lang.String java.util.HashMap など、標準ライブラリの一部である多くのタイプが含まれています。 Serializable インターフェースを実装しているが、ホワイトリストにない java.sql.Date をシリアル化しようとするとエラーが発生します。このタイプをリストに追加するにはどうすればよいですか?

役に立ちましたか?

解決

java.io.Serializableを実装している限り、サービスインターフェースに含める特定のタイプおよびそれらが参照するタイプはすべて自動的にホワイトリストに登録されます。例:

public String getStringForDates(ArrayList<java.util.Date> dates);

結果としてArrayListとDateの両方がホワイトリストに含まれます。

特定のタイプの代わりにjava.lang.Objectを使用しようとすると、トリッキーになります:

public Object getObjectForString(String str);

コンパイラーは何をホワイトリストに登録するかわからないため。その場合、オブジェクトがサービスインターフェイスのどこでも参照されない場合、IsSerializableインターフェイスで明示的にマークする必要があります。そうしないと、RPCメカニズムを介してオブジェクトを渡すことができません。

他のヒント

回避策があります。シリアル化に含めるすべてのタイプのメンバーフィールドを使用して、新しい Dummy クラスを定義します。次に、RPCインターフェイスにメソッドを追加します。

Dummy dummy(Dummy d);

実装はこれだけです:

Dummy dummy(Dummy d) { return d; }

そして、非同期インターフェースにはこれがあります:

void dummy(Dummy d, AsyncCallback< Dummy> callback);

GWTコンパイラはこれを取得し、 Dummy クラスはこれらの型を参照するため、それらをホワイトリストに含めます。

Dummy クラスの例:

public class Dummy implements IsSerializable {
    private java.sql.Date d;
}

ホワイトリストはGWTコンパイラーによって生成され、IsSerializableマーカーインターフェイスによって指定されたすべてのエントリが含まれます。

リストに型を追加するには、クラスがIsSerializableインターフェイスを実装していることを確認する必要があります。

さらに、シリアル化が正しく機能するためには、クラスにデフォルトの引数なしコンストラクターが必要です(コンストラクターは必要に応じてプライベートにすることができます)。また、クラスが内部の場合は、静的としてマークする必要があります。

プログラムでホワイトリストにアクセスする最も簡単な方法は、次のようなクラスを作成することです:

public class SerializableWhitelist implements IsSerializable {
    String[] dummy1;
    SomeOtherThingsIWishToSerialize dummy2;
}

それを .client パッケージに含め、RPCサービスからの参照を追加します(したがって、コンパイラによって分析されます)。

パラメータ化されていないマップの転送を有効にするより良い方法を見つけることができませんでした。これは明らかに、より一般的なサービスを作成するために時々必要なものです...

  

ホワイトリストはgwtコンパイラーによって生成され、IsSerializableマーカーインターフェイスによって指定されたすべてのエントリが含まれます。

     

リストに型を追加するには、クラスがIsSerializableインターフェイスを実装していることを確認する必要があります。

     

-アンドレジ

これはおそらく最も簡単な解決策です。 これについて覚えておくべき唯一のことは、シリアル化するすべてのクラスが「public、no-argument」を持つ必要があることです。コンストラクター、および(要件に応じて)メンバーフィールドのセッターメソッド。

目的の結果を確実にするには、すべての war /&lt; app&gt; / gwt / *。gwt.rpc

を削除します

同じ質問があり、以前の回答が満足のいくものではないと思う人には...

このメッセージでのように変更したSpringを使用しているため、GWTControllerでGWTを使用しています。 。メッセージはGrailsRemoteServiceServletを変更する方法を説明していますが、GWTControllerは同じ方法でRPC.decodeRequest()とRPC.encodeResponseForSuccess()を呼び出します。

これは私が使用しているGWTControllerの最終バージョンです。

/**
 * Used to instantiate GWT server in Spring context.
 *
 * Original version from <a href="http://docs.google.com/Doc?docid=dw2zgx2_25492p5qxfq&hl=en">this tutorial</a>.
 * 
 * ...fixed to work as explained <a href="http://blog.js-development.com/2009/09/gwt-meets-spring.html">in this tutorial</a>.
 * 
 * ...and then fixed to use StandardSerializationPolicy as explained in
 * <a href="http://markmail.org/message/k5j2vni6yzcokjsw">this message</a> to allow
 * using Serializable instead of IsSerializable in model.
 */
public class GWTController extends RemoteServiceServlet implements Controller, ServletContextAware {

 // Instance fields

 private RemoteService remoteService;

 private Class<? extends RemoteService> remoteServiceClass;

 private ServletContext servletContext;

 // Public methods

 /**
  * Call GWT's RemoteService doPost() method and return null.
  * 
  * @param request
  *            The current HTTP request
  * @param response
  *            The current HTTP response
  * @return A ModelAndView to render, or null if handled directly
  * @throws Exception
  *             In case of errors
  */
 public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
  doPost(request, response);
  return null; // response handled by GWT RPC over XmlHttpRequest
 }

 /**
  * Process the RPC request encoded into the payload string and return a string that encodes either the method return
  * or an exception thrown by it.
  * 
  * @param payload
  *            The RPC payload
  */
 public String processCall(String payload) throws SerializationException {
  try {
   RPCRequest rpcRequest = RPC.decodeRequest(payload, this.remoteServiceClass, this);

   // delegate work to the spring injected service
   return RPC.invokeAndEncodeResponse(this.remoteService, rpcRequest.getMethod(), rpcRequest.getParameters(), rpcRequest.getSerializationPolicy());
  } catch (IncompatibleRemoteServiceException e) {
   return RPC.encodeResponseForFailure(null, e);
  }
 }

 /**
  * Setter for Spring injection of the GWT RemoteService object.
  * 
  * @param RemoteService
  *            The GWT RemoteService implementation that will be delegated to by the {@code GWTController}.
  */
 public void setRemoteService(RemoteService remoteService) {
  this.remoteService = remoteService;
  this.remoteServiceClass = this.remoteService.getClass();
 }

 @Override
 public ServletContext getServletContext() {
  return servletContext;
 }

 public void setServletContext(ServletContext servletContext) {
  this.servletContext = servletContext;
 }
}

クライアントパッケージに配置するか、ダミーサービスインターフェイスで使用するだけでは、システムによって最適化されているように見えるため、十分ではないことがわかりました。

サービスインターフェイスで既に使用されているタイプの1つから派生したクラスを作成し、それをクライアントパッケージに固定するのが最も簡単であることがわかりました。他に何も必要ありません。

public class GWTSerializableTypes extends SomeTypeInServiceInterface implements IsSerializable {
    Long l;
    Double d;
    private GWTSerializableTypes() {}
}

この問題が発生しましたが、Serializableオブジェクトのコード行に問題をトレースしてしまいました。

Logger.getLogger(this.getClass().getCanonicalName()).log(Level.INFO, "Foo");

例外がキャッチされるまで、他の苦情はありませんでした:

 @Override
  protected void serialize(Object instance, String typeSignature)
      throws SerializationException {
    assert (instance != null);

    Class<?> clazz = getClassForSerialization(instance);

    try {
      serializationPolicy.validateSerialize(clazz);
    } catch (SerializationException e) {
      throw new SerializationException(e.getMessage() + ": instance = " + instance);
    }
    serializeImpl(instance, clazz);
  }

そして、スタックトレースのビジネスエンドは次のとおりです。

com.google.gwt.user.client.rpc.SerializationException: Type 'net.your.class' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.: instance = net.your.class@9c7edce
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:619)
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top