26 RESTによるグリッド操作の実行
この章の内容は次のとおりです。
- キーおよび値のタイプの指定
Coherence RESTサービスでは、公開されるキャッシュに関するメタデータが必要です。 - 単一オブジェクトのREST操作の実行
REST APIには、キャッシュ内の単一オブジェクト上での、GET、PUTおよびDELETE操作の実行のサポートが含まれます。 - 複数オブジェクトのREST操作の実行
複数オブジェクトの操作により、ユーザーは単一のネットワーク・リクエストで複数のオブジェクトを取得または削除できるため、ネットワークの使用量を著しく削減でき、ネットワークのパフォーマンスが向上します。 - 部分オブジェクトのREST操作の実行
GET操作を実行するときに、取得するオブジェクト属性を指定できます。 - RESTによる問合せの実行
Coherence RESTを使用すると、ユーザーはキャッシュの問合せを実行できます。 - RESTによる集計の実行
集計は、キャッシュ内のデータに対して実行できます。 - RESTによるエントリ処理の実行
エントリ・プロセッサは、キャッシュ内の1つまたは複数のオブジェクトで呼出しができます。 - 並列処理制御の理解
Coherence RESTでは、HTTPプロトコルに明確にマップされる場合のみ、オプティミスティック同時実行性をサポートします。 - キャッシュの別名の指定
キャッシュの別名は、単純化されたキャッシュ名を指定するために使用されます。別名は、キャッシュ名がREST URLパス・セグメントに最適でない場合に使用されます。 - サーバー送信イベントの使用
サーバー送信イベントではCoherence RESTアプリケーションでCoherenceクラスタからキャッシュ・イベントを自動的に受信できます。
親トピック: Coherence RESTの使用
キーおよび値のタイプの指定
coherence-rest-config.xml
ファイルを編集して、<key-class>
および<value-class>
要素を<resource>
要素の中に含め、それぞれにキーと値のタイプを設定します。「resource」を参照してください。
ノート:
<key-class>
および<value-class>
要素は、キャッシュ構成ファイルの<cache-mapping>
要素内または<resource>
要素内のいずれかに定義できます。
次の例では、String
キー・クラスおよびPerson
ユーザー・タイプの値クラスを定義します。
<resources> <resource> <cache-name>person</cache-name> <key-class>java.lang.String</key-class> <value-class>example.Person</value-class> </resource> </resources>
親トピック: RESTグリッド操作の実行
単一オブジェクトのREST操作の実行
GET操作
GET http://host:port/cacheName/key
キーに基づいて、キャッシュから単一オブジェクトを返します。指定されたキーのオブジェクトが存在しない場合、404 (Not Found)
のステータス・コードが返されます。get操作は部分的な結果をサポートします。「部分オブジェクトのREST操作の実行」を参照してください。オブジェクトにcom.tangosol.util.Versionsable
インタフェースが実装されている場合、条件付きのGET操作がサポートされます。応答にバージョンが付加され、クライアントのオブジェクトが最新バージョンかどうか判定するために使用されます。クライアントにオブジェクトの最新バージョンがすでにある場合は、304 (Not Modified)
のステータス・コードが返されます。
次のサンプル出力は、GET操作の応答を示しています。
* Client out-bound request > GET http://127.0.0.1:8080/dist-http-example/1 > Accept: application/xml * Client in-bound response < 200 < Content-Length: 212 < Content-Type: application/xml < <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Person><id>1</id><name> Mark</name><address><street>500 Oracle Parkway</street><city>Redwood Shores</city> <country>United States</country></address></Person> * Client out-bound request > GET http://127.0.0.1:8080/dist-http-example/1 > Accept: application/json * Client in-bound response < 200 < Content-Type: application/json < {"@type":"rest.Person","address":{"@type":"rest.Address","city":"Redwood Shores", "country":"United States","street":"500 Oracle Parkway"},"id":1,"name":"Mark"}
PUT操作
PUT http://host:port/cacheName/key
キャッシュで単一オブジェクトを作成または更新します。オブジェクトが更新された場合は、200 (OK)
のステータス・コードが返されます。オプティミスティック同時実行性チェックが失敗すると、409 (Conflict)
のステータス・コードと、エンティティとして現在のオブジェクトが返されます。「並列処理制御の理解」を参照してください。
次のサンプル出力は、PUT操作の応答を示しています。
* Client out-bound request > PUT http://127.0.0.1:8080/dist-test-sepx/1 > Content-Type: application/xml <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Person><id>1</id><name> Mark</name><address><street>500 Oracle Parkway</street><city>Redwood Shores</city> <country>United States</country></address></Person> * Client in-bound response < 200 < Content-Length: 0 < * Client out-bound request > PUT http://127.0.0.1:8080/dist-test-sepj/1 > Content-Type: application/json {"@type":"rest.Person","id":1,"name":"Mark","address":{"@type":"rest.Address","str eet":"500 Oracle Parkway","city":"Redwood Shores","country":"United States"}} * Client in-bound response < 200 < Content-Length: 0 <
Delete操作
DELETE http://host:port/cacheName/key
キーに基づいて、キャッシュから単一オブジェクトを削除します。オブジェクトが正常に削除された場合は200 (OK)
のステータス・コードが返され、指定されたキーのオブジェクトが存在しない場合は、404 (Not Found)
のステータス・コードが返されます。
親トピック: RESTグリッド操作の実行
複数オブジェクトのREST操作の実行
ノート:
PUT操作は、大量の破損データが生成される場合があるので、サポートされていません。特には、エンティティ・ボディ内の(シリアライズされた形式の)個々のオブジェクトを、対応するキーと同じ順序でURLに配置されることが求められます。また、更新により置換を行うため、オブジェクト全体のシリアライズされた形式を提供する必要があり、さらにオーバーヘッドが発生する場合があります。
GET操作
GET http://host:port/cacheName/(key1, key2, ...)
指定されたキーに基づいて、キャッシュからオブジェクトのセットを返します。返されるオブジェクトの順序は定義されず、URLのキー順序と一致する必要もありません。欠落したオブジェクトは、警告なしで結果から省略されます。200 (OK)
のステータス・コードが常に返されます。結果セットにオブジェクトがないと、空の結果セットが返されます。get操作は部分的な結果をサポートします。「部分オブジェクトのREST操作の実行」を参照してください。
DELETE操作
DELETE http://host:port/cacheName/(key1, key2, ...)
指定されたキーに基づいて、キャッシュから複数のオブジェクトを削除します。指定されたオブジェクトがキャッシュに存在しなくても、常に200 (OK)
のステータス・コードが返されます。
親トピック: RESTグリッド操作の実行
部分オブジェクトのREST操作の実行
p
として受け取ります。
次の例では、個人のid
およびname
属性のみを取得するget操作を実行します。
GET http://localhost:8080/people/123;p=id,name
住所のcountry
属性も含める場合、リクエストURLは次のようになります。
GET http://localhost:8080/people/123;p=id,name,address:(country)
この方法では、URLに対応した単純な表記を使用して、アプリケーションで必要なプロパティのみを選択的に取得できます。
次のサンプル出力は、GET操作の応答を示しています。
* Client out-bound request > GET http://127.0.0.1:8080/dist-test-sepj/1;p=name > Accept: application/json * Client in-bound response < 200 < Transfer-Encoding: chunked < Content-Type: application/json < {"name":"Mark"}
親トピック: RESTグリッド操作の実行
RESTによる問合せの実行
この項の内容は、次のとおりです。
直接問合せの使用
直接問合せは、REST URLでパラメータq
の値として送信できる問合せ式です。デフォルトで、問合せ式はURLエンコードのCohQL式として指定する必要があります(CohQLの述語句)。『Oracle Coherenceでのアプリケーションの開発』のエントリの結果セットでのフィルタリングに関する項を参照してください。直接問合せの構文は次のとおりです。
GET http://host:port/cacheName?q=query
たとえば、age
が18未満のPersonオブジェクトのperson
キャッシュを問い合せるとします。
GET http://host:port/person?q=age%3C18
デフォルトで直接問合せは無効です。直接問合せを有効にするには、coherence-rest-config.xml
ファイルを編集し、問合せ先のリソースごとに<direct-query>
要素を追加して、enabled
属性をtrue
に設定します。たとえば:
<resource> <cache-name>persons</cache-name> <key-class>java.lang.Integer</key-class> <value-class>example.Person</value-class> <direct-query enabled="true"/> </resource>
問合せが、直接問合せに対応していないリソースで実行された場合、403 (Forbidden)
の応答コードが返されます。
親トピック: RESTによる問合せの実行
名前付き問合せの使用
名前付き問合せは、coherence-rest-config.xml
ファイル内のリソースに対して構成する問合せ式です。デフォルトで、問合せ式はCohQL式として指定する必要があります(CohQLの述語句)。式をXMLファイル内で構成するため、特殊記号(<
および>
など)を対応するエンティティでエスケープする必要があります。『Oracle Coherenceでのアプリケーションの開発』のエントリの結果セットでのフィルタリングに関する項を参照してください。さらに、名前付き問合せには必要に応じてコンテキスト値を含めることができます。名前付き問合せの構文は次のとおりです。
GET http://host:port/cacheName/namedQuery?param1=value1,param2=value2...
名前付き問合せを指定するには、任意の数の<query>
要素を<resource>
要素内に追加します。それぞれの要素には、問合せ式と名前バインディングがあります。「query」を参照してください。たとえば:
<resource> <cache-name>persons</cache-name> <key-class>java.lang.Integer</key-class> <value-class>example.Person</value-class> <query> <name>minors</name> <expression>age < 18</expression> </query> <query> <name>first-name</name> <expression>name is :name</expression> </query> </resource>
名前付き問合せを使用するには、REST URL内に問合せの名前を入力します。この例では、前述の例で定義されたminors
名前付き問合せを使用しています。
GET http://host:port/persons/minors
パラメータには、コンテキスト値を問合せ式で置換えることができる柔軟性があります。次の例は、前述のfirst-name
問合せ式で定義された:name
パラメータを使用して、name
プロパティがMark
のエントリのみを問い合せます。
http://host:port/persons/first-name?name=Mark
パラメータ名の前にはコロン記号を付ける必要があります(:paramName
)。パラメータ・バインディングは型情報にアクセスできないため、比較演算子でTrueが予期される状況でFalseになる可能性があります。この動作を回避するために、問合せパラメータで型のヒントを指定します(:paramName;int
)。表26-1は、サポートされる型のヒントを示しています。
表26-1 パラメータ型のヒント
ヒント | 型 |
---|---|
i、int |
|
s、short |
|
l、long |
|
f、float |
|
d、double |
|
I |
|
D |
|
date |
|
uuid |
|
uid |
|
package.MyClass |
|
名前付き問合せは、集計およびエントリ処理とともに使用することもできます。「RESTによる集計の実行」および「RESTによるエントリ処理の実行」をそれぞれ参照してください。たとえば:
http://host:port/persons/first-name?name=Mark/long-max(age) http://host:port/persons/first-name?name=Mark/increment(age,1)
親トピック: RESTによる問合せの実行
問合せのソート順の指定
sort
マトリックス・パラメータは、REST URL内で使用されるオプションのパラメータです。これにより問合せから返された結果の順序を指定できます。sort
パラメータは、直接問合せと名前付け問合せの両方で使用できます。sort
パラメータの値は、ソートするプロパティのカンマ区切りリストを表し、それぞれにソート順を決定するオプションの:asc
(デフォルト)または:desc
修飾子を指定できます。たとえば、個人データのリストを名前の姓でソートし、家族のメンバーは年齢の大きい順にソートする場合、sort
パラメータは次のように定義します。
GET http://host:port/persons/minors;sort=lastName,age:desc
次の例は、直接問合せ内でsort
パラメータを使用します。
GET http://host:port/persons;sort=lastName,age:desc?q=age%3C18
親トピック: RESTによる問合せの実行
問合せ結果サイズの制限
大きなキャッシュに対する問合せは、メモリー不足エラーが発生する可能性のある大きな結果セットを返す可能性があります。大きなキャッシュを問合せる場合は、問合せでキーの使用がオプションである場合でも、常にキーを使用するようにしてください。キーが省略されると、問合せですべてのキャッシュ・エントリが返される場合があります。
クライアントに返される結果の数を制限する方法は、start
およびcount
マトリックス・パラメータを使用する方法と、max-results
属性を使用する方法の2つがあります。いずれの方法も、直接および名前付け問合せでサポートされます。
start
およびcount
パラメータは、返す結果のサブセットを決定するオプションの整数の引数です。次の例は、名前付け問合せでパラメータを使用し、名前によってソートされた最初の10のエントリを返します。
http://host:port/persons/minors;start=0;count=10;order=name:asc
次の例は、直接問合せ内でパラメータを使用しています。
GET http://host:port/persons;start=0;count=10?q=age%3C18
max-results
属性はcoherence-rest-config.xml
ファイル内で使用され、クライアントに返される結果の数を明示的に制限します。この属性では、キャッシュから返されるエントリの数が制限されないことに注意してください。次の例では、max-results
属性を設定します。
<resource max-results="50"> <cache-name>persons</cache-name> <key-class>java.lang.Integer</key-class> <value-class>example.Person</value-class> <direct-query enabled="true" max-results="25"> <query max-results="25"> <name>minors</name> <expression>age < 18</expression> </query> </resource>
両方が指定された場合、直接または名前付け問合せに対するmax-results
値は、リソースのmax-results
値を無視します。問合せがcount
パラメータを含んでおり、max-results
要素も指定されている場合、低い値の方が使用されます。
親トピック: RESTによる問合せの実行
キーのみの取出し
キャッシュに格納されたエントリのキーのみを検索することは可能です。キーの操作ではページングとソートはサポートされません。したがって、それらの問合せパラメータが送信された場合、無視されます。次のキーの取出し操作がサポートされています。
GET http://host:port/cacheName/keys
キャッシュ中のすべてのエントリのキーを返します。
GET http://host:port/cacheName/keys?q=query
直接問合せの基準を満たす、すべてのエントリのキーを返します。
GET http://host:port/cacheName/namedQuery/keys
名前付け問合せの基準を満たす、すべてのエントリのキーを返します。
親トピック: RESTによる問合せの実行
カスタム問合せエンジンの使用
ノート:
Coherence RESTのデフォルトの問合せエンジンでは、MvelExtractorが使用されます。デフォルトの問合せエンジンを使用するCoherence RESTユーザーは、MvelExtractorを使用してキャッシュ索引を作成する必要があります。この項には次のトピックが含まれます:
カスタム問合せエンジンの実装
カスタム問合せエンジンには、com.tangosol.coherence.rest.query.QueryEngine
とcom.tangosol.coherence.rest.query.Query
インタフェースを実装する必要があります。カスタム実装は、com.tangosol.coherence.rest.query.AbstractQueryEngine
ベース・クラスも拡張します。これにより、問合せ式の分析やパラメータ・バインドの処理を実行する有用なメソッドが提供されます。ベース・クラスでは、実行時のパラメータ置換と、問合せパラメータ値の一部として送信される型のヒントもサポートされます。パラメータ名および型のヒントはCohQL使用に従い、他の問合せエンジンの実装に使用できます。「名前付き問合せの使用」を参照してください。
次の例は、データベースに対してSQL問合せを直接実行し、キャッシュ・リードスルーを強制する簡単問合せエンジンの実装です。実際には、問合せエンジンの実装でランタイム・パラメータ・バインディングがサポートされる場合が多いでますが、この例にはありません。
public class SqlQueryEngine extends AbstractQueryEngine { protected Connection m_con; private static final String DB_DRIVER = "oracle.jdbc.OracleDriver"; private static final String DB_URL = "jdbc:oracle:thin:@localhost:1521:orcl"; private static final String DB_USERNAME = "username"; private static final String DB_PASSWORD = "password"; public SqlQueryEngine() { configureConnection(); } @Override public Query prepareQuery(String sQuery, Map<String, Object> mapParams) { ParsedQuery parsedQuery = parseQueryString(sQuery); String sSQL = createSelectPKQuery(parsedQuery.getQuery()); return new SqlQuery(sSQL); } protected void configureConnection() { try { Class.forName(DB_DRIVER); m_con = DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD); m_con.setAutoCommit(true); } catch (Exception e) { throw new RuntimeException(e); } } protected String createSelectPKQuery(String sSQL) { return "SELECT id,name,age FROM " + sSQL.substring(sSQL.toUpperCase().indexOf("FROM") + 4); } private class SqlQuery implements Query { protected String m_sql; public SqlQuery(String sql) { m_sql = sql; } @Override public Collection values(NamedCache cache, String sOrder, int nStart, int cResults) { // force read through Set setKeys = keySet(cache); return cache.getAll(setKeys).values(); } @Override public Set keySet(NamedCache cache) { Set setKeys = new HashSet(); try { PreparedStatement stmt = m_con.prepareStatement(m_sql); ResultSet result = stmt.executeQuery(); while (result.next()) { Object oKey = result.getLong(1); setKeys.add(oKey); Person person = new Person(result.getString("name"), result.getInt("age")); cache.put(oKey, person); } stmt.close(); } catch (SQLException e) { throw new RuntimeException(e); } return setKeys; } } }
親トピック: カスタム問合せエンジンの使用
カスタム問合せエンジンの有効化
カスタム問合せエンジンはcoherence-rest-config.xml
ファイルで有効化します。カスタム問合せエンジンを有効にするには、最初に<query-engines>
要素内に<engine>
を追加して実装を登録します。この要素には、問合せエンジンの名前と、実装クラスの完全修飾名が含まれています。「engine」を参照してください。たとえば:
<query-engines> <engine> <name>SQL-ENGINE</name> <class-name>package.SqlQueryEngine</class-name> </engine> </query-engines>
名前付け問合せまたは直接問合せのためのカスタム問合せエンジンを明示的に指定するには、<direct-query>
要素または<query>
要素内に、カスタム問合せエンジンの登録名を参照するengine
属性を追加します。たとえば:
<resource> <cache-name>persons</cache-name> <key-class>java.lang.Integer</key-class> <value-class>example.Person</value-class> <query engine="SQL-ENGINE"> <name>less-than-1000</name> <expression>select * from PERSONS where id < 1000</expression> </query> <direct-query enabled="true" engine="SQL-ENGINE"/> </resource>
カスタム問合せエンジンをデフォルトの問合せエンジンにするには、登録済の名前としてDEFAULT
(大文字が必須)を使用してください。次の定義はデフォルトCohQLベースの問合せエンジンをオーバーライドし、engine
属性を指定していない場合には自動的に使用されます。
<query-engines> <engine> <name>DEFAULT</name> <class-name>package.SqlQueryEngine</class-name> </engine> </query-engines>
親トピック: カスタム問合せエンジンの使用
RESTによる集計の実行
この項には次のトピックが含まれます:
RESTの集計の構文
次の例は、RESTを使用して集計を実行する方法を示します。集計に成功すると、200 (OK)
のステータス・コードがエンティティとして集約の結果とともに返されます。
-
キャッシュ内のすべてのエントリを集計します。
GET http://host:port/cacheName/aggregator(args, ...)
-
問合せ結果を集計します。問合せはURLエンコードのCohQL式として指定する必要があります(CohQLの述語句)。
GET http://host:port/cacheName/aggregator(args, ...)?q=query GET http://host:port/cacheName/namedQuery/aggregator(args, ...)?param1=value1
-
指定されたエントリを集計します。
GET http://host:port/cacheName/(key1, key2, ...)/aggregator(args, ...)
Coherence RESTは、(アグリゲータ関連のURLセグメントから)アグリゲータを作成するための簡単な戦略を提供します。初期状態のCoherence RESTでは、単一のタイプcom.tangosol.util.ValueExtractor
(LongMax
、DoubleMax
など)のパラメータを受け入れるコンストラクタにより、任意の登録された(組込みまたはユーザー登録の)アグリゲータを解決できます。URL内のアグリゲータのコールにパラメータが含まれない場合、com.tangosol.util.extractor.IdentityExtractor
を使用してアグリゲータが作成されます。
URL内のアグリゲータ・セグメントにパラメータが含まれない場合、または単一のValueExtractor
を受け入れるコンストラクタが存在しない場合、Coherence RESTはデフォルトのコンストラクタを使用してアグリゲータのインスタンス化を試行し、これは、一部の組込みのアグリゲータ(count
など)に最適な動作です。
次の例では、キャッシュ内で最も高齢な人を取得します。
GET http://host:port/people/long-max(age)
次の例では、数字のみを含むキャッシュで最大数を計算します。
GET http://host:port/numbers/comparable-max()
次の例では、個人データのキャッシュのサイズを計算します。
GET http://host:port/people/count()
親トピック: RESTによる集計の実行
事前定義のアグリゲータのリスト
次の事前定義のアグリゲータがサポートされます。
アグリゲータ名 | アグリゲータ |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
親トピック: RESTによる集計の実行
カスタム・アグリゲータの作成
カスタム・アグリゲータ・タイプを定義するには、REST URLで使用する名前と、com.tangosol.util.InvocableMap.EntryAggregator
インタフェースまたはcom.tangosol.coherence.rest.util.aggregator.AggregatorFactory
インタフェースを実装するクラスを指定します。
(ほとんどの事前定義のアグリゲータのように)集計が単一のプロパティまたはキャッシュ値自身で実行される場合、EntryAggregator
実装は単純なシナリオで使用されます。
より複雑な戦略が必要な場合、AggregatorFactory
インタフェースが使用されます。この実装で、アグリゲータ・パラメータを含むURLセグメントを解決し、それらのパラメータを使用して適切なアグリゲータを作成できる必要があります。
カスタム・アグリゲータは、coherence-rest-config.xml
ファイルの<aggregators>
要素で構成されます。「aggregator」を参照してください。次の例では、EntryAggregator
のカスタム実装とAggregatorFactory
のカスタム実装を構成しています。
<aggregators> <aggregator> <name>my-simple-aggr</name> <class-name>com.foo.MySimpleAggregator</class-name> </aggregator> <aggregator> <name>my-complex-aggr</name> <class-name>com.foo.MyAggreagatorFactory</class-name> </aggregator> </aggregators>
親トピック: RESTによる集計の実行
RESTによるエントリ処理の実行
この項には次のトピックが含まれます:
RESTのエントリ・プロセッサの構文
次の例は、RESTを使用してエントリ処理を実行する方法を示します。処理に成功すると、200 (OK)
のステータス・コードがエンティティとして処理の結果とともに返されます。
-
キャッシュ内のすべてのエントリを処理します。
POST http://host:port/cacheName/processor(args, ...)
-
問合せ結果を処理します。
POST http://host:port/cacheName/processor(args, ...)?q=query POST http://host:port/cacheName/namedQuery?param1=value1/processor(args, ...)
-
指定されたエントリを処理します。
POST http://host:port/cacheName/(key1, key2, ...)/processor (args, ...)
アグリゲータと異なり、プロセッサ(事前定義のプロセッサも含む)には、多彩な作成パターンがあるため、Coherence RESTではプロセッサの作成について何の想定もしていません。そのかわり、それぞれのエントリ・プロセッサ実装に対して、com.tangosol.coherence.rest.util.processor.ProcessorFactory
インタフェースの実装が存在する必要があります。これにより、URLセクションからの文字列の入力を処理して、プロセッサ・インスタンスをインスタンス化できます。Coherence RESTは、初期状態ではNumberIncrementor
およびNumberMultiplier
の2つのファクトリを備えています。
次の例では、キャッシュ内の各個人の年齢を5つ増加させます。
POST http://localhost:8080/people/increment(age, 5)
次の例では、数字のみを含むキャッシュ内の各数字を10倍します。
POST http://localhost:8080/numbers/multiply(10)
親トピック: RESTによるエントリ処理の実行
事前定義のエントリ・プロセッサのリスト
次の事前定義のプロセッサがサポートされます。
プロセッサ名 | プロセッサ |
---|---|
|
常に新しい(増加された)値を返す |
|
常に古い(増加されない)値を返す |
|
常に新しい(乗算された)値を返す |
|
常に古い(乗算されない)値を返す |
親トピック: RESTによるエントリ処理の実行
カスタム・エントリ・プロセッサの作成
カスタム・エントリ・プロセッサを定義するには、REST URLで使用される名前とcom.tangosol.coherence.rest.util.processor.ProcessorFactory
インタフェースを実装するクラスを指定します。
カスタム・エントリ・プロセッサは、coherence-rest-config.xml
ファイルの<processors>
要素内で構成されます。「processors」を参照してください。次の例では、ProcesorFactory
のカスタム実装を構成します。
<processors> <processor> <name>my-processor</name> <class-name>com.foo.MyProcessorFactory</class-name> </processor> </processors>
親トピック: RESTによるエントリ処理の実行
並列処理制御の理解
com.tangosol.util.Versionable
を実装するオブジェクトのGET
リクエストを送信する場合、現在のバージョン識別子がHTTP ETag
で返されます(オブジェクトの表現と同様に、バージョン識別子がJSON/XMLのシリアライズ形式に含まれると仮定されます)。アプリケーションが同じGET
リクエストをリソースに送信するとき、今回はIf-None-Match
ヘッダーに同じETag
値を使用する場合、Coherence RESTは、アプリケーションにはリソースの最新のバージョンがあることを示す304
のステータスを返します。
同様に、アプリケーションがPUT
リクエストを送信してオブジェクトを更新する際に、キャッシュ・オブジェクトでcom.tangosol.util.Versionable
インタフェースを実装していると、Coherence RESTは既存オブジェクトのバージョンと新規オブジェクトのバージョンが一致する場合のみ更新を実行します。それ以外の場合は、クライアントが変更を再度適用して再試行できるように、現在のオブジェクトとともに409 Conflict
ステータスが返されます。
次の例は、これらの概念について説明しています。
import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; import javax.ws.rs.core.MediaType; import org.codehaus.jettison.json.JSONObject; public class ConcurrencyTests { public static void main(String[] asArg) throws Exception { Client client = Client.create(); String url = "http://localhost:" + getPort() + "/dist-test1/2"; WebResource webResource = client.resource(url); // perform a GET of a server-side resource that implements Versionable ClientResponse response = webResource .accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); assert 200 == response.getStatus(); /* OK */ // verify that the current version of the resource is 1 JSONObject json = new JSONObject(response.getEntity(String.class)); String version = json.getString("versionIndicator"); assert "1".equals(version); assert new EntityTag("1").equals(response.getEntityTag()); // perform a conditional GET of the same resource and verify that we // get a response status of 304: Not Modified response = webResource .accept(MediaType.APPLICATION_JSON) .header ("If-None-Match", '"' + version + '"').get(ClientResponse.class); assert 304 == response.getStatus(); /* Not Modified */ // simulate a version change on the server-side by rolling back the // version indicator on our representation of the resource json.put("versionIndicator", String.valueOf(0)); // perform a conditional PUT of the same resource and verify that we // get a response status of 409: Conflict response = webResource .accept(MediaType.APPLICATION_JSON) .put(ClientResponse.class, json); assert 409 == response.getStatus(); /* Conflict */ // retry again with the returned value and verify that we now get a // response status of 200: OK json = new JSONObject(response.getEntity(String.class)); response = webResource .accept(MediaType.APPLICATION_JSON) .put(ClientResponse.class, json); assert 200 == response.getStatus(); /* OK */ } }
親トピック: RESTグリッド操作の実行
キャッシュの別名の指定
キャッシュの別名を定義するには、coherence-rest-config.xml
ファイルを編集して、<name>
要素を<resource>
要素内に含め、その値を単純化されたキャッシュ名に設定します。
次の例では、dist-extend-not-ideal-name-for-a-cache*
という名前のキャッシュに、people
という名前のキャッシュの別名を作成します。
<resources> <resource name="people"> <cache-name>dist-extend-not-ideal-name-for-a-cache*</cache-name> ... </resource> </resources>
親トピック: RESTグリッド操作の実行
サーバー送信イベントの使用
サーバー送信イベントでは、Grizzly HTTPサーバーまたはJetty HTTPサーバーのいずれかを使用する必要があります。「Grizzly HTTPサーバーの使用」および「Jetty HTTPサーバーの使用」をそれぞれ参照してください。また、サーバー送信イベントはWebブラウザでサポートされている必要があります。サポートの詳細は、ブラウザのドキュメントを参照してください。
この項には次のトピックが含まれます:
親トピック: RESTグリッド操作の実行
サーバー送信イベントの受信
Webページは、EventSource
オブジェクトを使用してサーバー送信イベントを受信します。EventSource
オブジェクトは、指定したURI に接続します(イベントが生成され、カスタムEventListeners
を追加して、サーバー送信の受信イベントがリスニングおよび処理されます)。Coherence RESTの例の次のコードでは、/cache/contacts
URIをリスニングしてinsert
、update
、delete
およびerror
イベントのイベント・リスナーを追加する新しいEventSource
オブジェクトを、JavaScriptを使用して作成します。
$scope.startListeningContacts = function() {
$scope.contacts.listening = true;
$scope.contacts.started = true;
if ($scope.contacts.filter == 'all') {
query = '';
}
else if ($scope.contacts.filter == '>=45') {
query = '?q=age%20>=%2045';
$scope.contacts.filter = 'age >= 45';
}
else {
query = '?q=age%20<%2045';
$scope.contacts.filter = 'age < 45';
}
$scope.contacts.status = 'Listening: ' + $scope.contacts.filter;
var eventSourceContacts = new EventSource('/cache/contacts' + query);
eventSourceContacts.addEventListener('insert', function(event) {
$scope.contacts.insertCount++;
$scope.contacts.allCount++;
$scope.updateContactEvent(JSON.parse(event.data), 'insert');
$scope.$apply();
});
eventSourceContacts.addEventListener('update', function(event) {
$scope.contacts.updateCount++;
$scope.contacts.allCount++;
$scope.updateContactEvent(JSON.parse(event.data), 'update');
$scope.$apply();
});
eventSourceContacts.addEventListener('delete', function(event) {
$scope.contacts.deleteCount++;
$scope.contacts.allCount++;
$scope.updateContactEvent(JSON.parse(event.data), 'delete');
$scope.$apply();
});
eventSourceContacts.addEventListener('error', function(event) {
var eventData = JSON.parse(event.data);
alert('error');
});
};
イベントが受信されると、イベントに基づいて、意味のあるアクションをアプリケーションで選択できます。たとえば:
$scope.updateContactEvent = function(eventData, eventType) { $scope.contacts.eventType = eventType; $scope.contacts.eventKey = eventData.key.firstName + ' ' + eventData.key.lastName; $scope.contacts.eventNewValue = 'N/A'; $scope.contacts.eventOldValue = 'N/A'; if (eventType == 'insert' || eventType == 'update') { $scope.contacts.eventNewValue = $scope.getContactString(eventData.newValue); } if (eventType == 'delete' || eventType == 'update') { $scope.contacts.eventOldValue = $scope.getContactString(eventData.oldValue); } };
親トピック: サーバー送信イベントの使用