SyncStack
SyncStack
The Sync API delivers the published content of a stack, then only the changes since your last sync. The SyncStack class holds one response of that API. Use this class to
- read the items of one sync batch
- request the next batch with the pagination token
- store the sync token for the next subsequent sync
Every sync method of the Stack class passes a SyncStack to the onCompletion(SyncStack syncStack, Error error) method of your SyncResultCallBack. On success, error is null. On failure, syncStack is null. See the Callbacks class page for the callback signature.
getCount
getCount returns the total_count value of this sync response.
Returns: int. The response's total_count value.
Validation
- There is no client-side validation. getCount reads a value that the SDK stored when the response arrived.
- getCount returns 0 when the response has no total_count key.
Behavior
- Client-side only. getCount sends no request.
- getCount returns the total_count value of the response body that the sync method received.
- See Which values each sync call fills on the SyncStack class page for the keys each response holds.
Example
Basic usage: print the total_count value of a sync response
import com.contentstack.sdk.Contentstack;
import com.contentstack.sdk.Error;
import com.contentstack.sdk.Stack;
import com.contentstack.sdk.SyncResultCallBack;
import com.contentstack.sdk.SyncStack;
public class PrintCountValue {
public static void main(String[] args) throws IllegalAccessException {
Stack stack = Contentstack.stack("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
stack.sync(new SyncResultCallBack() {
@Override
public void onCompletion(SyncStack syncStack, Error error) {
if (error != null) {
// The API rejected the request, or it did not complete
System.out.println("Request failed: " + error.getErrorCode() + " " + error.getErrorMessage());
return;
}
System.out.println("total_count: " + syncStack.getCount());
}
});
}
}getItems
getItems returns the items of this sync response, one JSON object per item.
Returns: List<JSONObject>. The items of this sync response.
Validation
- There is no client-side validation. getItems reads a value that the SDK stored when the response arrived.
- On a SyncStack that a sync callback receives, getItems never returns null. It returns an empty list when the response has no items key.
Behavior
- Client-side only. getItems sends no request.
- The list holds the items array of the response, the batch that Initial Sync, Sync using pagination token or Subsequent Sync returns.
- The SDK copies each item into a new JSONObject. In the top-level string values of the copy, it replaces <script> with <script> and </script> with </script>, in any letter case. Nested objects keep their original text. getJSONResponse returns the response without this change.
- The list holds one batch only. Use getPaginationToken to request the next batch.
Example
Basic usage: print each item of the first batch
import com.contentstack.sdk.Contentstack;
import com.contentstack.sdk.Error;
import com.contentstack.sdk.Stack;
import com.contentstack.sdk.SyncResultCallBack;
import com.contentstack.sdk.SyncStack;
import org.json.JSONObject;
import java.util.List;
public class PrintSyncItems {
public static void main(String[] args) throws IllegalAccessException {
Stack stack = Contentstack.stack("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
stack.sync(new SyncResultCallBack() {
@Override
public void onCompletion(SyncStack syncStack, Error error) {
if (error != null) {
// The API rejected the request, or it did not complete
System.out.println("Request failed: " + error.getErrorCode() + " " + error.getErrorMessage());
return;
}
List<JSONObject> items = syncStack.getItems();
System.out.println(items.size() + " items in this batch");
for (JSONObject item : items) {
System.out.println(item.toString());
}
}
});
}
}getJSONResponse
getJSONResponse returns the whole body of this sync response.
Returns: JSONObject. The whole sync response body.
Validation
- There is no client-side validation. getJSONResponse reads a value that the SDK stored when the response arrived.
Behavior
- Client-side only. getJSONResponse sends no request.
- The object holds every top-level key of the response, including keys that no other getter reads.
- IMPORTANT: Inside this object, the SDK stores nested objects as java.util.LinkedHashMap and arrays as java.util.ArrayList, not as JSONObject and JSONArray. So optJSONArray("items") and optJSONObject return null for keys that hold values. Read items with getItems, or read a nested value with get and cast it to java.util.List or java.util.Map.
- Top-level numbers and strings read normally with optInt and optString, and toString() prints the whole body as JSON.
Example
Basic usage: print the whole sync response
import com.contentstack.sdk.Contentstack;
import com.contentstack.sdk.Error;
import com.contentstack.sdk.Stack;
import com.contentstack.sdk.SyncResultCallBack;
import com.contentstack.sdk.SyncStack;
import org.json.JSONObject;
public class PrintSyncResponse {
public static void main(String[] args) throws IllegalAccessException {
Stack stack = Contentstack.stack("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
stack.sync(new SyncResultCallBack() {
@Override
public void onCompletion(SyncStack syncStack, Error error) {
if (error != null) {
// The API rejected the request, or it did not complete
System.out.println("Request failed: " + error.getErrorCode() + " " + error.getErrorMessage());
return;
}
JSONObject body = syncStack.getJSONResponse();
System.out.println(body.toString());
}
});
}
}Edge case: nested values are Java collections, not JSON types
import com.contentstack.sdk.Contentstack;
import com.contentstack.sdk.Error;
import com.contentstack.sdk.Stack;
import com.contentstack.sdk.SyncResultCallBack;
import com.contentstack.sdk.SyncStack;
import org.json.JSONObject;
import java.util.List;
public class ReadNestedSyncValue {
public static void main(String[] args) throws IllegalAccessException {
Stack stack = Contentstack.stack("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
stack.sync(new SyncResultCallBack() {
@Override
public void onCompletion(SyncStack syncStack, Error error) {
if (error != null) { System.out.println(error.getErrorMessage()); return; }
JSONObject body = syncStack.getJSONResponse();
// Prints null, because the SDK stores the items array as a java.util.List.
System.out.println(body.optJSONArray("items"));
Object items = body.opt("items");
if (items instanceof List) {
System.out.println(((List<?>) items).size() + " items");
}
}
});
}
}getLimit
getLimit returns the limit value of this sync response.
Returns: int. The response's limit value.
Validation
- There is no client-side validation. getLimit reads a value that the SDK stored when the response arrived.
- getLimit returns 0 when the response has no limit key.
Behavior
- Client-side only. getLimit sends no request.
- getLimit returns the limit value of the response body that the sync method received.
- See Which values each sync call fills on the SyncStack class page for the keys each response holds.
Example
Basic usage: print the limit value of a sync response
import com.contentstack.sdk.Contentstack;
import com.contentstack.sdk.Error;
import com.contentstack.sdk.Stack;
import com.contentstack.sdk.SyncResultCallBack;
import com.contentstack.sdk.SyncStack;
public class PrintLimitValue {
public static void main(String[] args) throws IllegalAccessException {
Stack stack = Contentstack.stack("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
stack.sync(new SyncResultCallBack() {
@Override
public void onCompletion(SyncStack syncStack, Error error) {
if (error != null) {
// The API rejected the request, or it did not complete
System.out.println("Request failed: " + error.getErrorCode() + " " + error.getErrorMessage());
return;
}
System.out.println("limit: " + syncStack.getLimit());
}
});
}
}getPaginationToken
getPaginationToken returns the token that requests the next batch of this sync.
Returns: String. The token for the next batch.
Validation
- There is no client-side validation. getPaginationToken reads a value that the SDK stored when the response arrived.
- getPaginationToken returns null when the response has no pagination_token key, which marks the last batch.
- getPaginationToken also returns null when the token holds a character other than a letter, a digit, -, _ or .. The SDK then logs a warning through java.util.logging.
Behavior
- Client-side only. getPaginationToken sends no request.
- The API returns a pagination token when more records remain, and repeats until it returns a sync token instead, as Sync using pagination token describes.
- The SDK does not request the next batch. Pass the token to the syncPaginationToken method of the Stack class until getPaginationToken returns null.
Example
Basic usage: request every batch until the sync completes
import com.contentstack.sdk.Contentstack;
import com.contentstack.sdk.Error;
import com.contentstack.sdk.Stack;
import com.contentstack.sdk.SyncResultCallBack;
import com.contentstack.sdk.SyncStack;
public class SyncEveryBatch {
public static void main(String[] args) throws IllegalAccessException {
final Stack stack = Contentstack.stack("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
stack.sync(new SyncResultCallBack() {
@Override
public void onCompletion(SyncStack syncStack, Error error) {
if (error != null) {
// The API rejected the request, or it did not complete
System.out.println("Request failed: " + error.getErrorCode() + " " + error.getErrorMessage());
return;
}
System.out.println(syncStack.getItems().size() + " items in this batch");
String paginationToken = syncStack.getPaginationToken();
if (paginationToken != null) {
// More records remain: request the next batch with this same callback
stack.syncPaginationToken(paginationToken, this);
} else {
System.out.println("Sync complete. Sync token: " + syncStack.getSyncToken());
}
}
});
}
}Recovery: resume an interrupted sync from a stored pagination token
import com.contentstack.sdk.Contentstack;
import com.contentstack.sdk.Error;
import com.contentstack.sdk.Stack;
import com.contentstack.sdk.SyncResultCallBack;
import com.contentstack.sdk.SyncStack;
public class ResumeSync {
public static void main(String[] args) throws IllegalAccessException {
Stack stack = Contentstack.stack("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
stack.syncPaginationToken("<PAGINATION_TOKEN>", new SyncResultCallBack() {
@Override
public void onCompletion(SyncStack syncStack, Error error) {
if (error != null) { System.out.println(error.getErrorMessage()); return; }
System.out.println(syncStack.getItems().size() + " items in this batch");
System.out.println("Next pagination token: " + syncStack.getPaginationToken());
}
});
}
}getSkip
getSkip returns the skip value of this sync response.
Returns: int. The response's skip value.
Validation
- There is no client-side validation. getSkip reads a value that the SDK stored when the response arrived.
- getSkip returns 0 when the response has no skip key.
Behavior
- Client-side only. getSkip sends no request.
- getSkip returns the skip value of the response body that the sync method received.
- See Which values each sync call fills on the SyncStack class page for the keys each response holds.
Example
Basic usage: print the skip value of a sync response
import com.contentstack.sdk.Contentstack;
import com.contentstack.sdk.Error;
import com.contentstack.sdk.Stack;
import com.contentstack.sdk.SyncResultCallBack;
import com.contentstack.sdk.SyncStack;
public class PrintSkipValue {
public static void main(String[] args) throws IllegalAccessException {
Stack stack = Contentstack.stack("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
stack.sync(new SyncResultCallBack() {
@Override
public void onCompletion(SyncStack syncStack, Error error) {
if (error != null) {
// The API rejected the request, or it did not complete
System.out.println("Request failed: " + error.getErrorCode() + " " + error.getErrorMessage());
return;
}
System.out.println("skip: " + syncStack.getSkip());
}
});
}
}getSyncToken
getSyncToken returns the token that the next subsequent sync starts from.
Returns: String. The token for the next subsequent sync.
Validation
- There is no client-side validation. getSyncToken reads a value that the SDK stored when the response arrived.
- getSyncToken returns null when the response has no sync_token key. A response without it has more batches to follow.
- getSyncToken also returns null when the token holds a character other than a letter, a digit, -, _ or .. The SDK then logs a warning through java.util.logging.
Behavior
- Client-side only. getSyncToken sends no request.
- The API returns the sync token on the last batch of a sync, as Sync using pagination token describes.
- Store the token and pass it to the syncToken method of the Stack class later. Subsequent Sync then returns only the changes since that sync.
Example
Basic usage: store the sync token after an initial sync
import com.contentstack.sdk.Contentstack;
import com.contentstack.sdk.Error;
import com.contentstack.sdk.Stack;
import com.contentstack.sdk.SyncResultCallBack;
import com.contentstack.sdk.SyncStack;
public class StoreSyncToken {
public static void main(String[] args) throws IllegalAccessException {
Stack stack = Contentstack.stack("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
stack.sync(new SyncResultCallBack() {
@Override
public void onCompletion(SyncStack syncStack, Error error) {
if (error != null) {
// The API rejected the request, or it did not complete
System.out.println("Request failed: " + error.getErrorCode() + " " + error.getErrorMessage());
return;
}
String syncToken = syncStack.getSyncToken();
if (syncToken == null) {
System.out.println("More batches remain. Use getPaginationToken first.");
return;
}
System.out.println("Store this sync token: " + syncToken);
}
});
}
}Subsequent sync: read the changes since a stored sync token
import com.contentstack.sdk.Contentstack;
import com.contentstack.sdk.Error;
import com.contentstack.sdk.Stack;
import com.contentstack.sdk.SyncResultCallBack;
import com.contentstack.sdk.SyncStack;
public class SubsequentSync {
public static void main(String[] args) throws IllegalAccessException {
Stack stack = Contentstack.stack("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
stack.syncToken("<SYNC_TOKEN>", new SyncResultCallBack() {
@Override
public void onCompletion(SyncStack syncStack, Error error) {
if (error != null) { System.out.println(error.getErrorMessage()); return; }
System.out.println(syncStack.getItems().size() + " changed items");
System.out.println("New sync token: " + syncStack.getSyncToken());
}
});
}
}getUrl
getUrl is meant to return the URL of the sync request.
Returns: String. The request URL field, which is always null.
Validation
- There is no client-side validation.
Behavior
- Known issue: getUrl always returns null, because the SDK never stores the request URL. Do not rely on it. The sync methods send their requests to /v3/stacks/sync on the host of the stack.
- Client-side only. getUrl sends no request.
Example
Basic usage: getUrl returns null
import com.contentstack.sdk.Contentstack;
import com.contentstack.sdk.Error;
import com.contentstack.sdk.Stack;
import com.contentstack.sdk.SyncResultCallBack;
import com.contentstack.sdk.SyncStack;
public class PrintSyncUrl {
public static void main(String[] args) throws IllegalAccessException {
Stack stack = Contentstack.stack("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
stack.sync(new SyncResultCallBack() {
@Override
public void onCompletion(SyncStack syncStack, Error error) {
if (error != null) {
// The API rejected the request, or it did not complete
System.out.println("Request failed: " + error.getErrorCode() + " " + error.getErrorMessage());
return;
}
// Prints null in this release.
System.out.println(syncStack.getUrl());
}
});
}
}