5.2. ProtoStream を使用したユーザータイプのマーシャリング
ユーザータイプは、Data Grid がそのままではサポートしない Java オブジェクトです。ユーザータイプをマーシャリングするには、SerializationContextInitializer
インターフェイスを実装して Java オブジェクトを記述し、ProtoStream ライブラリーが Protobuf 形式にエンコードし、Data Grid がそれらを送信および保存できるようにします。
5.2.1. シリアル化コンテキストイニシャライザーの生成
ProtoStream SerializationContext
には、Protobuf スキーマからロードされたカスタム Java オブジェクトの Protobuf タイプ定義と、それらのオブジェクトに付随するマーシャラーが含まれています。
Data Grid は、コンパイル時にクラスの Java アノテーションを処理する protostream-processor
アーティファクトを提供します。プロセッサーは、Protobuf スキーマ、マーシャラー、および ProtoStream SerializationContext
の初期化に使用できる SerializationContextInitializer
インターフェイスの具体的な実装を生成します。
デフォルトでは、実装名は Impl 接尾辞が付いたアノテーション付きクラス名です。
手順
protostream-processor
依存関係をpom.xml
に追加します。<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> <!-- This dependency should be declared in the "provided" scope or made "optional" because it is a compile-only dependency and is not required at runtime. Transitive propagation of this dependency should be also be avoided. --> <scope>provided</scope> </dependency> </dependencies>
マーシャリングする Java オブジェクトに
@ProtoField
と@ProtoFactory
アノテーションを付けます。Author.java
import org.infinispan.protostream.annotations.ProtoFactory; import org.infinispan.protostream.annotations.ProtoField; public class Author { @ProtoField(number = 1) final String name; @ProtoField(number = 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) final String title; @ProtoField(number = 2) final String description; @ProtoField(number = 3, defaultValue = "0") final int publicationYear; @ProtoField(number = 4, collectionImplementation = ArrayList.class) final List<Author> authors; @ProtoFactory Book(String title, String description, int publicationYear, List<Author> authors) { this.title = title; this.description = description; this.publicationYear = publicationYear; this.authors = authors; } // public Getter methods omitted for brevity }
SerializationContextInitializer
を拡張し、@AutoProtoSchemaBuilder
アノテーションが付けられたインターフェイスを定義します。@AutoProtoSchemaBuilder( includeClasses = { Book.class, Author.class, }, schemaFileName = "library.proto", 1 schemaFilePath = "proto/", 2 schemaPackageName = "book_sample") interface LibraryInitializer extends SerializationContextInitializer { }
次のステップ
SerializationContextInitializer
実装を Data Grid 設定に追加して登録します。
シリアル化コンテキストイニシャライザーの登録 を参照してください。
5.2.2. シリアライゼーションコンテキストイニシャライザーの手動実装
場合によっては、Protobuf スキーマを手動で定義し、ProtoStream マーシャラーを実装する必要があります。たとえば、Java オブジェクトクラスを変更してアノテーションを追加できない場合などです。
手順
マーシャリングする Java オブジェクトの構造化表現を提供する Protobuf スキーマの
.proto
ファイルを作成します。package book_sample; message Book { optional string title = 1; optional string description = 2; optional int32 publicationYear = 3; // no native Date type available in Protobuf repeated Author authors = 4; } message Author { optional string name = 1; optional string surname = 2; }
前述の
.library.proto
ファイルは、book_sample パッケージに含まれる Book という名前のエンティティー (Protobuf メッセージタイプ) を定義します。Book は、プリミティブ型のいくつかのフィールドと、Author メッセージタイプである authors という名前のアレイ (Protobuf 反復可能フィールド) を宣言します。- メッセージをネストできますが、結果的に構造は厳密にツリーであり、グラフではありません。
- 型の継承はできません。
- コレクションはサポート対象外ですが、フィールドを繰り返してアレイをエミュレートできます。
org.infinispan.protostream.MessageMarshaller
インターフェイスを使用して、クラスのマーシャラーを実装します。注記MessageMarshaller
インターフェイスが非推奨になりました。次のバージョンの Data Grid は、外部のサードパーティー Java オブジェクトクラスに
@ProtoAdaptor
アノテーションを使用するアダプタークラスを作成できる代替実装を提供します。BookMarshaller.java
import org.infinispan.protostream.MessageMarshaller; public class BookMarshaller implements MessageMarshaller<Book> { @Override public String getTypeName() { return "book_sample.Book"; } @Override public Class<? extends Book> getJavaClass() { return Book.class; } @Override public void writeTo(MessageMarshaller.ProtoStreamWriter writer, Book book) throws IOException { writer.writeString("title", book.getTitle()); writer.writeString("description", book.getDescription()); writer.writeInt("publicationYear", book.getPublicationYear()); writer.writeCollection("authors", book.getAuthors(), Author.class); } @Override public Book readFrom(MessageMarshaller.ProtoStreamReader reader) throws IOException { String title = reader.readString("title"); String description = reader.readString("description"); int publicationYear = reader.readInt("publicationYear"); List<Author> authors = reader.readCollection("authors", new ArrayList<>(), Author.class); return new Book(title, description, publicationYear, authors); } }
AuthorMarshaller.java
import org.infinispan.protostream.MessageMarshaller; public class AuthorMarshaller implements MessageMarshaller<Author> { @Override public String getTypeName() { return "book_sample.Author"; } @Override public Class<? extends Author> getJavaClass() { return Author.class; } @Override public void writeTo(MessageMarshaller.ProtoStreamWriter writer, Author author) throws IOException { writer.writeString("name", author.getName()); writer.writeString("surname", author.getSurname()); } @Override public Author readFrom(MessageMarshaller.ProtoStreamReader reader) throws IOException { String name = reader.readString("name"); String surname = reader.readString("surname"); return new Author(name, surname); } }
.proto
スキーマと ProtoStream マーシャラー実装をSerializationContext
に登録するSerializationContextInitializer
実装を作成します。ManualSerializationContextInitializer.java
import org.infinispan.protostream.FileDescriptorSource; import org.infinispan.protostream.SerializationContext; import org.infinispan.protostream.SerializationContextInitializer; ... public class ManualSerializationContextInitializer implements SerializationContextInitializer { @Override public String getProtoFileName() { return "library.proto"; } @Override public String getProtoFile() throws UncheckedIOException { // Assumes that the file is located in a Jar's resources, we must provide the path to the library.proto file return FileDescriptorSource.getResourceAsString(getClass(), "/" + getProtoFileName()); } @Override public void registerSchema(SerializationContext serCtx) { serCtx.registerProtoFiles(FileDescriptorSource.fromString(getProtoFileName(), getProtoFile())); } @Override public void registerMarshallers(SerializationContext serCtx) { serCtx.registerMarshaller(new AuthorMarshaller()); serCtx.registerMarshaller(new BookMarshaller()); } }
次のステップ
SerializationContextInitializer
実装を Data Grid 設定に追加して登録します。
シリアル化コンテキストイニシャライザーの登録 を参照してください。
5.2.3. シリアル化コンテキストイニシャライザーの登録
Data Grid 設定で SerializationContextInitializer
実装を宣言して登録します。
手順
-
以下の例のように、プログラムまたは宣言的に
SerializationContextInitializer
実装を手動で登録します。
プログラムによる設定
GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder(); builder.serialization() .addContextInitializers(new LibraryInitializerImpl(), new SCIImpl());
宣言型設定
<serialization> <context-initializer class="org.infinispan.example.LibraryInitializerImpl"/> <context-initializer class="org.infinispan.example.another.SCIImpl"/> </serialization>