2012-04-12 12 views
4

私はTreeMapを持つシリアライズ可能なオブジェクトを持っています。GWT TreeMapのOrdering/Comparatorをシリアライズ

Map<String, Dogs> dogsByNames = Maps.newTreeMap(); // guava style 

これまでのところ、すべて問題ありません。 は、今では、キーの大文字と小文字を無視するnessassaryです:

Map<String, Dogs> dogsByNames = Maps.newTreeMap(String.CASE_INSENSITIVE_ORDER); 

String.CASE_INSENSITIVE_ORDERがserialzableではないので、これは動作しません:

com.google.gwt.user.client.rpc。 SerializationException:タイプ 'java.lang.String $ CaseInsensitiveComparator'は、このSerializationPolicyまたは のClassオブジェクトをロードできなかった タイプのセットに含まれていませんでした。セキュリティ上の目的のために、このタイプ がシリアライズされません。:インスタンス= [email protected]

だから私は自分のものを作成します。

private static abstract class MyComparator<T> 
    implements 
     Comparator<T>, // extends Ordering<T> do not work 
     IsSerializable { // Serializable do not work 
} 

public static final MyComparator<String> CASE_INSENSITIVE_ORDER = new MyComparator<String>() { 
    @Override 
    public int compare(final String left, final String right) { 
     if (null == left) { 
      return (null == right) ? 0 : -1; 
     } else if (null == right) { 
      return 1; 
     } 
     return left.compareToIgnoreCase(right); 
    } 
}; 

しかし、これはまだありません作業。

何が間違っていますか?

ソリューション:

protected static class MyOrdering // no-private!!! 
    extends 
     Ordering<String> 
    implements 
     IsSerializable { 
    @Override 
    public int compare(final String left, final String right) { 
     if (null == left) { 
      return (null == right) ? 0 : -1; 
     } else if (null == right) { 
      return 1; 
     } 
     return left.compareToIgnoreCase(right); 
    } 
} 

public static final Ordering<String> CASE_INSENSITIVE_ORDER = new MyOrdering(); 
+1

docs 'CASE_INSENSITIVE_ORDER' **は** serializableです:_A compareToIgnoreCaseのようにStringオブジェクトを順序付けするComparatorです。このコンパレータはシリアル化可能です。 – Xaerxess

+0

実際はそうではありません。 (@see編集) –

+0

@ eneveuの答えが役に立つかもしれません。 – Xaerxess

答えて

5

あなたが作成したCASE_INSENSITIVE_ORDERはGWTでシリアライズすることができない匿名クラス、です。それはGWT直列化可能にするために、あなたが行ったように(のような

CaseInsensitiveOrder implements Comparator<..>, Serializable { 
    ... 
} 
  • が一定CASE_INSENSITIVE_ORDERを作成したカスタムトップレベルのクラスを作成します

    1. する必要があります。

    2. は、カスタムフィールドのシリアライザを作成します。そのクラス(CaseInsensitiveOrder_CustomFieldSerializer)の場合、deserialize()CASE_INSENSITIVE_ORDERインスタンスを返します。
  • +0

    これは正しいヒントでした。コンパレータをネストされたクラスとして実装した後。私は非公開にする必要がありました。だからあなたの3は本当に必要ではありません。 –

    +0

    3は、逆シリアル化された注文がオリジナルと同じインスタンスであることを確認するために必要です。 MyOrderingの複数のインスタンスで暮らすことができれば、スキップすることができます。 –

    0

    エラーのスタックトレースが参考になります。しかし、私はあなたのような例外を得ることを推測ハザードます:

    がcom.google.gwt.user.client.rpc.SerializationException:タイプ 「com.foo.Bar.MyComparatorは」に含まれていなかったがこのSerializationPolicyまたはそのClassオブジェクトによって にシリアル化できるタイプのセットは、 をロードできませんでした。セキュリティ上の理由から、この型はシリアル化されません。

    これは、GWTがコンパイル時にシリアル化する必要があるすべての型のリストを作成するためです。これが「シリアライゼーションポリシー」です。これを行うために、GWTはすべてのRPCメソッドで引数と戻り値の型を検査し、すべての "到達可能な"型を検索します。

    コンパイラは、コンパレータがシリアル化されることを認識せず、シリアル化ポリシーに追加されません。

    回避方法は、this other SO answerで説明されているように、シリアル化が必要な可能性があるすべての型をパラメータとしてとるダミーメソッドを宣言することです。ような何か:

    // in your RPC interface 
    SerializationWhitelist dummyMethodForSerializationPolicy(SerializationWhitelist serializationWhiteList); 
    
    // the SerializableWhiteList class 
    public class SerializationWhitelist { 
        public Bar.MyComparator<String> myComparator; 
    }