第9章 Externalizable API
9.1. Externalizable API
Externalizer
は以下を実行できるクラスです。
- 該当するオブジェクトタイプをバイトアレイにマーシャリングします。
- バイトアレイの内容のオブジェクトタイプのインスタンスに対するマーシャリングを解除します。
エクスターナライザーは Red Hat JBoss Data Grid によって使用され、ユーザーはオブジェクトタイプをどのようにシリアライズするかを指定できます。Red Hat JBoss Data Grid で使用されるマーシャリングインフラストラクチャーは、JBoss Marshalling に基づいて構築され、効率的なペイロード配信を提供し、ストリームのキャッシュを可能にします。ストリームキャッシングを使用すると、データに複数回アクセスできますが、通常はストリームは 1 度だけ読み取ることができます。
Externalizable インターフェースはシリアライゼーションを使用および拡張します。このインターフェースは、Red Hat JBoss Data Grid でシリアライズとデシリアライズを制御するために使用されます。
9.2. エクスターナライザーのカスタマイズ
Red Hat JBoss Data Grid のデフォルト設定では、分散またはレプリケートされたキャッシュで使用されるすべてのオブジェクトはシリアライズ可能である必要があります。デフォルトの Java シリアル化メカニズムでは、ネットワークやパフォーマンスの効率が悪化する可能性があります。また、シリアライズのバージョン管理や後方互換性などに懸念があります。
スループットやパフォーマンスを向上し、特定のオブジェクトの互換性を強制するには、カスタマイズされたエクスターナライザーを使用します。Red Hat JBoss Data Grid のカスタマイズされたエクスターナライザーは、以下の 2 つ方法のいずれかで使用できます。
- Externalizable インターフェースを使用します。
- 高度なエクスターナライザーを使用します。
9.3. @SerializeWith を使用したマーシャリングのオブジェクトのアノテーション付け
オブジェクトをマーシャルするには、マーシャルまたはアンマーシャルする必要があるタイプにエクスターナライザー実装を提供し、マーシャルされたタイプクラスに @SerializeWith
アノテーションを付けて使用するエクスターナライザークラスを示します。
@SerializeWith アノテーションの使用
import org.infinispan.commons.marshall.Externalizer; import org.infinispan.commons.marshall.SerializeWith; @SerializeWith(Person.PersonExternalizer.class) public class Person { final String name; final int age; public Person(String name, int age) { this.name = name; this.age = age; } public static class PersonExternalizer implements Externalizer<Person> { @Override public void writeObject(ObjectOutput output, Person person) throws IOException { output.writeObject(person.name); output.writeInt(person.age); } @Override public Person readObject(ObjectInput input) throws IOException, ClassNotFoundException { return new Person((String) input.readObject(), input.readInt()); } } }
この例では、 @SerializeWith
アノテーションによってオブジェクトがマーシャル可能であると定義されています。よって、JBoss Marshalling は渡されたエクスターナライザークラスを使用してオブジェクトをマーシャルします。
この方法はエクスターナライザーを簡単に定義できますが、以下の欠点があります。
- このやり方で生成されたペイロードサイズは最も効率的ではありません。これは、モデルの制約の一部 (同じクラスの異なるバージョンへのサポートなど) や、エクスターナライザークラスをマーシャルする必要性が原因です。
-
このモデルでは、マーシャルされるクラスに
@SerializeWith
アノテーションを付ける必要があります。しかし、ソースコードが利用できないクラスにエクスターナライザーを提供する必要がある可能性があり、他の制約では変更できません。 - このモデルで使用されるアノテーションは、マーシャリング層などの下位レベルの詳細を抽象化しようとするフレームワーク開発者やサービスプロバイダーが制限されることがあります。
このような欠点に影響されるユーザーは高度なエクスターナライザーを使用できます。
エクスターナライザー実装のコーディングを容易にし、よりタイプセーフにするには、タイプ <t> をマーシャルまたはアンマーシャルされたオブジェクトのタイプとして定義します。
9.4. 高度なエクスターナライザーの使用
9.4.1. 高度なエクスターナライザーの使用
カスタマイズされた高度なエクスターナライザーを使用すると、Red Hat JBoss Data Grid のパフォーマンスを最適化できます。
-
readObject()
およびwriteObject()
メソッドを定義および実装します。 - エクスターナライザーをマーシャラークラスとリンクします。
- 高度なエクスターナライザーを登録します。
9.4.2. メソッドの実装
高度なエクスターナライザーを使用するには、readObject()
および writeObject()
メソッドを定義および実装します。定義の例は以下のとおりです。
メソッドの定義および実装
import org.infinispan.commons.marshall.AdvancedExternalizer; public class Person { final String name; final int age; public Person(String name, int age) { this.name = name; this.age = age; } public static class PersonExternalizer implements AdvancedExternalizer<Person> { @Override public void writeObject(ObjectOutput output, Person person) throws IOException { output.writeObject(person.name); output.writeInt(person.age); } @Override public Person readObject(ObjectInput input) throws IOException, ClassNotFoundException { return new Person((String) input.readObject(), input.readInt()); } @Override public Set<Class<? extends Person>> getTypeClasses() { return Util.<Class<? extends Person>>asSet(Person.class); } @Override public Integer getId() { return 2345; } } }
このメソッドにはアノテーションが付けられたユーザークラスは必要ありません。そのため、このメソッドはソースコードの使用や変更が不可能なクラスに有効です。
9.4.3. エクスターナライザーとマーシャラークラスのリンク
getTypeClasses()
の実装を使用してこのエクスターナライザーによるマーシャリングが可能なクラスを検索し、readObject()
および writeObject()
クラスへリンクします。
実装例を以下に示します。
import org.infinispan.util.Util; <!-- Additional configuration information here --> @Override public Set<Class<? extends ReplicableCommand>> getTypeClasses() { return Util.asSet(LockControlCommand.class, GetKeyValueCommand.class, ClusteredGetCommand.class, MultipleRpcCommand.class, SingleRpcCommand.class, CommitCommand.class, PrepareCommand.class, RollbackCommand.class, ClearCommand.class, EvictCommand.class, InvalidateCommand.class, InvalidateL1Command.class, PutKeyValueCommand.class, PutMapCommand.class, RemoveCommand.class, ReplaceCommand.class); }
この例では、ReplicableCommandExternalizer
は複数のコマンドタイプを外部化できることを示しています。この例では ReplicableCommand
インターフェースを拡張するすべてのコマンドをマーシャルしますが、フレームワークはクラスの等価比較のみをサポートするため、マーシャルされたクラスがすべて特定のクラスまたはインターフェースの子であることを示すことはできません。
場合によっては、外部化するクラスがプライベートであるためクラスインスタンスにアクセスできないことがあります。このような場合、提供された完全修飾クラス名でクラスを検索し、戻します。例は次のとおりです。
@Override public Set<Class<? extends List>> getTypeClasses() { return Util.<Class<? extends List>>asSet( Util.<List>loadClass("java.util.Collections$SingletonList", null)); }
9.4.4. 高度なエクスターナライザーの登録 (プログラムを使用)
高度なエクスターナライザーの設定後、Red Hat JBoss Data Grid で使用するために登録します。以下のようにプログラムを使用して登録します。
高度なエクスターナライザーのプログラムを使用した登録
GlobalConfigurationBuilder builder = ... builder.serialization() .addAdvancedExternalizer(new Person.PersonExternalizer());
最初の行に GlobalConfigurationBuilder の必要な情報を入力します。
9.4.5. 複数のエクスターナライザーの登録
GlobalConfiguration.addExternalizer()
は varargs
を許可するため、高度なエクスターナライザーを複数登録することもできます。新しいエクスターナライザーを登録する前に、@Marshalls
アノテーションを使用して ID が定義されていることを確認します。
エクスターナライザーの複数登録
builder.serialization() .addAdvancedExternalizer(new Person.PersonExternalizer(), new Address.AddressExternalizer());
9.5. エクスターナライザー ID 値のカスタマイズ
9.5.1. エクスターナライザー ID 値のカスタマイズ
高度なエクスターナライザーには必要な場合にカスタム ID を割り当てることができます。一部の ID 範囲は他のモジュールやフレームワーク用に予約されるため、その使用を避ける必要があります。
ID 範囲 | 対象 |
---|---|
1000-1099 |
Infinispan Tree モジュール |
1100-1199 |
Red Hat JBoss Data Grid Server モジュール |
1200-1299 |
Hibernate Infinispan 2 次キャッシュ |
1300-1399 |
JBoss Data Grid Lucene Directory |
1400-1499 |
Hibernate OGM |
1500-1599 |
Hibernate Search |
1600-1699 |
Infinispan Query モジュール |
1700-1799 |
Infinispan Remote Query モジュール |
1800-1849 |
JBoss Data Grid Scripting モジュール |
1850-1899 |
JBoss Data Grid Server Event Logger モジュール |
1900-1999 |
JBoss Data Grid リモートストア |
9.5.2. エクスターナライザー ID のカスタマイズ (プログラムを使用)
以下の設定を使用して、プログラムを使用して特定の ID をエクスターナライザーに割り当てます。
エクスターナライザーへの ID の割り当て
GlobalConfiguration globalConfiguration = new GlobalConfigurationBuilder() .serialization() .addAdvancedExternalizer($ID, new Person.PersonExternalizer()) .build();
$ID
を指定する ID に置き換えます。