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 プロセッサーで Protobuf スキーマを生成します。
生成された Protobuf スキーマは、
target/<schemaFilePath>/ディレクトリーにあります。CREATE権限を持つユーザーを用意します。注記セキュリティー認可には、スキーマを追加するための
CREATE権限が必要です。デフォルト設定では、少なくともdeployerのロールが必要です。
手順
次のいずれかの方法で、Protobuf スキーマを Data Grid サーバーに追加します。
- 任意のブラウザーで Data Grid コンソールを開き、Schema タブを選択してから Add Protobuf schema を選択します。
Data Grid コマンドラインインターフェイス (CLI) から
--upload=引数を指定してschemaコマンドを使用します。schema --upload=person.proto personREST API を使用して、
POST要求のペイロードに Protobuf スキーマを含めます。POST/rest/v2/schemas/<schema_name>以下の例のように、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 マーシャリングを設定するより効率的で信頼できる方法です。