第8章 Externalizable API

8.1. Externalizable API

Externalizer は以下を実行できるクラスです。

  • 該当するオブジェクトタイプをバイトアレイにマーシャリングします。
  • バイトアレイの内容のオブジェクトタイプのインスタンスに対するマーシャリングを解除します。

エクスターナライザーは Red Hat JBoss Data Grid によって使用され、ユーザーはオブジェクトタイプをどのようにシリアライズするかを指定できます。Red Hat JBoss Data Grid で使用されるマーシャリングインフラストラクチャーは、JBoss Marshalling に基づいて構築され、効率的なペイロード配信を提供し、ストリームのキャッシュを可能にします。ストリームキャッシングを使用すると、データに複数回アクセスできますが、通常はストリームは 1 度だけ読み取ることができます。

Externalizable インターフェースはシリアライゼーションを使用および拡張します。このインターフェースは、Red Hat JBoss Data Grid でシリアライズとデシリアライズを制御するために使用されます。

8.2. エクスターナライザーのカスタマイズ

Red Hat JBoss Data Grid のデフォルト設定では、分散またはレプリケートされたキャッシュで使用されるすべてのオブジェクトはシリアライズ可能である必要があります。デフォルトの Java シリアル化メカニズムでは、ネットワークやパフォーマンスの効率が悪化する可能性があります。また、シリアライズのバージョン管理や後方互換性などに懸念があります。

スループットやパフォーマンスを向上し、特定のオブジェクトの互換性を強制するには、カスタマイズされたエクスターナライザーを使用します。Red Hat JBoss Data Grid のカスタマイズされたエクスターナライザーは、以下の 2 つ方法のいずれかで使用できます。

  • Externalizable インターフェースを使用します。詳細は Externalizable API を参照してください。
  • 高度なエクスターナライザーを使用します。

8.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> をマーシャルまたはアンマーシャルされたオブジェクトのタイプとして定義します。

8.4. 高度なエクスターナライザーの使用

8.4.1. 高度なエクスターナライザーの使用

カスタマイズされた高度なエクスターナライザーを使用すると、Red Hat JBoss Data Grid のパフォーマンスを最適化できます。

  1. readObject() および writeObject() メソッドを定義および実装します。
  2. エクスターナライザーをマーシャラークラスとリンクします。
  3. 高度なエクスターナライザーを登録します。

8.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;
      }
   }
}

注記

このメソッドにはアノテーションが付けられたユーザークラスは必要ありません。そのため、このメソッドはソースコードの使用や変更が不可能なクラスに有効です。

8.4.4. 高度なエクスターナライザーの登録 (プログラムを使用)

高度なエクスターナライザーの設定後、Red Hat JBoss Data Grid で使用するために登録します。以下のようにプログラムを使用して登録します。

高度なエクスターナライザーのプログラムを使用した登録

GlobalConfigurationBuilder builder = ...
builder.serialization()
   .addAdvancedExternalizer(new Person.PersonExternalizer());

最初の行に GlobalConfigurationBuilder の必要な情報を入力します。

8.4.5. 複数のエクスターナライザーの登録

GlobalConfiguration.addExternalizer()varargs を許可するため、高度なエクスターナライザーを複数登録することもできます。新しいエクスターナライザーを登録する前に、@Marshalls アノテーションを使用して ID が定義されていることを確認します。

エクスターナライザーの複数登録

builder.serialization()
   .addAdvancedExternalizer(new Person.PersonExternalizer(),
                            new Address.AddressExternalizer());

8.5. エクスターナライザー ID 値のカスタマイズ

8.5.1. エクスターナライザー ID 値のカスタマイズ

高度なエクスターナライザーには必要な場合にカスタム ID を割り当てることができます。一部の ID 範囲は他のモジュールやフレームワーク用に予約されるため、その使用を避ける必要があります。

表8.1 エクスターナライザーの予約される 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 リモートストア

8.5.2. エクスターナライザー ID のカスタマイズ (プログラムを使用)

以下の設定を使用して、プログラムを使用して特定の ID をエクスターナライザーに割り当てます。

エクスターナライザーへの ID の割り当て

GlobalConfiguration globalConfiguration = new GlobalConfigurationBuilder()
            .serialization()
               .addAdvancedExternalizer($ID, new Person.PersonExternalizer())
            .build();

$ID を指定する ID に置き換えます。