メタデータ

このセクションでは、Spring Data REST ベースのアプリケーションによって提供されるさまざまな形式のメタデータについて詳しく説明します。

アプリケーションレベルのプロファイルセマンティクス (ALPS)

ALPS (英語) は、アプリケーションレベルのセマンティクスの簡単な説明を定義するためのデータ形式であり、複雑さは HTML マイクロ形式と似ています。ALPS ドキュメントは、アプリケーションに依存しないメディア型(HTML、HAL、Collection + JSON、Siren など)を持つドキュメントのアプリケーションセマンティクスを説明するためのプロファイルとして使用できます。これにより、メディア型間でプロファイルドキュメントの再利用性が向上します。
— M。アドムンドセン / L。リチャードソン / M。フォスター
https://tools.ietf.org/html/draft-amundsen-richardson-foster-alps-00

Spring Data REST は、エクスポートされたすべてのリポジトリに対して ALPS ドキュメントを提供します。これには、RESTful 遷移と各リポジトリの属性の両方に関する情報が含まれています。

Spring Data REST アプリのルートには、プロファイルリンクがあります。persons と関連する addresses の両方を含むアプリがあると仮定すると、ルートドキュメントは次のようになります。

{
  "_links" : {
    "persons" : {
      "href" : "http://localhost:8080/persons"
    },
    "addresses" : {
      "href" : "http://localhost:8080/addresses"
    },
    "profile" : {
      "href" : "http://localhost:8080/profile"
    }
  }
}

RFC 6906 [IETF] (英語) で定義されているプロファイルリンクは、アプリケーションレベルの詳細を含める場所です。ALPS ドラフト仕様 [IETF] (英語) は、特定のプロファイル形式を定義することを目的としています。これについては、このセクションの後半で説明します。

localhost:8080/profile のプロファイルリンクに移動すると、次のようなコンテンツが表示されます。

{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/profile"
    },
    "persons" : {
      "href" : "http://localhost:8080/profile/persons"
    },
    "addresses" : {
      "href" : "http://localhost:8080/profile/addresses"
    }
  }
}
ルートレベルでは、profile は単一のリンクであり、複数のアプリケーションプロファイルを提供することはできません。そのため、/profile に移動して、各リソースのメタデータへのリンクを見つける必要があります。

/profile/persons に移動し、Person リソースのプロファイルデータを見ると、次の例のようなコンテンツが表示されます。

{
  "version" : "1.0",
  "descriptors" : [ {
    "id" : "person-representation", (1)
    "descriptors" : [ {
      "name" : "firstName",
      "type" : "SEMANTIC"
    }, {
      "name" : "lastName",
      "type" : "SEMANTIC"
    }, {
      "name" : "id",
      "type" : "SEMANTIC"
    }, {
      "name" : "address",
      "type" : "SAFE",
      "rt" : "http://localhost:8080/profile/addresses#address"
    } ]
  }, {
    "id" : "create-persons", (2)
    "name" : "persons", (3)
    "type" : "UNSAFE", (4)
    "rt" : "#person-representation" (5)
  }, {
    "id" : "get-persons",
    "name" : "persons",
    "type" : "SAFE",
    "rt" : "#person-representation"
  }, {
    "id" : "delete-person",
    "name" : "person",
    "type" : "IDEMPOTENT",
    "rt" : "#person-representation"
  }, {
    "id" : "patch-person",
    "name" : "person",
    "type" : "UNSAFE",
    "rt" : "#person-representation"
  }, {
    "id" : "update-person",
    "name" : "person",
    "type" : "IDEMPOTENT",
    "rt" : "#person-representation"
  }, {
    "id" : "get-person",
    "name" : "person",
    "type" : "SAFE",
    "rt" : "#person-representation"
  } ]
}
1#person-representation として識別される Person リソースの属性の詳細なリストには、属性の名前がリストされています。
2 サポートされている操作。これは、新しい Person を作成する方法を示しています。
3name は persons です。これは、POST を単一の person ではなく、コレクション全体に適用する必要があることを示します(複数形であるため)。
4type は UNSAFE です。これは、この操作によってシステムの状態が変わる可能性があるためです。
5rt は #person-representation であり、返されるリソース型が Person リソースになることを示します。
この JSON ドキュメントのメディア型は application/alps+json です。これは、メディア型が application/hal+json であった以前の JSON ドキュメントとは異なります。これらのフォーマットは異なり、異なる仕様によって管理されます。

次の例に示すように、コレクションリソースを調べると、_links のコレクションに profile リンクがあります。

{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/persons" (1)
    },
    ... other links ...
    "profile" : {
      "href" : "http://localhost:8080/profile/persons" (2)
    }
  },
  ...
}
1 この HAL ドキュメントは、Person コレクションを表しています。
2 メタデータの同じ URI へのプロファイルリンクがあります。

繰り返しますが、デフォルトでは、profile リンクは ALPS を提供します。ただし、Accept ヘッダー [W3C] (英語) を使用する場合は、application/alps+json を提供できます。

ハイパーメディア制御型

ALPS は、各ハイパーメディアコントロールの型を表示します。それらが含まれます:

表 1: ALPS 型
タイプ 説明

SEMANTIC

状態要素(HTML.SPANHTML.INPUT など)。

SAFE

安全なべき等状態遷移をトリガーするハイパーメディアコントロール(GET や HEAD など)。

IDEMPOTENT

安全でないべき等状態遷移(PUT や DELETE など)をトリガーするハイパーメディアコントロール。

UNSAFE

安全ではない、べき等ではない状態遷移(POST など)をトリガーするハイパーメディアコントロール。

前に示した表現セクションでは、アプリケーションからのデータのビットが SEMANTIC としてマークされています。address フィールドは、安全な GET を取得するためのリンクです。SAFE としてマークされます。ハイパーメディア操作自体は、前の表に示すように型にマップされます。

射影のある ALPS

射影を定義すると、それらは ALPS メタデータにもリストされます。inlineAddress と noAddresses も定義したとすると、それらは関連する操作の中に表示されます。(これら 2 つの射影の定義と説明については、"射影" を参照してください)つまり、GET はコレクション全体の操作に表示され、GET は単一のリソースの操作に表示されます。次の例は、get-persons サブセクションの代替バージョンを示しています。

...
  {
    "id" : "get-persons",
    "name" : "persons",
    "type" : "SAFE",
    "rt" : "#person-representation",
    "descriptors" : [ { (1)
      "name" : "projection",
      "doc" : {
        "value" : "The projection that shall be applied when rendering the response. Acceptable values available in nested descriptors.",
        "format" : "TEXT"
      },
      "type" : "SEMANTIC",
      "descriptors" : [ {
        "name" : "inlineAddress", (2)
        "type" : "SEMANTIC",
        "descriptors" : [ {
          "name" : "address",
          "type" : "SEMANTIC"
        }, {
          "name" : "firstName",
          "type" : "SEMANTIC"
        }, {
          "name" : "lastName",
          "type" : "SEMANTIC"
        } ]
      }, {
        "name" : "noAddresses", (3)
        "type" : "SEMANTIC",
        "descriptors" : [ {
          "name" : "firstName",
          "type" : "SEMANTIC"
        }, {
          "name" : "lastName",
          "type" : "SEMANTIC"
        } ]
      } ]
    } ]
  }
...
1 新しい属性 descriptors が表示され、1 つのエントリ projection を持つ配列が含まれます。
2projection.descriptors の内部には、inLineAddress が表示されます。addressfirstNamelastName をレンダリングします。射影内にレンダリングされた関連により、データフィールドがインラインで含まれます。
3noAddresses は、firstName と lastName を含むサブセットを提供します。

これらすべての情報を使用して、クライアントは利用可能な RESTful トランジションだけでなく、バックエンドとの対話に必要なデータ要素もある程度推測できます。

ALPS の説明にカスタムの詳細を追加する

ALPS メタデータに表示されるカスタムメッセージを作成できます。これを行うには、次のように rest-messages.properties を作成します。

rest.description.person=A collection of people
rest.description.person.id=primary key used internally to store a person (not for RESTful usage)
rest.description.person.firstName=Person's first name
rest.description.person.lastName=Person's last name
rest.description.person.address=Person's address

これらの rest.description.* プロパティは、Person リソースに表示する詳細を定義します。これらは、person-representation の ALPS 形式を次のように変更します。

...
  {
    "id" : "person-representation",
    "doc" : {
      "value" : "A collection of people", (1)
      "format" : "TEXT"
    },
    "descriptors" : [ {
      "name" : "firstName",
      "doc" : {
        "value" : "Person's first name", (2)
        "format" : "TEXT"
      },
      "type" : "SEMANTIC"
    }, {
      "name" : "lastName",
      "doc" : {
        "value" : "Person's last name", (3)
        "format" : "TEXT"
      },
      "type" : "SEMANTIC"
    }, {
      "name" : "id",
      "doc" : {
        "value" : "primary key used internally to store a person (not for RESTful usage)", (4)
        "format" : "TEXT"
      },
      "type" : "SEMANTIC"
    }, {
      "name" : "address",
      "doc" : {
        "value" : "Person's address", (5)
        "format" : "TEXT"
      },
      "type" : "SAFE",
      "rt" : "http://localhost:8080/profile/addresses#address"
    } ]
  }
...
1rest.description.person の値は、表現全体にマッピングされます。
2rest.description.person.firstName の値は、firstName 属性にマップされます。
3rest.description.person.lastName の値は、lastName 属性にマップされます。
4rest.description.person.id の値は、通常は表示されないフィールドである id 属性にマップされます。
5rest.description.person.address の値は、address 属性にマップされます。

これらのプロパティ設定を指定すると、各フィールドに追加の doc 属性が追加されます。

Spring MVC (Spring Data REST アプリケーションの本質) はロケールをサポートしています。つまり、異なるメッセージを持つ複数のプロパティファイルをバンドルできます。

JSON スキーマ

JSON スキーマ (英語) は、Spring Data REST によってサポートされる別の形式のメタデータです。彼らの Web サイトによると、JSON スキーマには次の利点があります。

  • 既存のデータ形式について説明します

  • 明確で人間および機械が読み取り可能なドキュメント

  • 完全な構造検証。自動テストとクライアントから送信されたデータの検証に役立ちます

前のセクションで示したように、ルート URI から profile リンクに移動することで、このデータにアクセスできます。

{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/profile"
    },
    "persons" : {
      "href" : "http://localhost:8080/profile/persons"
    },
    "addresses" : {
      "href" : "http://localhost:8080/profile/addresses"
    }
  }
}

これらのリンクは前に示したものと同じです。JSON スキーマを取得するには、次の Accept ヘッダーを使用して JSON スキーマを呼び出すことができます: application/schema+json

この場合、curl -H 'Accept:application/schema+json' localhost:8080/profile/persons を実行すると、次のような出力が表示されます。

{
  "title" : "org.springframework.data.rest.webmvc.jpa.Person", (1)
  "properties" : { (2)
    "firstName" : {
      "readOnly" : false,
      "type" : "string"
    },
    "lastName" : {
      "readOnly" : false,
      "type" : "string"
    },
    "siblings" : {
      "readOnly" : false,
      "type" : "string",
      "format" : "uri"
    },
    "created" : {
      "readOnly" : false,
      "type" : "string",
      "format" : "date-time"
    },
    "father" : {
      "readOnly" : false,
      "type" : "string",
      "format" : "uri"
    },
    "weight" : {
      "readOnly" : false,
      "type" : "integer"
    },
    "height" : {
      "readOnly" : false,
      "type" : "integer"
    }
  },
  "descriptors" : { },
  "type" : "object",
  "$schema" : "https://json-schema.org/draft-04/schema#"
}
1 エクスポートされた型
2 プロパティのリスト

リソースに他のリソースへのリンクがある場合は、詳細が表示されます。

次の例に示すように、コレクションリソースを調べると、_links のコレクションに profile リンクがあります。

{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/persons" (1)
    },
    ... other links ...
    "profile" : {
      "href" : "http://localhost:8080/profile/persons" (2)
    }
  },
  ...
}
1 この HAL ドキュメントは、Person コレクションを表しています。
2 メタデータの同じ URI へのプロファイルリンクがあります。

この場合も、profile リンクはデフォルトで ALPS を提供します。application/schema+jsonAccept ヘッダー [W3C] (英語) を指定すると、JSON スキーマ表現がレンダリングされます。