2.2. シリアル化のコンテキストイニシャライザーの作成


シリアル化コンテキストイニシャライザーを使用すると、Data Grid で以下を登録することができます。

  • ユーザータイプを記述する Protobuf スキーマ。
  • シリアル化およびデシリアライズ機能を提供するマーシャラー。

概略としては、以下の操作を行いシリアル化コンテキストイニシャライザーを作成する必要があります。

  1. ProtoStream アノテーションを Java クラスに追加します。
  2. Data Grid が提供する ProtoStream プロセッサーを使用して、SerializationContextInitializer 実装をコンパイルします。
注記

org.infinispan.protostream.MessageMarshaller インターフェイスは非推奨となり、ProtoStream の今後のバージョンで削除される予定です。完全に削除されるまで MessageMarshaller の使用方法を示すコード例またはドキュメントは無視する必要があります。

2.2.1. ProtoStream プロセッサーの追加

Data Grid は、コンパイル時にクラスの Java アノテーションを処理する ProtoStream プロセッサーアーティファクトを提供し、Protobuf スキーマ、付随マーシャラー、および SerializationContextInitializer インターフェイスの具体的な実装を生成します。

手順

  • pom.xmlmaven-compiler-plugin のアノテーションプロセッサー設定に protostream-processor を追加します。

    <build>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>...</version>
          <configuration>
            <annotationProcessorPaths>
              <annotationProcessorPath>
                <groupId>org.infinispan.protostream</groupId>
                <artifactId>protostream-processor</artifactId>
                <version>...</version>
              </annotationProcessorPath>
            </annotationProcessorPaths>
          </configuration>
        </plugin>
      </plugins>
    </build>

2.2.2. ProtoStream アノテーションの Java クラスへの追加

Java クラスとそのメンバーにアノテーションを追加して ProtoStream メタデータを宣言します。次に、Data Grid は ProtoStream プロセッサーを使用して Protobuf スキーマと、それらのアノテーションから関連するマーシャラーを生成します。

手順

  1. フィールドで直接、または getter メソッドまたは setter メソッドのいずれかで、@ProtoField でマーシャリングする Java フィールドにアノテーションを付けます。

    Java クラスのアノテーションが付けられていないフィールドは一時的です。たとえば、Java クラスに 15 つのフィールドがあり、それらのうち 5 つにアノテーションを付けるとします。作成されるスキーマにはこれらの 5 つのフィールドのみが含まれ、これらの 5 つのフィールドのみが Data Grid にクラスインスタンスを保存するときにマーシャリングされます。

  2. @ProtoFactory を使用して、イミュータブルオブジェクトのコンストラクターにアノテーションを付けます。アノテーションが付けられたコンストラクターは @ProtoField アノテーションが付けられたフィールドをすべて初期化する必要があります。
  3. @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 オブジェクトクラスをマーシャリングすることができます。

手順

  1. 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 の具体的な実装を生成するように、@ProtoSchema アノテーションをインターフェイスに追加できます。

注記

デフォルトでは、生成された実装名は "Impl" 接尾辞が付いたアノテーション付きクラス名です。

手順

  1. GeneratedSchema を拡張するインターフェイスまたはそのスーパーインターフェイス SerializationContextInitializer を定義します。

    注記

    GeneratedSchema インターフェイスには Protobuf スキーマにアクセスするためのメソッドが含まれていますが、SerializationContextInitializer インターフェイスは登録メソッドのみをサポートします。

  2. インターフェイスに @ProtoSchema アノテーションを付けます。
  3. includeClasses パラメーターには、生成された SerializationContextInitializer 実装のすべてのクラスが含まれることを確認します。
  4. schemaFileName パラメーターで、生成された .proto スキーマの名前を指定します。
  5. schemaFilePath パラメーターで、スキーマファイルが生成される target/classes の下にパスを設定します。
  6. schemaPackageName パラメーターで、生成された .proto スキーマのパッケージ名を指定します。

次の例は、@ProtoSchema でアノテーションが付けられた GeneratedSchema インターフェイスを示しています。

@ProtoSchema(
      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. Protocol Buffers のベストプラクティス

Protocol Buffers のドキュメントには、下位互換性を維持するためにメッセージを設計する方法とスキーマを 進化させる 方法に関する ベストプラクティス のリストが記載されています。

Data Grid は、スキーマが更新されたときに自動的に互換性チェックを実行し、非互換性が検出された場合は更新を拒否できます。チェックの種類は、グローバル serialization 設定の schema-compatibility 属性を介して設定できます。利用可能なレベルは次のとおりです。

  • UNRESTRICTED: チェックは実行されない
  • LENIENT: ルールのサブセットが適用される
  • STRICT: すべてのルールが適用される (デフォルト)

次の表は、各レベルで有効になっている互換性チェックルールを示しています。

ルール説明レベル

予約フィールドを使用しない

現在の定義と更新された定義を比較し、メッセージの以前に予約されたフィールドまたは ID が同じメッセージの一部として使用されている場合は、警告のリストを返します。

LENIENTSTRICT

フィールド ID の変更なし

現在の定義と更新された定義を比較し、フィールド ID 番号が変更されている場合は、警告のリストを返します。

LENIENTSTRICT

フィールドタイプを変更なし

現在の定義と更新された定義を比較し、フィールドタイプが変更されている場合は、警告のリストを返します。

LENIENTSTRICT

予約なしでフィールドを削除しない

現在の定義と更新された定義を比較し、フィールド名または ID の対応する予約なしにフィールドが削除された場合は、警告のリストを返します。

LENIENTSTRICT

予約フィールドを削除しない

現在の定義と更新された定義を比較し、予約済みフィールドが削除されている場合は、警告のリストを返します。

STRICT

フィールド名を変更しない

現在の定義と更新された定義を比較し、メッセージの以前のフィールドの名前が変更されている場合は、警告のリストを返します。

STRICT

2.2.6. シリアル化コンテキストイニシャライザーの登録

組み込みキャッシュの場合、Data Grid は java.util.ServiceLoader を使用してアノテーションが付けられた SerializationContextInitializer 実装にシリアル化コンテキストおよびマーシャラーを自動的に登録します。

必要に応じて、SerializationContextInitializer 実装の自動登録を無効にして、手動で登録することができます。

重要

1 つの SerializationContextInitializer 実装を手動で登録する場合は、自動登録が無効になります。その後、他のすべての実装を手動で登録する必要があります。

手順

  1. ProtoSchema.service アノテーションの値を false に設定します。

    @ProtoSchema(
          includeClasses = SomeClass.class,
          ...
          service = false
    )
  2. 以下の例のように、プログラムまたは宣言的に SerializationContextInitializer 実装を手動で登録します。

宣言的

<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.7. 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 person
  • REST 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.8. 手動によるシリアル化コンテキストイニシャライザーの実装

重要

Data Grid は、SerializationContextInitializer または GeneratedSchema インターフェイスを手動で実装しないことを強く推奨します。

ProtobufTagMarshaller および RawProtobufMarshaller アノテーションを使用して SerializationContextInitializer または GeneratedSchema インターフェイスを手動で実装できます。

ただし、手動の実装には多くの面倒なオーバーヘッドが必要で、エラーが発生する可能性が高くなります。protostream-processor アーティファクトを使用して生成する実装は、ProtoStream マーシャリングを設定するより効率的で信頼できる方法です。

Red Hat logoGithubRedditYoutubeTwitter

詳細情報

試用、購入および販売

コミュニティー

Red Hat ドキュメントについて

Red Hat をお使いのお客様が、信頼できるコンテンツが含まれている製品やサービスを活用することで、イノベーションを行い、目標を達成できるようにします。

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。このような変更は、段階的に実施される予定です。詳細情報: Red Hat ブログ.

会社概要

Red Hat は、企業がコアとなるデータセンターからネットワークエッジに至るまで、各種プラットフォームや環境全体で作業を簡素化できるように、強化されたソリューションを提供しています。

© 2024 Red Hat, Inc.