2.2. シリアル化のコンテキストイニシャライザーの作成
シリアル化コンテキストイニシャライザーを使用すると、Data Grid で以下を登録することができます。
- ユーザータイプを記述する Protobuf スキーマ。
- シリアル化およびデシリアライズ機能を提供するマーシャラー。
概略としては、以下の操作を行いシリアル化コンテキストイニシャライザーを作成する必要があります。
- ProtoStream アノテーションを Java クラスに追加します。
-
Data Grid が提供する ProtoStream プロセッサーを使用して、
SerializationContextInitializer
実装をコンパイルします。
org.infinispan.protostream.MessageMarshaller
インターフェイスは非推奨となり、ProtoStream の今後のバージョンで削除される予定です。完全に削除されるまで MessageMarshaller
の使用方法を示すコード例またはドキュメントは無視する必要があります。
2.2.1. ProtoStream プロセッサーの追加
Data Grid は、コンパイル時にクラスの Java アノテーションを処理する ProtoStream プロセッサーアーティファクトを提供し、Protobuf スキーマ、付随マーシャラー、および SerializationContextInitializer
インターフェイスの具体的な実装を生成します。
手順
provided
スコープでprotostream-processor
依存関係をpom.xml
に追加します。注記この依存関係はコンパイル時にのみ必要です。そのため、
provided
スコープを使用するか、オプションとしてマークする必要があります。また、protostream-processor
が推移的な依存関係として伝播されないようにする必要があります。<dependencyManagement> <dependencies> <dependency> <groupId>org.infinispan</groupId> <artifactId>infinispan-bom</artifactId> <version>${version.infinispan}</version> <type>pom</type> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.infinispan.protostream</groupId> <artifactId>protostream-processor</artifactId> <scope>provided</scope> </dependency> </dependencies>
2.2.2. ProtoStream アノテーションの Java クラスへの追加
Java クラスとそのメンバーにアノテーションを追加して ProtoStream メタデータを宣言します。次に、Data Grid は ProtoStream プロセッサーを使用して Protobuf スキーマと、それらのアノテーションから関連するマーシャラーを生成します。
手順
フィールドで直接、または getter メソッドまたは setter メソッドのいずれかで、
@ProtoField
でマーシャリングする Java フィールドにアノテーションを付けます。Java クラスのアノテーションが付けられていないフィールドは一時的です。たとえば、Java クラスに 15 つのフィールドがあり、それらのうち 5 つにアノテーションを付けるとします。作成されるスキーマにはこれらの 5 つのフィールドのみが含まれ、これらの 5 つのフィールドのみが Data Grid にクラスインスタンスを保存するときにマーシャリングされます。
-
@ProtoFactory
を使用して、イミュータブルオブジェクトのコンストラクターにアノテーションを付けます。アノテーションが付けられたコンストラクターは@ProtoField
アノテーションが付けられたフィールドをすべて初期化する必要があります。 -
@ProtoEnumValue
で Java 列挙型のメンバーにアノテーションを付けます。
以下の Author.java
および Book.java
の例は、@ProtoField
および @ProtoFactory
のアノテーションが付けられた Java クラスを示しています。
Author.java
import org.infinispan.protostream.annotations.ProtoFactory; import org.infinispan.protostream.annotations.ProtoField; public class Author { @ProtoField(1) final String name; @ProtoField(2) final String surname; @ProtoFactory Author(String name, String surname) { this.name = name; this.surname = surname; } // public Getter methods omitted for brevity }
Book.java
import org.infinispan.protostream.annotations.ProtoFactory; import org.infinispan.protostream.annotations.ProtoField; public class Book { @ProtoField(number = 1) public final UUID id; @ProtoField(number = 2) final String title; @ProtoField(number = 3) final String description; @ProtoField(number = 4, defaultValue = "0") final int publicationYear; @ProtoField(number = 5, collectionImplementation = ArrayList.class) final List<Author> authors; @ProtoField(number = 6) public Language language; @ProtoFactory Book(UUID id, String title, String description, int publicationYear, List<Author> authors, Language language) { this.id = id; this.title = title; this.description = description; this.publicationYear = publicationYear; this.authors = authors; this.language = language; } // public Getter methods not included for brevity }
以下の Language.java
の例は、対応する Protobuf スキーマとともに @ProtoEnumValue
アノテーションが付けられた Java 列挙を示しています。
Language.java
import org.infinispan.protostream.annotations.ProtoEnumValue; public enum Language { @ProtoEnumValue(number = 0, name = "EN") ENGLISH, @ProtoEnumValue(number = 1, name = "DE") GERMAN, @ProtoEnumValue(number = 2, name = "IT") ITALIAN, @ProtoEnumValue(number = 3, name = "ES") SPANISH, @ProtoEnumValue(number = 4, name = "FR") FRENCH; }
Language.proto
enum Language { EN = 0; DE = 1; IT = 2; ES = 3; FR = 4; }
2.2.3. ProtoStream アダプタークラスの作成
ProtoStream は @ProtoAdapter
アノテーションを提供し、これを使用して、直接アノテーションを付けることができない外部のサードパーティーの Java オブジェクトクラスをマーシャリングすることができます。
手順
Adapter
クラスを作成し、以下の例のように@ProtoAdapter
アノテーションを追加します。import java.util.UUID; import org.infinispan.protostream.annotations.ProtoAdapter; import org.infinispan.protostream.annotations.ProtoFactory; import org.infinispan.protostream.annotations.ProtoField; import org.infinispan.protostream.descriptors.Type; /** * Human readable UUID adapter for UUID marshalling */ @ProtoAdapter(UUID.class) public class UUIDAdapter { @ProtoFactory UUID create(String stringUUID) { return UUID.fromString(stringUUID); } @ProtoField(1) String getStringUUID(UUID uuid) { return uuid.toString(); } }
2.2.4. シリアル化コンテキストイニシャライザーの生成
ProtoStream プロセッサーを追加して Java クラスにアノテーションを付けると、Data Grid が Protobuf スキーマ、付随するマーシャラー、および SerializationContextInitializer
の具体的な実装を生成するように @AutoProtoSchemaBuilder
アノテーションをインターフェイスに追加できます。
デフォルトでは、生成された実装名は Impl 接尾辞が付いたアノテーション付きクラス名です。
手順
GeneratedSchema
を拡張するインターフェイスまたはそのスーパーインターフェイスSerializationContextInitializer
を定義します。注記GeneratedSchema
インターフェイスには Protobuf スキーマにアクセスするためのメソッドが含まれていますが、SerializationContextInitializer
インターフェイスは登録メソッドのみをサポートします。-
インターフェイスに
@AutoProtoSchemaBuilder
アノテーションを付けます。 -
includeClasses
パラメーターには、生成されたSerializationContextInitializer
実装のすべてのクラスが含まれることを確認します。 -
schemaFileName
パラメーターで、生成された.proto
スキーマの名前を指定します。 -
schemaFilePath
パラメーターで、スキーマファイルが生成されるtarget/classes
の下にパスを設定します。 -
schemaPackageName
パラメーターで、生成された.proto
スキーマのパッケージ名を指定します。
以下の例は、@AutoProtoSchemaBuilder
アノテーションが付けられた GeneratedSchema
インターフェイスを示しています。
@AutoProtoSchemaBuilder( includeClasses = { Book.class, Author.class, UUIDAdapter.class, Language.class }, schemaFileName = "library.proto", schemaFilePath = "proto/", schemaPackageName = "book_sample") interface LibraryInitializer extends GeneratedSchema { }
次のステップ
埋め込みキャッシュを使用する場合は、Data Grid は SerializationContextInitializer
実装を自動的に登録します。
リモートキャッシュを使用する場合は、SerializationContextInitializer
実装を Data Grid Server に登録する必要があります。
2.2.5. シリアル化コンテキストイニシャライザーの登録
埋め込みキャッシュの場合、Data Grid は java.util.ServiceLoader
を使用してアノテーションが付けられた SerializationContextInitializer
実装にシリアル化コンテキストおよびマーシャラーを自動的に登録します。
必要に応じて、SerializationContextInitializer
実装の自動登録を無効にして、手動で登録することができます。
1 つの SerializationContextInitializer
実装を手動で登録する場合は、自動登録が無効になります。その後、他のすべての実装を手動で登録する必要があります。
手順
AutoProtoSchemaBuilder.service
アノテーションにfalse
の値を設定します。@AutoProtoSchemaBuilder( includeClasses = SomeClass.class, ... service = false )
-
以下の例のように、プログラムまたは宣言的に
SerializationContextInitializer
実装を手動で登録します。
宣言的 (Declarative)
<serialization> <context-initializer class="org.infinispan.example.LibraryInitializerImpl"/> <context-initializer class="org.infinispan.example.another.SCIImpl"/> </serialization>
プログラマティック
GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder(); builder.serialization() .addContextInitializers(new LibraryInitializerImpl(), new SCIImpl());
2.2.6. Data Grid Server への Protobuf スキーマの登録
Ickle クエリーを実行する場合、または application/x-protostream
から application/json
などの他のメディアタイプに変換する場合は、Data Grid Server に Protobuf スキーマを登録する必要があります。
前提条件
ProtoStream プロセッサーを使用して
SerializationContextInitializer
実装を生成している。ビルドの完了後に、生成された Protobuf スキーマを
target/<schemaFilePath>/
ディレクトリーに見つけることができます。
手順
以下のいずれかを実行して、生成された Protobuf スキーマを Data Grid Server に登録します。
生成された Protobuf スキーマを、Data Grid コマンドラインインターフェイス (CLI)、REST インターフェイス、または
ProtobufMetadataManager
JMX MBean を使用して専用の___protobuf_metadata
キャッシュに追加します。この方法では、Data Grid がスキーマを自動的にクラスター全体に分散できるようにします。
注記キャッシュのセキュリティー承認を有効にする場合、ユーザーは
___protobuf_metadata
キャッシュにスキーマを追加するCREATE
パーミッションを持っている必要があります。デフォルトの承認設定を使用する場合は、ユーザーに少なくともdeployer
ロールを割り当てます。以下の例のように、Hot Rod クライアントで生成された
SerializationContextInitializer
実装を使用して、Protobuf スキーマを登録します。/** * Register generated Protobuf schema with Data Grid Server. * This requires the RemoteCacheManager to be initialized. * * @param initializer The serialization context initializer for the schema. */ private void registerSchemas(SerializationContextInitializer initializer) { // Store schemas in the '___protobuf_metadata' cache to register them. // Using ProtobufMetadataManagerConstants might require the query dependency. final RemoteCache<String, String> protoMetadataCache = remoteCacheManager.getCache(ProtobufMetadataManagerConstants.PROTOBUF_METADATA_CACHE_NAME); // Add the generated schema to the cache. protoMetadataCache.put(initializer.getProtoFileName(), initializer.getProtoFile()); // Ensure the registered Protobuf schemas do not contain errors. // Throw an exception if errors exist. String errors = protoMetadataCache.get(ProtobufMetadataManagerConstants.ERRORS_KEY_SUFFIX); if (errors != null) { throw new IllegalStateException("Some Protobuf schema files contain errors: " + errors + "\nSchema :\n" + initializer.getProtoFileName()); } }
SerializationContextInitializer
実装およびカスタムクラスを持つ JAR ファイルを$RHDG_HOME/server/lib
ディレクトリーに追加します。これを実行すると、Data Grid Server は起動時に Protobuf スキーマを登録します。ただし、スキーマは
___protobuf_metadata
キャッシュに保存されたり、クラスター全体で自動的に分散されたりしないため、アーカイブを各サーバーインストールに追加する必要があります。注記Data Grid Server が
application/x-protostream
からapplication/x-java-object
への変換を実施する必要がある場合、これを実行する必要があります。この場合、POJO 用の JAR ファイルも追加する必要があります。
次のステップ
以下の例のように、SerializationContextInitializer
を Hot Rod クライアントに登録します。
ConfigurationBuilder remoteBuilder = new ConfigurationBuilder(); remoteBuilder.addServer().host(host).port(Integer.parseInt(port)); // Add your generated SerializationContextInitializer implementation. LibraryInitalizer initializer = new LibraryInitalizerImpl(); remoteBuilder.addContextInitializer(initializer);
2.2.7. 手動によるシリアル化コンテキストイニシャライザーの実装
Data Grid は、SerializationContextInitializer
または GeneratedSchema
インターフェイスを手動で実装しないことを強く推奨します。
ProtobufTagMarshaller
および RawProtobufMarshaller
アノテーションを使用して SerializationContextInitializer
または GeneratedSchema
インターフェイスを手動で実装できます。
ただし、手動の実装には多くの面倒なオーバーヘッドが必要で、エラーが発生する可能性が高くなります。protostream-processor
アーティファクトを使用して生成する実装は、ProtoStream マーシャリングを設定するより効率的で信頼できる方法です。