不変クラスFoo(IDと名前からなるPOJO)を考慮してください。これは、サーバーからクライアントにデータを送信するためにシリアル化する必要があります。 FooのオブジェクトのGWTカスタムフィールドシリアル化の問題
public final class Foo
{
private final int m_id;
private final String m_displayName;
private Foo(final int id, final String displayName)
{
m_id = id;
m_displayName = displayName;
}
public static Foo create(final int id, final String displayName)
{
// Some error checking occurs here.
. . .
m_id = id;
m_displayName = displayName;
}
// Getters etc.
. . .
}
インスタンス化は、静的なファクトリ関数を介して発生し、オブジェクトの不変ので全くゼロ引数のコンストラクタが存在しません。
データメンバFooを含み、インスタンス化のためのBuilderパターンを実装する不変クラスのBarも考慮してください(問題とは無関係にスニペットから省略されています)。
public final class Bar
{
private final Foo m_foo;
. . .
private Bar(final Builder builder)
{
. . .
}
public static Builder createBuilder()
{
return new Builder();
}
}
私はその不変性を取り除くか、直列化のために任意のゼロ引数のコンストラクタを追加することなく、このオブジェクトをシリアル化する必要がある方法に関する私の選択肢を評価した後、私は両方のために、私はCustomFieldSerializerを実装するために必要な事実(に締結しましたクライアントとサーバー)。
私はGWTのServer Communicationの記事に書かれたガイドラインに従い、以下に示すように私自身のCustomFieldSerializerを実装しました。
// Contains the serialization logic of the class Bar.
public final class Bar_CustomFieldSerializerBase
{
public static Bar instantiate(final SerializationStreamReader streamReader) throws SerializationException
{
return Bar.createBuilder().forFoo((Foo) streamReader.readObject()).build();
}
public static void serialize(final SerializationStreamWriter streamWriter, final Bar instance)
throws SerializationException
{
// . . .
streamWriter.writeObject(instance.getFoo());
}
public static void deserialize(final SerializationStreamReader streamReader, final Bar instance)
{
/*
* Empty as everything is handled on instantiateInstance().
*/
}
}
// The CustomFieldSerializer for class Bar.
public class Bar_CustomFieldSerializer extends CustomFieldSerializer<Bar>
{
public static void deserialize(final SerializationStreamReader streamReader, final Bar instance) throws SerializationException
{
Bar_CustomFieldSerializerBase.deserialize(streamReader, instance);
}
public static void serialize(final SerializationStreamWriter streamWriter, final Bar instance) throws SerializationException
{
Bar_CustomFieldSerializerBase.serialize(streamWriter, instance);
}
public static Bar instantiate(final SerializationStreamReader streamReader) throws SerializationException
{
return Bar_CustomFieldSerializerBase.instantiate(streamReader);
}
@Override
public boolean hasCustomInstantiateInstance()
{
return true;
}
@Override
public Bar instantiateInstance(final SerializationStreamReader streamReader) throws SerializationException
{
return instantiate(streamReader);
}
@Override
public void deserializeInstance(final SerializationStreamReader streamReader, final Bar instance) throws SerializationException
{
deserialize(streamReader, instance);
}
@Override
public void serializeInstance(final SerializationStreamWriter streamWriter, final Bar instance) throws SerializationException
{
serialize(streamWriter, instance);
}
// Server side CustomFieldSerializer for class Bar.
public class Bar_ServerCustomFieldSerializer extends ServerCustomFieldSerializer<Bar>
{
public static void deserialize(ServerSerializationStreamReader streamReader, Bar instance,
Type[] expectedParameterTypes, DequeMap<TypeVariable<?>, Type> resolvedTypes) throws SerializationException
{
/*
* Empty as everything is handled on instantiateInstance().
*/
}
@Override
public Bar instantiateInstance(ServerSerializationStreamReader streamReader) throws SerializationException
{
return Bar_CustomFieldSerializerBase.instantiate(streamReader);
}
@Override
public void deserializeInstance(ServerSerializationStreamReader streamReader, Bar instance,
Type[] expectedParameterTypes, DequeMap<TypeVariable<?>, Type> resolvedTypes) throws SerializationException
{
deserialize(streamReader, instance, expectedParameterTypes, resolvedTypes);
}
@Override
public void deserializeInstance(SerializationStreamReader streamReader, Bar instance) throws SerializationException
{
Bar_CustomFieldSerializerBase.deserialize(streamReader, instance);
}
@Override
public void serializeInstance(SerializationStreamWriter streamWriter, Bar instance) throws SerializationException
{
Bar_CustomFieldSerializerBase.serialize(streamWriter, instance);
}
}
クラスバーは私が行って、CustomFieldSerializersの別のセットを実装し、Fooクラスのために、この時間は、クライアントとサーバーの両方で、同じパターンを以下のシリアル化する必要はFooオブジェクトが含まれているため。
シリアライゼーションクラスバーのために、特にこの時点で発生したときに問題が発生:
public static void serialize(final SerializationStreamWriter streamWriter, final Bar instance)
throws SerializationException
{
// . . .
streamWriter.writeObject(instance.getFoo());
}
私が取得例外メッセージは以下の通りです:
[WARN] Exception while dispatching incoming RPC call com.google.gwt.user.client.rpc.SerializationException: Type 'ui.shared.models.fooItems.Foo' 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.
それはのwriteObject(と思われます)は、クライアントとサーバーの両方にカスタムシリアライザが提供されていても、Fooクラスがホワイトリスト項目に属していないため、Foo型のオブジェクトをシリアル化できません。
私はいつものwriteObjectを(スキップできる)呼び出しとのwriteIntを(呼び出し) & WriteStringは(うまく機能している)各フーのデータメンバーの()が、私はむしろのwriteObjectを(になるだろう)働く私が提案した解決策は、Fooのシリアライザ(明白な)とバーのシリアライザ(あまり明白ではない)の両方に反映されなければならないので、Fooクラスの変更が反映されなければならないので、メンテナンスの間違いが起こりやすい非常にです。
私は(任意の違いはありませんでしたし、それが彼らの供給私の知る限りクラスので、任意の違いを作るべきではないfooとbarの両方でisSerializableインタフェースを実装するから、私はネット上で見つけることができるほとんど何でも試してみました独自のシリアライザはこのルールを遵守する必要はありません)、プライベートゼロ-argsコンストラクタを提供することもできます(カスタムフィールドシリアライザのインスタンス化関数は静的ファクトリを介して処理する必要があります)。
なぜFooクラスはホワイトリストに登録されていませんか?私は何かを見逃したり、何かを誤解したことがありますか?
ありがとうございます。
回答にスポットがあります。私はシナリオ全体が完全に混乱していることに非常に同意します。カスタムフィールドのシリアライゼーションクラスを提供するクラスは、ホワイトリストに登録されたオブジェクトに自動的に追加する必要があります。現在の実装では、開発者が問題を突き抜けたり、複雑なシステムを追加したりすることがあります。 –
真実は、この答えが示唆するよりもやや簡単だと思います。まず、「最終」フィールドは無視されます(http://code.google.com/p/google-web-toolkit/issues/detail?id=1054のように提出されます)。そのため、理論的にはすべてのコードを呼び出すことができるので(つまり、可能な型を解決するのが難しい問題です)、独自のシリアライザの機能に関係なく、所有者の型が送信されます。その結果、そのタイプを参照する新しいメソッドを追加するだけで、それをマークすることができます。 'final'を削除するか(または1054を修正する)、このメソッドは必要ありません。 –
@ColinAlworth実際にあなたは100%正しいです – jusio