Google Data Protocol のバッチ処理

バッチ処理を使用すると、各オペレーションを個別に送信しなくても、1 回のリクエストで複数のオペレーションを実行できます。

: 一括操作を実行するには、Google Data API クライアント ライブラリの最新バージョンを使用する必要があります。バッチ オペレーションは JavaScript クライアント ライブラリではサポートされていません。

対象者

このドキュメントは、バッチ処理を使用して 1 回のリクエストで複数のオペレーションを送信するプログラマを対象としています。

このドキュメントは、GData Java クライアント ライブラリの使用経験があることを前提としています。このドキュメントの例では、Java クライアント ライブラリを使用してバッチ オペレーションを実行する方法について説明します。

このドキュメントで紹介する例は Google Base Data API に固有のものです。ただし、他のサービスでバッチ機能を利用することもできます。

注: 他のクライアント ライブラリでもプロトコルと一般的な手順は同じですが、バッチ リクエストを実行する具体的な方法が異なる場合があります。クライアント ライブラリ固有のドキュメントを参照してください。

はじめに

GData バッチフィードを使用すると、挿入、更新、削除、クエリの各オペレーションを複数収集し、それらをまとめて送信、実行できます。

たとえば、次のフィードには 4 つのオペレーションが含まれています。

<feed>
  <entry>
    <batch:operation type="insert"/>
    ... what to insert ...
  </entry> 
  <entry>
    <batch:operation type="update"/>
    ... what to update ...
  </entry>
  <entry>
    <batch:operation type="delete"/>
    ... what to delete ...
  </entry>
  <entry>
    <batch:operation type="query"/>
    ... what to query ...
  </entry>
</feed>

サービスはリクエストされた変更を可能な限り多く実行し、各オペレーションの成功または失敗を評価するために使用できるステータス情報を返します。

バッチに含まれるオペレーションのうち、一部のオペレーションが失敗した場合でも、サービスはバッチ内で各オペレーションを実行しようとします。

バッチ リクエストの送信

バッチ リクエストは HTTP POST としてバッチ URL に送信します。サポートされるバッチ オペレーションは、フィードによって異なります。読み取り専用フィードはクエリのみをサポートしています。

特定のフィードがバッチ オペレーションをサポートしているかどうかを確認するには、フィードに対してクエリを実行します。フィードに「一括」リンクの関係が含まれている場合は、フィードが一括操作をサポートしていることを示します。

「バッチ」リンクの関係は、rel="http://schemas.google.com/g/2005#batch" を持つ <link> 要素です。リンク関係の href 属性は、バッチ オペレーション用のフィード ドキュメントを保存する URL を定義します。

たとえば、GET http://www.google.com/base/feeds/items(通常の Google Base の「items」フィード)を実行すると、次のようなレスポンスが返されます。

<feed xmlns=...
  <id>http://www.google.com/base/feeds/items</id>
  <link rel="http://schemas.google.com/g/2005#feed"
    type="application/atom+xml"
    href="http://www.google.com/base/feeds/items"/>
  <link rel="http://schemas.google.com/g/2005#post"
    type="application/atom+xml"
    href="http://www.google.com/base/feeds/items"/>
  <link rel="http://schemas.google.com/g/2005#batch"
    type="application/atom+xml"
    href="http://www.google.com/base/feeds/items/batch"/>
  ...
</feed> 

この例では、バッチ URL は http://www.google.com/base/feeds/items/batch です。

一括処理フィードの作成

オペレーション フィードには、挿入、更新、削除、またはクエリするエントリのリストが含まれます。 各オペレーションは <batch:operation type="insert|update|delete|query"/> 要素で定義されます。

この要素は、<feed> 要素の直接の子や、フィード内のエントリの直接の子、あるいはその両方になります。エントリに含まれている場合、その特定のエントリに対して実行するオペレーションを指定します。この要素をフィードに含めると、<batch:operation/> 要素を持たないエントリで実行するデフォルトのオペレーションが指定されます。

エントリもフィードもオペレーションを指定していない場合、デフォルトのオペレーションは insert です。

1 つのバッチフィードの同じエントリに複数の処理を適用することはできません。同じエントリに対して複数のオペレーションを指定した場合、結果は不確定です。

パフォーマンスを向上させるため、オペレーションはリクエストされた順序で処理されないことがあります。ただし、最終結果は、エントリが順番に処理されている場合と常に同じです。

サーバーに送信する XML のバイト数は 1 MB(1,048,576 バイト)以下にする必要があります。一般に、合計バイト数が 1 MB を超えない限り、リクエストできるオペレーション数に上限はありません。ただし、サービスによっては追加の制約があります。

一括オペレーションを使用するには、バッチ名前空間宣言を <feed> 要素に属性として追加する必要があります。

<feed 
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"
  ...
  xmlns:batch="http://schemas.google.com/gdata/batch">

挿入操作

挿入オペレーションは次のように表されます。

<batch:operation type="insert">

挿入オペレーションは、エントリの POST と同じです。オペレーションが成功すると、更新されたドキュメント <id> 要素と <batch:status code="201"/> 要素を含むエントリ コンテンツ全体が返されます。

正常な挿入リクエストの例を次に示します。

<entry>
  <title type="text">...</title>
  <content type="html">...</content>
  <batch:id>itemA</batch:id>
  <batch:operation type="insert"/>
  <g:item_type>recipes</g:item_type>
  ... 
</entry>

挿入リクエストが成功した場合のレスポンスの例を次に示します。

<entry>
  <batch:status code="201"/>
  <batch:id>itemA</batch:id>
  <batch:operation type="insert"/>
  <id>http://www.google.com/base/feeds/items/17437536661927313949</id>
  <link rel="self" type="application/atom+xml"
    href="http://www.google.com/base/feeds/items/17437536661927313949"/>
  <title type="text">...</title>
  <content type="html">...</content>
  <g:item_type>recipes</g:item_type>
  ... 
</entry>

更新オペレーション

<batch:operation type="update">

更新オペレーションは、エントリの <id> 要素によって参照される URL で PUT を実行するのと同じです。オペレーションが成功すると、<batch:status code="200"/> 要素とともにエントリのコンテンツ全体が返されます。

注: 一部のフィードでは、一括更新リクエストでエントリの rel="edit" リンクを指定する必要があります。これには、Google Data Protocol の v1 スタイルのオプティミスティック同時実行をサポートするフィードと、URL である ID がないフィードが含まれます。

更新リクエストの例を次に示します。

<entry>
  <id>http://www.google.com/base/feeds/items/17437536661927313949</id>
  <batch:operation type="update"/>
  ...
</entry>

正常なレスポンスの例を次に示します。

<entry>
  <batch:status code="200"/>
  <id>http://www.google.com/base/feeds/items/17437536661927313949</id>
  <batch:operation type="update"/>
  ... 
</entry>

注: 一部のフィードでは、他の人の変更を意図せず変更しないように、強力な ETag を使用しています。これらのフィードのいずれかでエントリの一括更新リクエストを行う場合は、そのエントリの gd:etag 属性に ETag 値を指定してください。例: <entry gd:etag="'F08NQAxFdip7IWA6WhVR'">...<batch:operation type="update"/>...

部分更新オペレーション

部分更新をサポートするフィードは、バッチ リクエストで使用することもできます。部分更新オペレーションは、エントリの <id> 要素によって参照される URL で PATCH を実行するのと同じです。オペレーションが成功すると、<batch:status code="200"/> 要素とともにエントリのコンテンツ全体が返されます。

注: 一部のフィードでは、一括更新リクエストでエントリの rel="edit" リンクを指定する必要があります。これには、Google Data Protocol の v1 スタイルのオプティミスティック同時実行をサポートするフィードと、URL である ID がないフィードが含まれます。

<batch:operation type="patch"/>

部分更新リクエストの例を次に示します。

<entry gd:fields="content" gd:etag="FE8LQQJJeSp7IWA6WhVa">
  <id>http://www.google.com/calendar/feeds/jo@gmail.com/private/full/entryID</id>
  <batch:operation type="patch"/>
  <title>New title</title>
</entry>

正常なレスポンスの例は次のとおりです。

<entry gd:etag="FE8LQQJJeSp7IWA6WhVa">
  <batch:status code="200"/>
  <id>http://www.google.com/calendar/feeds/jo@gmail.com/private/full/entryID</id>
  <batch:operation type="patch"/>
  <title>New title</title>
  <content></content>
  ...rest of the entry...
</entry>

オペレーションの削除

<batch:operation type="delete">

削除オペレーションは、エントリの <id> 要素によって参照される URL で DELETE を実行するのと同じです。削除オペレーションの場合は、 <id> 要素を送信するだけでエントリを削除できます。batch: 名前空間にない要素に指定しているその他の情報は無視されます。オペレーションが成功すると、同じ ID を持つエントリが <batch:status code="200"/> 要素とともに返されます。

注: 一部のフィードでは、一括削除リクエストでエントリの rel="edit" リンクを指定する必要があります。これには、Google Data Protocol の v1 スタイルのオプティミスティック同時実行をサポートするフィードと、URL である ID がないフィードが含まれます。

削除リクエストの例を次に示します。

<entry>
  <batch:operation type="delete"/>
  <id>http://www.google.com/base/feeds/items/17437536661927313949</id>
</entry>

正常なレスポンスの例を次に示します。

<entry>
  <batch:operation type="delete"/>
  <id>http://www.google.com/base/feeds/items/17437536661927313949</id>
  <batch:status code="200" reason="Success"/>
</entry>

注: 一部のフィードでは、他の人の変更を意図せず変更しないように、強力な ETag を使用しています。これらのフィードのいずれかでエントリの一括削除リクエストを行う場合は、エントリの gd:etag 属性に ETag 値を指定してください。たとえば、<entry gd:etag="'F08NQAxFdip7IWA6WhVR'">...<batch:operation type="delete"/>... です。

クエリ オペレーション

<batch:operation type="query">

クエリ オペレーションは、エントリの <id> 要素によって参照される URL で GET を実行するのと同じです。オペレーションが成功すると、エントリの内容全体が返されます。

注: 一部のフィードでは、一括クエリ リクエストでエントリの rel="self" リンクを指定する必要があります。これには、URL である ID がないフィードも含まれます。

クエリ リクエストの例を次に示します。

<entry>
  <id>http://www.google.com/base/feeds/items/1743753666192313949</id>
  <batch:operation type="query"/>
</entry>

正常なレスポンスの例を次に示します。

<entry>
  <id>http://www.google.com/base/feeds/items/1743753666192313949</id>
  <batch:operation type="query"/>
  <batch:status code="200" reason="Success"/>
   ...
</entry>

トラッキング オペレーション

GData エントリの結果は、必ずしもリクエストと同じ順序で返されるとは限りません。ID を使用して、その存続期間内のオペレーションを追跡できます。

更新、削除、クエリ操作については、エントリ自体の ID を使用して操作を追跡できます。

挿入操作では、ID がまだ存在しないため、操作識別子を渡すことができます。この ID を使用して、結果エントリをリクエスト エントリにリンクできます。オペレーション ID は <batch:id> 要素で渡されます。

GData はオペレーションごとに、オペレーションが成功したかどうかを示すレスポンスを返します。各レスポンスは、関連するエントリを示します。更新、削除、クエリ、または挿入オペレーションが成功すると、エントリ ID が常に返されます。バッチ ID を指定した場合は、これも返されます。挿入オペレーションでエラーが発生した場合、エントリ ID は関連付けられません。バッチ ID のみが返されます。

各オペレーションの識別子を使用して、失敗したオペレーションのみを再試行できます。オペレーションのバッチ全体を再送信する必要はありません。

<batch:id> の内容はクライアント定義の文字列値で、対応するレスポンス エントリにエコーバックされます。クライアントがレスポンスを元のリクエストのエントリに関連付けるのに役立つ任意の値を指定できます。この要素は、オペレーションが失敗した場合でも、対応するエントリでそのままエコーされます。GData がこのバッチ ID の内容を保存したり解釈したりすることはありません。

次の例は、一括処理フィードを示しています。<batch:id> 要素は、このオペレーションに itemB というラベルを付けます。

<entry>
  <title type="text">...</title>
  <content type="html">...</content>
  <batch:id>itemB</batch:id>
  <batch:operation type="insert"/>
  <g:item_type>recipes</g:item_type>
</entry>

次の例は、このオペレーションに応じて返されるバッチ ステータス エントリを示しています。

<entry>
  <id>http://www.google.com/base/feeds/items/2173859253842813008</id>
  <published>2006-07-11T14:51:43.560Z</published>
  <updated>2006-07-11T14:51: 43.560Z</updated>
  <title type="text">...</title>
  <content type="html">...</content>
  <link rel="self" 
    type="application/atom+xml" 
    href="http://www.google.com/base/feeds/items/2173859253842813008"/>
  <link rel="edit" 
    type="application/atom+xml" 
    href="http://www.google.com/base/feeds/items/2173859253842813008"/>
  <g:item_type>recipes</g:item_type>
  <batch:operation type="insert"/>
  <batch:id>itemB</batch:id>
  <batch:status code="201" reason="Created"/>
</entry>

ステータス コードの処理

ステータス コードは次の要素で表されます。

<batch:status code="200|201|404|500|..." reason="reason" [content-type="type"]/>

レスポンス フィード内の各エントリには、1 つの <batch:status> 要素が含まれています。この要素は、オペレーションの実行中に発生した内容を記述します。これは、操作がバッチ フィードの一部としてではなく個別に送信された場合に送信された HTTP レスポンスを模倣しています。

レスポンスの各エントリの <batch:status> 要素を確認して、関連するオペレーションが正常に処理されたかどうかを確認する必要があります。code="n" 属性には GData のステータス コードが含まれます。

ステータスの説明

<batch:status> 要素の reason="reason" 属性には、オペレーションのステータスに関する詳細な説明が含まれています。

コンテンツ タイプ

<batch:status> 要素の content-type="type" 属性には、<batch:status> 要素に含まれるデータの MIME タイプが含まれています。これは、HTTP ステータス レスポンスの Content-Type ヘッダーに対応します。この属性は省略可能です。

コンテンツ タイプが設定されている場合、<batch:status> 要素の本文には、エントリの処理中に発生した問題が記述されています。

中断されたオペレーションの特定

中断されたオペレーションのレスポンスには、次の要素が含まれます。

<batch:interrupted reason="reason" success="N" failures="N" parsed="N">

この要素は、バッチ処理が中断され、割り込みの原因の復元に失敗したことを意味します。一部のエントリが正常に処理されている可能性があります。この時点で成功したと報告されていないエントリはすべて破棄されました。

この要素は非常に一般的ではなく、通常は、リクエストの本文で送信されたフィードが正しい XML 形式ではないことを示します。

<batch:status> 要素と同様に、短いステータス コードが reason 属性にあります。要素内に長いレスポンスが表示されることもあります。

バッチ オペレーションとステータス フィードの例

サーバーに送信できるバッチ オペレーション フィードは次のとおりです。このフィードは、サーバーが 2 つのエントリを削除し、2 つの新しいエントリを追加するようリクエストします。以下の例でハイライト表示されているように、 <feed> 要素にはバッチの名前空間の宣言を含める必要があります。

POST : http://www.google.com/base/feeds/items/batch
<?xml version="1.0" encoding="UTF-8"?>
<feed
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"
  xmlns:g="http://base.google.com/ns/1.0"
  xmlns:batch="http://schemas.google.com/gdata/batch">
  <title type="text">My Batch Feed</title>
  <entry>
    <id>http://www.google.com/base/feeds/items/13308004346459454600</id>
    <batch:operation type="delete"/>
  </entry>
  <entry>
    <id>http://www.google.com/base/feeds/items/17437536661927313949</id>
    <batch:operation type="delete"/>
  </entry>
  <entry>
    <title type="text">...</title>
    <content type="html">...</content>
    <batch:id>itemA</batch:id>
    <batch:operation type="insert"/>
    <g:item_type>recipes</g:item_type>
  </entry>
  <entry>
    <title type="text">...</title>
    <content type="html">...</content>
    <batch:id>itemB</batch:id>
    <batch:operation type="insert"/>
    <g:item_type>recipes</g:item_type>
  </entry>
</feed>

2 つの挿入が機能し、2 つの削除のうち 1 つが失敗すると仮定します。この場合、バッチ ステータスのフィードは次のようになります。 エントリが、バッチ オペレーション フィードと比較して並べ替えられています。

<?xml version="1.0" encoding="UTF-8"?>
<feed
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"
  xmlns:g="http://base.google.com/ns/1.0"
  xmlns:batch="http://schemas.google.com/gdata/batch">
  <id>http://www.google.com/base/feeds/items</id>
  <updated>2006-07-11T14:51:42.894Z</updated>
  <title type="text">My Batch</title>
  <link rel="http://schemas.google.com/g/2005#feed"
    type="application/atom+xml"
    href="http://www.google.com/base/feeds/items"/>
  <link rel="http://schemas.google.com/g/2005#post"
    type="application/atom+xml"
    href="http://www.google.com/base/feeds/items"/>
  <link rel=" http://schemas.google.com/g/2005#batch"
    type="application/atom+xml"
    href="http://www.google.com/base/feeds/items/batch"/>
  <entry>
    <id>http://www.google.com/base/feeds/items/2173859253842813008</id>
    <published>2006-07-11T14:51:43.560Z</published>
    <updated>2006-07-11T14:51: 43.560Z</updated>
    <title type="text">...</title>
    <content type="html">...</content>
    <link rel="self"
      type="application/atom+xml"
      href="http://www.google.com/base/feeds/items/2173859253842813008"/>
    <link rel="edit"
      type="application/atom+xml"
      href="http://www.google.com/base/feeds/items/2173859253842813008"/>
    <g:item_type>recipes</g:item_type>
    <batch:operation type="insert"/>
    <batch:id>itemB</batch:id>
    <batch:status code="201" reason="Created"/>
  </entry>
  <entry>
    <id>http://www.google.com/base/feeds/items/11974645606383737963</id>
    <published>2006-07-11T14:51:43.247Z</published>
    <updated>2006-07-11T14:51: 43.247Z</updated>
    <title type="text">...</title>
    <content type="html">...</content>
    <link rel="self"
      type="application/atom+xml"
      href="http://www.google.com/base/feeds/items/11974645606383737963"/>
    <link rel="edit"
      type="application/atom+xml"
      href="http://www.google.com/base/feeds/items/11974645606383737963"/>
    <g:item_type>recipes</g:item_type>
    <batch:operation type="insert"/>
    <batch:id>itemA</batch:id>
    <batch:status code="201" reason="Created"/>
  </entry>
  <entry>
    <id>http://www.google.com/base/feeds/items/13308004346459454600</id>
    <updated>2006-07-11T14:51:42.894Z</updated>
    <title type="text">Error</title>
    <content type="text">Bad request</content>
    <batch:status code="404"
      reason="Bad request"
      content-type="application/xml">
      <errors>
        <error type="request" reason="Cannot find item"/>
      </errors>
    </batch:status>
  </entry>
  <entry>
    <id>http://www.google.com/base/feeds/items/17437536661927313949</id>
    <updated>2006-07-11T14:51:43.246Z</updated>
    <content type="text">Deleted</content>
    <batch:operation type="delete"/>
    <batch:status code="200" reason="Success"/>
  </entry>
</feed>

GData Java クライアント ライブラリのバッチ機能の使用

このセクションでは、GData Java クライアント ライブラリのバッチ機能を使用して、挿入、更新、削除のグループを一括で送信する方法について説明します。

このセクションの例では、Google Base API を使用しています。

まず、標準の GData クラスと Google Base クラスに加えて、必要なクラスをインポートします。

import com.google.gdata.data.batch.*;
import com.google.api.gbase.client.*;

バッチ リクエストを送信するには、フィードからバッチ URL を取得する必要があります。次のコード スニペットは、これを行うために、feed がフィードに関する情報を含む GoogleBaseFeed オブジェクトであると仮定しています。

Link batchLink = feed.getLink(Link.Rel.FEED_BATCH, Link.Type.ATOM);
if (batchLink != null) {
  URL batchUrl = new URL(batchLink.getHref());
  ... // batch handling
} else {
  // batching is not supported for this feed
}

次のコード スニペットでは、1 つのオペレーションに 2 つのエントリを挿入するフィードを準備しています。

GoogleBaseEntry entry1 = new GoogleBaseEntry();
...   // initialize entry 1 content
BatchUtils.setBatchId(entry1, "A"); // A is the local batch ID for this entry
feed.addEntry(entry1);
GoogleBaseEntry entry2 = new GoogleBaseEntry();
... // initialize entry 2 content
BatchUtils.setBatchId(entry2, "B"); // B is the local batch ID for this entry
feed.addEntry(entry2);

この例のコードでは、これらのエントリに対して実行されるオペレーションが insert であることを明示していません。挿入はデフォルトのオペレーションであるため、これを明示的に指定する必要はありません。

バッチフィードを送信して結果を受け取るには、Service.batch メソッドを呼び出します。

Service.insert と同様に、Service.batch は新しい <atom:id> 値が設定された挿入されたエントリを返します。返されたエントリは GoogleBaseFeed オブジェクトに含まれます。

他の 2 つのエントリを挿入する際に 3 つ目のエントリ(すでに取得して entry3 に保存している)を削除する場合は、次のコードを使用します。

GoogleBaseEntry toDelete = new GoogleBaseEntry();


toDelete.setId(entry3.getId());
BatchUtils.setBatchOperationType(toDelete, BatchOperationType.DELETE);

feed.addEntry(toDelete);


GoogleBaseFeed result = service.batch(batchUrl, feed);

ここで、servicecom.google.gdata.client.Service のインスタンスです。

エントリを更新するには、OperationType.UPDATE を指定し、ほとんどの場合空白ではなく、必要な変更でエントリを初期化します。

これらの例では、Google Base Data API を使用しています。service.batch を別のタイプの GData サービスとともに使用している場合は、GoogleBaseFeed クラス、GoogleBaseEntry クラス、GoogleBaseService クラスを、適切なフィード、エントリ、サービスクラスに置き換えます。

バッチ オペレーションの結果は、リクエストされた順序で返されるとは限りません。上記の例では、結果フィードに entry2 の後に entry1 が続く場合もあります。エントリが特定の順序で返されるとは限りません。

バッチ オペレーション フィードでは、トラッキング オペレーションで説明されているように、各挿入オペレーションに一意のバッチ ID を割り当てる必要があります。上記の例では、バッチ ID は AB です。そのため、リクエストしたオペレーションのステータスを確認するには、次のように、返されたバッチフィード内で各エントリを反復処理し、バッチ ID またはエントリ ID を比較する必要があります。

for (GoogleBaseEntry entry : result.getEntries()) {
  String batchId = BatchUtils.getBatchId(entry);      
  if (BatchUtils.isSuccess(entry)) {     
    if ("A".equals(batchId)) {       
      entry1 = entry;     } 
    else if ("B".equals(batchId)) {       
      entry2 = entry;     } 
    else if (BatchUtils.getBatchOperationType(entry) 
      == BatchOperationType.DELETE) {       
      System.out.println("Entry " + entry.getId() +
      " has been deleted successfully.");     
    }      
  } else {     
    BatchStatus status = BatchUtils.getBatchStatus(entry);     
    System.err.println(batchId + " failed (" +                
      status.getReason() + ") " +  status.getContent());      
    }    
  } 

返されたフィード内で表示される各エントリには、BatchStatus オブジェクトが関連付けられています。BatchStatus オブジェクトには、HTTP 戻りコードと、エントリの処理中に発生したエラーを説明するレスポンスが含まれます。各エントリの HTTP 戻りコードを確認して、オペレーションが成功したかどうかを確認する必要があります。

チェックは、上記の例のコンビニエンス メソッド BatchUtils.isSuccess によって行われます。この場合、BatchUtils.getBatchStatus(entry) < 300 と同じです。

ステータス コードとレスポンスの詳細については、ステータス コードの処理をご覧ください。

トップへ戻る