すべてのリソースには、リソースが変更されるたびに変更されるバージョン フィールド(etag
フィールド)があります。Etag は HTTP の標準的な部分であり、カレンダー API では次の 2 つのケースでサポートされています。
- リソースの変更時に、その間にこのリソースへの書き込みがなかったことを確認する(条件付き変更)
- リソースの取得時に、リソースが変更された場合にのみリソースデータを取得する(条件付き取得)
条件付き変更
最後に取得したときから変更されていない場合にのみリソースを更新または削除する場合は、以前の取得時の etag の値を含む If-Match
ヘッダーを指定できます。これは、リソースの変更が失われるのを防ぐために非常に便利です。クライアントは、リソースを再取得して変更を再適用できます。
エントリ(とその ETag)が前回の取得から変更されていない場合、変更は成功し、新しい ETag を含むリソースの新しいバージョンが返されます。そうでない場合は、412(前提条件が満たされなかった)レスポンス コードが返されます。
次のサンプルコード スニペットは、Java クライアント ライブラリを使用して条件付き変更を行う方法を示しています。
private static void run() throws IOException { // Create a test event. Event event = Utils.createTestEvent(client, "Test Event"); System.out.println(String.format("Event created: %s", event.getHtmlLink())); // Pause while the user modifies the event in the Calendar UI. System.out.println("Modify the event's description and hit enter to continue."); System.in.read(); // Modify the local copy of the event. event.setSummary("Updated Test Event"); // Update the event, making sure that we don't overwrite other changes. int numAttempts = 0; boolean isUpdated = false; do { Calendar.Events.Update request = client.events().update("primary", event.getId(), event); request.setRequestHeaders(new HttpHeaders().setIfMatch(event.getEtag())); try { event = request.execute(); isUpdated = true; } catch (GoogleJsonResponseException e) { if (e.getStatusCode() == 412) { // A 412 status code, "Precondition failed", indicates that the etag values didn't // match, and the event was updated on the server since we last retrieved it. Use // {@link Calendar.Events.Get} to retrieve the latest version. Event latestEvent = client.events().get("primary", event.getId()).execute(); // You may want to have more complex logic here to resolve conflicts. In this sample we're // simply overwriting the summary. latestEvent.setSummary(event.getSummary()); event = latestEvent; } else { throw e; } } numAttempts++; } while (!isUpdated && numAttempts <= MAX_UPDATE_ATTEMPTS); if (isUpdated) { System.out.println("Event updated."); } else { System.out.println(String.format("Failed to update event after %d attempts.", numAttempts)); } }
条件付き取得
前回取得したときから変更されている場合にのみリソースを取得する場合は、前回の取得時の etag の値を含む If-None-Match
ヘッダーを指定します。前回取得してからエントリ(およびその etag)が変更されている場合は、新しい etag を含むリソースの新しいバージョンが返されます。それ以外の場合は、304(変更なし)レスポンス コードが返されます。
次のサンプルコードのスニペットは、Java クライアント ライブラリを使用して条件付き取得を行う方法を示しています。
private static void run() throws IOException { // Create a test event. Event event = Utils.createTestEvent(client, "Test Event"); System.out.println(String.format("Event created: %s", event.getHtmlLink())); // Pause while the user modifies the event in the Calendar UI. System.out.println("Modify the event's description and hit enter to continue."); System.in.read(); // Fetch the event again if it's been modified. Calendar.Events.Get getRequest = client.events().get("primary", event.getId()); getRequest.setRequestHeaders(new HttpHeaders().setIfNoneMatch(event.getEtag())); try { event = getRequest.execute(); System.out.println("The event was modified, retrieved latest version."); } catch (GoogleJsonResponseException e) { if (e.getStatusCode() == 304) { // A 304 status code, "Not modified", indicates that the etags match, and the event has // not been modified since we last retrieved it. System.out.println("The event was not modified, using local version."); } else { throw e; } } }