第13章 REST API
13.1. REST インターフェース
Red Hat JBoss Data Grid は REST インターフェースを提供し、クライアントとサーバー間の疎結合を可能にします。REST インターフェースの主な利点は既存の HTTP クライアントとの相互運用性や、php クライアントへの接続の提供です。さらに、特定のバージョンのクライアントライブラリーやバインディングが必要ありません。
REST API によってオーバーヘッドが発生します。REST コールの理解や作成に REST クライアントまたはカスタムコードが必要になります。パフォーマンスに懸念がある場合は Hot Rod クライアントの使用が推奨されます。
Red Hat JBoss Data Grid の REST API と対話するには、HTTP クライアントライブラリーのみが必要です。Java の場合は、Apache HTTP Commons Client や java.net API になります。
以下の例は、REST セキュリティーが REST コネクターで無効になっていることを前提としています。REST セキュリティーを削除するには、コネクターから authentication
および encryption
要素を削除します。
13.2. Ruby クライアントコード
以下のコードは ruby を使用して Red Hat JBoss Data Grid の REST API と対話する例です。提供されたコードは特別なライブラリーを必要とせず、標準的な net/HTTP ライブラリーを使用できます。
Ruby での REST API の使用
require 'net/http' http = Net::HTTP.new('localhost', 8080) #An example of how to create a new entry http.post('/rest/MyData/MyKey', 'DATA_HERE', {"Content-Type" => "text/plain"}) #An example of using a GET operation to retrieve the key puts http.get('/rest/MyData/MyKey').body #An Example of using a PUT operation to overwrite the key http.put('/rest/MyData/MyKey', 'MORE DATA', {"Content-Type" => "text/plain"}) #An example of Removing the remote copy of the key http.delete('/rest/MyData/MyKey') #An example of creating binary data http.put('/rest/MyImages/Image.png', File.read('/Users/michaelneale/logo.png'), {"Content-Type" => "image/png"})
13.3. Ruby の例で JSON を使用
前提条件
ruby で JavaScript Object Notation (JSON
) を使用して Red Hat JBoss Data Grid の REST インターフェースと対話するには、JSON Ruby ライブラリーをインストールし (プラットフォームのパッケージマネージャーまたは Ruby ドキュメンテーションを参照)、以下のコードを使用して要件を宣言します。
require 'json'
Ruby での JSON の使用
以下のコードは、Ruby で JavaScript Object Notation (JSON
) と PUT
関数を使用して特定のデータ (この場合は、個人の名前と年齢) を送信する例です。
data = {:name => "michael", :age => 42 } http.put('/rest/Users/data/0', data.to_json, {"Content-Type" => "application/json"})
13.4. Python クライアントコード
以下のコードは Python を使用して Red Hat JBoss Data Grid の REST API と対話する例です。提供されたコードは、標準的な HTTP ライブラリーのみを必要とします。
Python での REST API の使用
import httplib #How to insert data conn = httplib.HTTPConnection("localhost:8080") data = "SOME DATA HERE \!" #could be string, or a file... conn.request("POST", "/rest/default/0", data, {"Content-Type": "text/plain"}) response = conn.getresponse() print response.status #How to retrieve data import httplib conn = httplib.HTTPConnection("localhost:8080") conn.request("GET", "/rest/default/0") response = conn.getresponse() print response.status print response.read()
13.5. Java クライアントコード
以下のコードは Java を使用して Red Hat JBoss Data Grid の REST API と対話する例です。
インポートの定義
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL;
String 値をキャッシュに追加
// Using the imports in the previous example public class RestExample { /** * Method that puts a String value in cache. * @param urlServerAddress * @param value * @throws IOException */ public void putMethod(String urlServerAddress, String value) throws IOException { System.out.println("----------------------------------------"); System.out.println("Executing PUT"); System.out.println("----------------------------------------"); URL address = new URL(urlServerAddress); System.out.println("executing request " + urlServerAddress); HttpURLConnection connection = (HttpURLConnection) address.openConnection(); System.out.println("Executing put method of value: " + value); connection.setRequestMethod("PUT"); connection.setRequestProperty("Content-Type", "text/plain"); connection.setDoOutput(true); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(connection.getOutputStream()); outputStreamWriter.write(value); connection.connect(); outputStreamWriter.flush(); System.out.println("----------------------------------------"); System.out.println(connection.getResponseCode() + " " + connection.getResponseMessage()); System.out.println("----------------------------------------"); connection.disconnect(); }
以下のコードは、Red Hat JBoss Data Grid REST インターフェースと対話するために Java を使用して URL に指定された値を読み取るメソッドの例です。
キャッシュから String 値を取得
// Continuation of RestExample defined in previous example /** * Method that gets an value by a key in url as param value. * @param urlServerAddress * @return String value * @throws IOException */ public String getMethod(String urlServerAddress) throws IOException { String line = new String(); StringBuilder stringBuilder = new StringBuilder(); System.out.println("----------------------------------------"); System.out.println("Executing GET"); System.out.println("----------------------------------------"); URL address = new URL(urlServerAddress); System.out.println("executing request " + urlServerAddress); HttpURLConnection connection = (HttpURLConnection) address.openConnection(); connection.setRequestMethod("GET"); connection.setRequestProperty("Content-Type", "text/plain"); connection.setDoOutput(true); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream())); connection.connect(); while ((line = bufferedReader.readLine()) != null) { stringBuilder.append(line + '\n'); } System.out.println("Executing get method of value: " + stringBuilder.toString()); System.out.println("----------------------------------------"); System.out.println(connection.getResponseCode() + " " + connection.getResponseMessage()); System.out.println("----------------------------------------"); connection.disconnect(); return stringBuilder.toString(); }
Java Main メソッドの使用
// Continuation of RestExample defined in previous example /** * Main method example. * @param args * @throws IOException */ public static void main(String[] args) throws IOException { //Note that the cache name is "cacheX" RestExample restExample = new RestExample(); restExample.putMethod("http://localhost:8080/rest/cacheX/1", "Infinispan REST Test"); restExample.getMethod("http://localhost:8080/rest/cacheX/1"); } }
13.6. REST インターフェースの使用
13.6.1. REST インターフェース操作
Red Hat JBoss Data Grid のリモートクライアントサーバーモードでは、クライアントが以下を実行できるようにする REST インターフェースが提供されます。
- データの追加
- データの取得
- データの削除
- データのクエリー
13.6.1.1. データ形式
REST API は、設定可能なメディアタイプによって定義される形式にデータを保存するキャッシュを公開します。
以下の XML スニペットは、キーと値のメディアタイプを定義する設定例になります。
<cache> <encoding> <key media-type="application/x-java-object; type=java.lang.Integer"/> <value media-type="application/xml; charset=UTF-8"/> </encoding> </cache>
13.6.1.2. デフォルトのデータ形式
デフォルトのメディアタイプはキーと値の両方で application/octet-stream
であり、以下の例外があります。
-
インデックス化されたキャッシュのデフォルトのメディアタイプは
application/x-protostream
です。 -
互換性モードを使用するキャッシュのデフォルトのメディアタイプは
application/x-java-object
です。
13.6.1.3. サポートされるデータ形式
Red Hat JBoss Data Grid では、クライアントは異なる形式のデータを読み書きでき、自動的に形式を変換できます。
JBoss Data Grid は、相互に交換可能なデータ形式を複数サポートします。
-
application/x-java-object
-
application/octet-stream
-
application/x-www-form-urlencoded
-
text/plain
JBoss Data Grid は、前述のリストにあるデータ形式が変換前および変換後となるデータ形式もサポートします。
-
application/xml
-
application/json
-
application/x-jboss-marshalling
-
application/x-java-serialized
-
application/x-protostream
さらに、JBoss Data Grid は application/x-protostream
と application/json
間の変換をサポートします。
13.6.1.4. ヘッダー
Red Hat JBoss Data Grid REST API への呼び出しは、以下を記述するヘッダーを提供できます。
- キャッシュに書き込まれたコンテンツ。
- キャッシュから読み取るときに必要なコンテンツのデータ形式。
JBoss Data Grid は、値に適用される HTTP/1.1 Content-Type
および Accept
ヘッダーと、キーの Key-Content-Type
ヘッダーをサポートします。
13.6.1.5. Accept ヘッダー
Red Hat JBoss Data Grid の REST サーバーは、Accept
ヘッダーの RFC-2616 仕様に準拠し、サポートされる変換を基にして適切なメディアタイプをネゴシエートします。
たとえば、キャッシュからデータを読み取るため、クライアントが呼び出しで以下のヘッダーを送信するとします。
Accept: text/plain;q=0.7, application/json;q=0.8, */*;q=0.6
この場合、ネゴシエーション中に JBoss Data Grid はメディアタイプの優先度が最も高い (0.8) JSON
形式を優先します。サーバーが JSON 形式をサポートしない場合、次に優先度が高い (0.7) text/plain
が優先されます。
サーバーが JSON
および text/plain
メディアタイプをサポートしない場合は、/
が優先されます。これは、キャッシュ設定を基にした適切なメディアタイプを意味します。
ネゴシエーションの終了後、サーバーは選択したメディアタイプを継続して操作に使用します。操作中にエラーが発生した場合、サーバーは他のメディアタイプの使用を試みません。
13.6.1.6. Key-Content-Type ヘッダー
REST API へのほとんどの呼び出しは URL にキーが含まれています。これらの呼び出しを処理するとき、Red Hat JBoss Data Grid はデフォルトで java.lang.String
をキーのコンテンツタイプとして使用します。しかし、Key-Content-Type
ヘッダーを使用して別のコンテンツタイプをキーに指定することもできます。
用途 | API 呼び出し | Header |
---|---|---|
|
|
|
|
|
|
ダブルキーを指定 |
|
|
application/x-java-object
の type
パラメーターはプリミティブラッパー型と java.lang.String
に制限されます。さらにこのパラメーターはバイトに制限され、結果として application/x-java-object;type=Bytes
が application/octet-stream;encoding=hex
と同等になります。
13.6.2. REST API を介したデータの追加
13.6.2.1. データをキャッシュに追加
以下のメソッドでデータをキャッシュに追加します。
-
HTTP
PUT
メソッド -
HTTP
POST
メソッド
PUT
および POST
メソッドで REST API を呼び出すとき、リクエストのボディーにはデータが含まれます。
13.6.2.2. PUT /{cacheName}/{cacheKey}
提供された URL フォームからの PUT
要求により、提供されたキーを使用して要求本文からのペイロードがターゲットキャッシュに配置されます。このタスクが正常に完了するには、ターゲットキャッシュがサーバーに存在する必要があります。
例として、以下の URL では値 hr
がキャッシュ名で payRoll%2F3
がキーになります。値 %2F
は、/
文字がキーで使用されたことを示しています。
http://someserver/rest/hr/payRoll%2F3
既存のデータが置き換えられ、必要な場合は Time-To-Live
および Last-Modified
の値が更新されます。
以下の引数を使用してサーバーが起動された場合は、キーの /
を表す値 %2F
を含むキャッシュキー (提供された例を参照) を正常に実行できます。
-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
13.6.2.3. POST /{cacheName}/{cacheKey}
提供された URL フォームからの POST
メソッドにより、提供されたキーを使用して (要求本文からの) ペイロードがターゲットキャッシュに配置されます。ただし、POST
メソッドでは、値がキャッシュ/キーに存在する場合に、HTTP CONFLICT
ステータスが返され、内容が更新されません。
13.6.2.4. PUT および POST メソッドのヘッダー
Header | 任意または必須 | 説明 |
---|---|---|
|
任意 |
URL のキーのコンテンツタイプを指定します。 |
|
任意 |
REST API に送信された値のメディアタイプを指定します。 |
|
任意 |
ブール値を指定します。値が |
|
任意 |
エントリーが自動的に削除されるまでの期間を秒数で指定します。負の値を指定すると、永久に削除されないエントリーが作成されます。 |
|
任意 |
エントリーがアイドル状態でいられる期間を秒数で指定します。この期間を過ぎるとエントリーは削除されます。負の値を指定すると、永久に削除されないエントリーが作成されます。 |
timeToLiveSeconds
ヘッダーおよび maxIdleTimeSeconds
ヘッダーには以下の組み合わせを設定できます。
-
timeToLiveSeconds
ヘッダーとmaxIdleTimeSeconds
ヘッダーの両方に値0
が割り当てられた場合、キャッシュは XML またはプログラムを使用して設定されたデフォルトのtimeToLiveSeconds
値とmaxIdleTimeSeconds
値を使用します。 -
maxIdleTimeSeconds
ヘッダー値のみが0
に設定された場合は、timeToLiveSeconds
値をパラメーターとして渡す必要があります (パラメーターが存在しない場合はデフォルトの-1
)。さらにmaxIdleTimeSeconds
パラメーター値は、デフォルトで XML またはプログラムを使用して設定された値に設定されます。 -
timeToLiveSeconds
ヘッダー値のみが0
に設定された場合は、エクスパレーションが即座に発生し、maxIdleTimeSeconds
値がパラメーターとして渡された値に設定されます (パラメーターが提供されなかった場合はデフォルトの-1
)。
13.6.3. REST API を介したデータの取得
13.6.3.1. キャッシュからのデータの取得
以下のメソッドでキャッシュからデータを取得します。
-
HTTP
GET
メソッド -
HTTP
HEAD
メソッド
13.6.3.2. GET /{cacheName}/{cacheKey}
GET
メソッドは、指定の cacheName
に存在し、関連するキーに一致するデータを応答の本文として返します。Content-Type ヘッダーは、データのタイプを提供します。ブラウザーはキャッシュに直接アクセスできます。
各エントリーに対して、要求された URL
でデータの状態を示す Last-Modified ヘッダーとともに一意のエンティティータグ (ETag) が返されます。ETag により、ブラウザー (および他のクライアント) は、(帯域幅を節約するために) データが変更された場合のみデータを要求できます。ETag は、HTTP 標準の一部であり、Red Hat JBoss Data Grid によりサポートされます。
格納されたコンテンツのタイプは、返されたタイプです。例として、String が格納された場合は、文字列が返されます。シリアライズされた形式で格納されたオブジェクトは、手動でデシリアライズする必要があります。
クエリーに extended
パラメーターを追加すると、追加の情報が返されます。例を以下に示します。
GET /{cacheName}/{cacheKey}?extended
以下のカスタムヘッダーが返されます。
-
Cluster-Primary-Owner
: キーのプライマリーオーナーであるノードを特定します。 -
Cluster-Node-Name
: リクエストを処理したサーバーの JGroups ノード名を指定します。 -
Cluster-Physical-Address
: リクエストを処理したサーバーの物理 JGroups アドレスを指定します。
13.6.3.3. HEAD /{cacheName}/{cacheKey}
HEAD
メソッドは、GET
メソッドと同様に動作しますが、コンテンツを返しません (ヘッダーフィールドが返されます)。
HEAD
メソッドは、追加情報を返す extended
パラメーターもサポートします。
13.6.3.4. GET /{cacheName}
GET
メソッドは、キャッシュに存在するキーのリストを返すことができます。返されるキーのリストは応答のボディーにあります。
Accept
ヘッダーは次のように応答をフォーマットできます。
-
application/xml
はキーのリストを XML 形式で返します。 -
application/json
はキーのリストを JSON 形式で返します。 -
text/plain
はキーのリストを行ごとに 1 つのキーで示したプレーンテキストで返します。
キャッシュが分散されている場合、リクエストを処理するノードが所有するキーのみが返されます。すべてのキーを返すには、次のようにクエリーに global
パラメータを追加します。
GET /{cacheName}?global
13.6.3.5. GET および HEAD メソッドのヘッダー
Header | 任意または必須 | 説明 |
---|---|---|
|
任意 |
URL のキーのコンテンツタイプを指定します。指定のない場合、デフォルトは |
|
任意 |
|
13.6.4. REST API を介したデータの削除
13.6.4.1. キャッシュからのデータの削除
HTTP DELETE
メソッドで Red Hat JBoss Data Grid からデータを削除します。
DELETE
メソッドは以下を行うことができます。
-
キャッシュエントリー/値を削除します (
DELETE /{cacheName}/{cacheKey}
) -
キャッシュからすべてのエントリーを削除します (
DELETE /{cacheName}
)
13.6.4.2. DELETE /{cacheName}/{cacheKey}
DELETE
メソッドがこのコンテキスト (DELETE /{cacheName}/{cacheKey}) で使用された場合、指定のキーのキャッシュからキー/値を削除します。
13.6.4.3. DELETE /{cacheName}
このコンテキスト (DELETE /{cacheName}
) では、DELETE
メソッドが名前付きキャッシュ内のすべてのエントリーを削除します。正常な DELETE
操作後に、HTTP ステータスコード 200
が返されます。
13.6.4.4. バックグラウンド削除操作
performAsync
ヘッダーの値を true
に設定して、削除操作がバックグラウンドで続行される状態で値がすぐに返されるようにします。
13.6.5. ETag ベースのヘッダー
ETag ベースのヘッダー
各 REST インターフェースエントリーに対して、提供された URL
でデータの状態を示す Last-Modified
ヘッダーとともに、ETag (エンティティータグ) が返されます。ETag は、帯域幅を節約するためにデータが変更された場合にのみ、データを要求する HTTP 操作で使用されます。以下のヘッダーは、ETag (エンティティータグ) ベースの楽観的ロックをサポートします。
Header | アルゴリズム | 例 | 説明 |
---|---|---|---|
If-Match |
If-Match = "If-Match" ":" ( "*" | 1#entity-tag ) |
- |
(リソースから以前に取得された) 指定されたエンティティーが最新であることを確認するために、関連するエンティティータグのリストとともに使用されます。 |
If-None-Match |
- |
(リソースから以前に取得された) 指定されたエンティティーが最新でないことを確認するために、関連するエンティティータグのリストとともに使用されます。この機能により、必要なときに、最小のトランザクションオーバーヘッドで、キャッシュされた情報が効率的に更新されます。 | |
If-Modified-Since |
If-Modified-Since = "If-Modified-Since" ":" HTTP-date |
If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT |
要求されたバリアントの最終変更日時と、提供された時間および日付の値とを比較します。指定された日時以降に要求されたバリアントが変更されなかった場合は、エンティティーの代わりに |
If-Unmodified-Since |
If-Unmodified-Since = "If-Unmodified-Since" ":" HTTP-date |
If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT |
要求されたバリアントの最終変更日時と、提供された時間および日付の値とを比較します。指定された日時以降に要求されたリソースが変更されなかった場合は、指定された操作が実行されます。指定された日時以降に要求されたリソースが変更された場合は、操作が実行されず、エンティティーの代わりに |
13.6.6. REST インターフェースを介したデータのクエリー
Red Hat JBoss Data Grid では、Ickle クエリーを JSON 形式で使用して、REST インターフェースを介してデータをクエリーできます。
JBoss Data Grid 7.2 では、REST インターフェースを介したデータのクエリーはテクノロジープレビューの機能となります。
13.6.6.1. JSON から Protostream への変換
JBoss Data Grid はプロトコルバッファーを使用して、データを効率的にバイナリー形式でキャッシュに保存し、クエリーを公開してコンテンツを JSON 形式で読み書きできるようにします。
Protobuf でエンコードされたエントリーを保存するには、キャッシュを application/x-protostream
メディアタイプで設定する必要があります。設定後、JBoss Data Grid は自動的に JSON を Protobuf に変換します。
キャッシュがインデックス化されている場合、設定を何も実行する必要はありません。デフォルトでは、インデックス化されたキャッシュはエントリーを application/x-protostream
メディアタイプで保存します。
しかし、キャッシュがインデックス化されていない場合、以下の例のようにキーと値を application/x-protostream
メディアタイプに設定する必要があります。
<cache> <encoding> <key media-type="application/x-protostream"/> <value media-type="application/x-protostream"/> </encoding> </cache>
13.6.6.2. Protobuf スキーマの登録
Protobuf スキーマを登録するには、以下の例のように HTTP POST
メソッドを使用して、スキーマを ___protobuf_metadata
キャッシュに挿入します。
curl -u user:password -X POST --data-binary @./schema.proto http://127.0.0.1:8080/rest/___protobuf_metadata/schema.proto
Protobuf のエンコーディングと Protobuf スキーマの登録についての詳細は、「Protobuf エンコーディング」を参照してください。
13.6.6.3. JSON ドキュメントの Protobuf メッセージへのマッピング
_type
フィールドが JSON ドキュメントに含まれるようにする必要があります。このフィールドは、JSON ドキュメントが対応する Protobuf メッセージを特定します。
たとえば、以下は Person
として定義された Protobuf メッセージになります。
message Person { required string name = 1; required int32 age = 2; }
以下は対応する JSON ドキュメントになります。
Person.json
{ "_type": "Person", "name": "user1", "age": 32 }
13.6.6.4. キャッシュへの内容の追加
以下のように、JSON 形式でキャッシュにコンテンツを書き込むことができます。
curl -u user:user -XPOST --data-binary @./Person.json -H "Content-Type: application/json; charset=UTF-8" http://127.0.0.1:8080/rest/{cacheName}/{key}
-
{cacheName}
はクエリーを行うキャッシュの名前を指定します。 -
{key}
はデータをキャッシュに保存するキーの名前を指定します。
コンテンツをキャッシュに書き込んだ後、以下のように JSON 形式で読み取ることができます。
curl -u user:user http://127.0.0.1:8080/rest/{cacheName}/{key}
13.6.6.5. REST エンドポイントのクエリー
HTTP GET
メソッドまたは POST
メソッドを使用して、REST インターフェース経由でデータのクエリーを行います。
GET
メソッドのクエリーリクエストの構造は次のようになります。
{cacheName}?action=search&query={ickle query}
-
{cacheName}
はクエリーを行うキャッシュの名前を指定します。 -
{ickle query}
は実行する Ickle クエリーを指定します。
以下はクエリーの例になります。
-
Person
という名前のエンティティーからすべてのデータを返す:http://localhost:8080/rest/mycache?action=search&query=from Person
-
select 句でクエリーを絞り込む:
http://localhost:8080/rest/mycache?action=search&query=Select name, age from Person
-
クエリーの結果をグループ化する:
http://localhost:8080/rest/mycache?action=search&query=from Person group by age
POST
メソッドのクエリーリクエストの構造は次のようになります。
{cacheName}?action=search
リクエストのボディーは、クエリーと JSON 形式のパラメーターを指定します。
以下は、Entity
という名前のエンティティーからデータを返し、where 句を使用して結果をフィルターするクエリーの例になります。
{ "query":"from Entity where name:\"user1\"", "max_results":20, "offset":10 }
13.6.6.5.1. 任意のリクエストパラメーター
以下の任意のパラメーターをクエリーリクエストに適用できます。
パラメーター | 説明 |
---|---|
|
クエリー結果の数をこの最大数に制限します。デフォルトの値は |
|
返す最初の結果のインデックスを指定します。デフォルトの値は |
|
サーバーがどのようにクエリーを実行するかを、以下の値で指定します。
|
13.6.6.5.2. クエリー結果
Ickle クエリーの結果は、以下の例のように JSON形式で返されます。
{ "total_results" : 150, "hits" : [ { "hit" : { "name" : "user1", "age" : 35 } }, { "hit" : { "name" : "user2", "age" : 42 } }, { "hit" : { "name" : "user3", "age" : 25 } } ] }
-
total_results
はクエリーが返した結果の数になります。 -
hits
はクエリーと一致するすべての結果をリストします。 -
hit
にはクエリーの各結果のフィールドが含まれます。
Ickle クエリーの詳細は、「Ickle クエリー言語を使用したクエリーの構築」を参照してください。