Contentstack Delivery Java SDK
Overview
This reference covers the public API of the com.contentstack.sdk:java package, with one page per class. Use it to look up method signatures, parameters, return types, validation behavior, and worked examples for every object you reach from a Stack.
Before you begin This reference assumes you have installed and initialized the SDK. If you have not, complete the Get Started with Java Delivery SDK guide first. This SDK requires Java 8 or later, because the package targets Java 1.8. This reference documents version 2.8.3, and the changelog lists behavior changes between releases.
Minimum Working Example
The program below creates a stack, fetches one entry of a content type, and prints its title.
import com.contentstack.sdk.Contentstack;
import com.contentstack.sdk.Entry;
import com.contentstack.sdk.EntryResultCallBack;
import com.contentstack.sdk.Error;
import com.contentstack.sdk.ResponseType;
import com.contentstack.sdk.Stack;
public class FetchEntry {
public static void main(String[] args) throws IllegalAccessException {
Stack stack = Contentstack.stack("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
Entry entry = stack.contentType("<CONTENT_TYPE_UID>").entry("<ENTRY_UID>");
entry.fetch(new EntryResultCallBack() {
@Override
public void onCompletion(ResponseType responseType, 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(entry.getTitle());
}
});
}
}SDK Structure
The SDK uses a builder pattern. Contentstack.stack returns a Stack that stores your credentials and settings. Each call from it returns an object for a narrower scope, such as a content type, an entry, a query, or an asset. A request method sends the request. Use fetch for a single item, find or findOne for a query, fetchAll for the asset list, findAll for global fields, and the sync methods for bulk retrieval. Every chain starts at the Stack.
Request methods do not return the result and do not throw when a request fails. Each one takes a callback, an object you write that overrides onCompletion. The SDK calls it with the result, or with an Error when the API rejects the request or the request does not complete. The Callbacks page lists which request method takes which callback.
Requests are synchronous. The SDK sends the request on the calling thread and runs the callback before the request method returns. Option methods store a value and send nothing, so an invalid option surfaces as an Error in the callback of the request. Some option methods on Query and AssetLibrary check their input first and stop the request instead. The class pages list these checks.
Class Overview
Set up the stack. The classes in the table below create and configure a stack.
| Class | Role | Accessed via |
|---|---|---|
| Contentstack | The entry point that creates a stack and looks up endpoint URLs for a region. | Contentstack.stack(...) |
| Stack | One stack and environment, and the start of every chain. | Contentstack.stack(apiKey, deliveryToken, environment) |
| Config | The optional settings of a stack, including region, host, branch, proxy, retry, and live preview. | new Config() |
| RetryOptions | The retry behavior for transient HTTP statuses and network errors. | new RetryOptions() |
Read content types and entries. The classes in the table below read content types, entries, and query results.
| Class | Role | Accessed via |
|---|---|---|
| ContentType | One content type and its schema. | stack.contentType(uid) |
| Entry | One entry of a content type. | contentType.entry(uid) |
| Group | The fields of one Group field of an entry. | entry.getGroup(key) |
| Query | A filtered list of the entries of one content type. | contentType.query() |
| QueryResult | The entries a query returns, with the count and content type when you ask for them. | the find callback |
Read assets, global fields, and taxonomies. The classes in the table below read assets and global fields, and find entries by taxonomy term.
| Class | Role | Accessed via |
|---|---|---|
| Asset | One published asset. | stack.asset(uid) |
| AssetLibrary | The list of published assets in the stack. | stack.assetLibrary() |
| GlobalField | One global field, or every global field, of the stack. | stack.globalField(uid) |
| Taxonomy | A query that finds entries by the taxonomy terms they carry. | stack.taxonomy() |
Sync content, and receive results and errors. The classes in the table below cover sync results, callbacks, and request errors.
| Class | Role | Accessed via |
|---|---|---|
| SyncStack | One batch of a sync, with its pagination or sync token. | the sync callback |
| Callbacks | The callback classes that receive the result of each request. | new EntryResultCallBack() { ... } |
| Error | The details of a request that failed. | the error argument of a callback |
Task Index
| Task | Start here | Class |
|---|---|---|
| Fetch one entry by UID | fetch | Entry |
| Filter entries by a field value | where | Query |
| Page through the entries of a content type | skip | Query |
| Return referenced entries in full | includeReference | Entry |
| Read an entry in another locale | setLocale | Entry |
| List the published assets in the stack | fetchAll | AssetLibrary |
| Resize or reformat an image on delivery | imageTransform | Stack |
| Filter entries by a taxonomy term and the terms below it | equalAndBelow | Taxonomy |
| Read the schema of a content type | fetch | ContentType |
| Sync all published content, then only what changed | sync | Stack |
| Set the region, branch, or proxy | Config | Config |
| Change the retry settings for failed requests | RetryOptions | RetryOptions |
Key Usage Patterns
Each example below is a complete Java program with its own imports and stack, so you can run it as is.
Filter and sort the entries of a content type
import com.contentstack.sdk.Contentstack;
import com.contentstack.sdk.Entry;
import com.contentstack.sdk.Error;
import com.contentstack.sdk.Query;
import com.contentstack.sdk.QueryResult;
import com.contentstack.sdk.QueryResultsCallBack;
import com.contentstack.sdk.ResponseType;
import com.contentstack.sdk.Stack;
public class FindRecentArticles {
public static void main(String[] args) throws IllegalAccessException {
Stack stack = Contentstack.stack("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
// The filter and sort methods store values. find sends the request.
Query query = stack.contentType("<CONTENT_TYPE_UID>").query();
query.exists("url").descending("updated_at").limit(10).includeCount();
query.find(new QueryResultsCallBack() {
@Override
public void onCompletion(ResponseType responseType, QueryResult queryResult, Error error) {
if (error != null) { System.out.println(error.getErrorMessage()); return; }
System.out.println("Showing " + queryResult.getResultObjects().size() + " of " + queryResult.getCount());
for (Entry entry : queryResult.getResultObjects()) {
System.out.println(entry.getTitle() + ": " + entry.getString("url"));
}
}
});
}
}Page through every entry of a content type
The SDK sends one request per find call and does not request further pages. The program below builds a new query for each page, and stops at the count that includeCount adds.
import com.contentstack.sdk.Contentstack;
import com.contentstack.sdk.Entry;
import com.contentstack.sdk.Error;
import com.contentstack.sdk.Query;
import com.contentstack.sdk.QueryResult;
import com.contentstack.sdk.QueryResultsCallBack;
import com.contentstack.sdk.ResponseType;
import com.contentstack.sdk.Stack;
public class ReadAllEntries {
public static void main(String[] args) throws IllegalAccessException {
Stack stack = Contentstack.stack("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
final int pageSize = 100;
final int[] total = {1};
for (int skip = 0; skip < total[0]; skip += pageSize) {
Query query = stack.contentType("<CONTENT_TYPE_UID>").query();
query.includeCount().skip(skip).limit(pageSize);
query.find(new QueryResultsCallBack() {
@Override
public void onCompletion(ResponseType responseType, QueryResult queryResult, Error error) {
if (error != null) { System.out.println(error.getErrorMessage()); total[0] = 0; return; }
// find runs synchronously, so the loop reads the new total before it continues
total[0] = queryResult.getCount();
for (Entry entry : queryResult.getResultObjects()) {
System.out.println(entry.getUid());
}
}
});
}
}
}Sync all published content, then only what changed
The SDK returns one batch per sync call. The program below requests the next batch with its pagination token until a batch has none, then prints the sync token to store for the next run.
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 SyncAllContent {
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) { System.out.println(error.getErrorMessage()); return; }
System.out.println("Items in this batch: " + syncStack.getItems().size());
if (syncStack.getPaginationToken() != null) {
stack.syncPaginationToken(syncStack.getPaginationToken(), this);
} else {
// Store this token, and pass it to syncToken on the next run to receive only the changes
System.out.println("Sync token: " + syncStack.getSyncToken());
}
}
});
}
}Connect to another region with a branch and custom retries
import com.contentstack.sdk.Config;
import com.contentstack.sdk.Contentstack;
import com.contentstack.sdk.Entry;
import com.contentstack.sdk.EntryResultCallBack;
import com.contentstack.sdk.Error;
import com.contentstack.sdk.ResponseType;
import com.contentstack.sdk.RetryOptions;
import com.contentstack.sdk.Stack;
public class FetchFromEuBranch {
public static void main(String[] args) throws IllegalAccessException {
// Set every option before you call stack. The stack reads the config once, when it is created.
Config config = new Config();
config.setRegion(Config.ContentstackRegion.EU);
config.setBranch("<BRANCH>");
config.setRetryOptions(new RetryOptions()
.setRetryLimit(5)
.setRetryDelay(500)
.setBackoffStrategy(RetryOptions.BackoffStrategy.LINEAR));
Stack stack = Contentstack.stack("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>", config);
Entry entry = stack.contentType("<CONTENT_TYPE_UID>").entry("<ENTRY_UID>");
entry.fetch(new EntryResultCallBack() {
@Override
public void onCompletion(ResponseType responseType, Error error) {
if (error != null) { System.out.println(error.getErrorMessage()); return; }
System.out.println(entry.getTitle());
}
});
}
}Tell a network failure from an API rejection
A timeout or network failure produces no API error body, so getErrorCode returns 0. For an API rejection, getErrorCode returns the API's own error code, such as 141, not the HTTP status. The program below handles the two cases separately.
import com.contentstack.sdk.Contentstack;
import com.contentstack.sdk.Entry;
import com.contentstack.sdk.EntryResultCallBack;
import com.contentstack.sdk.Error;
import com.contentstack.sdk.ResponseType;
import com.contentstack.sdk.Stack;
public class ReportFailures {
public static void main(String[] args) throws IllegalAccessException {
Stack stack = Contentstack.stack("<API_KEY>", "<DELIVERY_TOKEN>", "<ENVIRONMENT>");
Entry entry = stack.contentType("<CONTENT_TYPE_UID>").entry("<ENTRY_UID>");
entry.fetch(new EntryResultCallBack() {
@Override
public void onCompletion(ResponseType responseType, Error error) {
if (error == null) {
System.out.println(entry.getTitle());
} else if (error.getErrorCode() == 0) {
// No API error body: a timeout, a network failure, or a response the SDK could not read
System.out.println("Request did not complete: " + error.getErrorMessage());
} else {
// The API answered and rejected the request
System.out.println("API error " + error.getErrorCode() + ": " + error.getErrorMessage());
System.out.println("Details: " + error.getErrorDetail());
}
}
});
}
}SDK-Wide Notes
| Concern | Behavior | Default when unset |
|---|---|---|
| Authentication | Contentstack.stack takes the API key, delivery token, and environment, and every request from the stack sends them as the api_key, access_token, and environment headers. No other method takes credentials. | Not applicable. stack throws for a null or empty value, but does not check the token until the first request. |
| Error surfacing | Request methods do not throw for a failed request. The callback receives an Error with getErrorMessage, getErrorCode, and getErrorDetail, and the result argument is null. The HTTP status is not available. | Not applicable. A timeout or network failure gives error code 0. |
| Threading | Request methods run on the calling thread and call the callback before they return, including any retry waits. | Not applicable. |
| Regions and endpoints | Call setRegion on Config: US, EU, AU, AZURE_NA, AZURE_EU, GCP_NA, or GCP_EU. The stack resolves the delivery host for the region from the endpoint list bundled with the SDK. setHost overrides the region. | Config.ContentstackRegion.US, which resolves to cdn.contentstack.io. |
| Branches | Call setBranch on Config before you create the stack. The SDK sends it as the branch header on every request. | No branch header, so the API applies its default. |
| Rate limiting and retry | This SDK automatically retries on 429 with configurable delay and attempt limits. It also retries 408, 502, 503, 504, and network errors. See RetryOptions. | 3 retries, with waits of 1, 2, and 4 seconds. |
| Timeouts | The SDK has no timeout setting. The HTTP client, OkHttp, applies its own limits, and a request that times out reaches the callback as an Error whose message starts with Request timed out:. | 10 seconds to connect, 10 seconds to read, and 10 seconds to write. |
| Proxy configuration | Call setProxy on Config with a java.net.Proxy before you create the stack. | null, so the JVM's default proxy settings apply. |
| Settings after creation | Contentstack.stack reads the Config once. A change you make to the Config after stack returns does not change the host, region, branch, or headers of that stack. | Not applicable. |
Warning This SDK requires a delivery token. Contentstack.stack does not check the token, so a management token or a preview token in its place fails at the first request with an Error in the callback. For live preview, pass a preview token to setPreviewToken on Config instead. Refer to Content Delivery API Errors for the full error code list.
SDK Limitations
| Capability | Supported | Notes / Alternative |
|---|---|---|
| Read every page of a list in one call | No | Loop with skip and limit on a new query per page, as in Key Usage Patterns above. Request each sync batch with syncPaginationToken. |
| Receive the HTTP status of a failed request | No | Use getErrorCode, which holds the API's error code, and getErrorDetail. |
| Read date fields as correct Calendar values | No | The date getters return a date one month late. Read the raw value with getString and parse it with java.time.OffsetDateTime.parse. See the Entry class page. |
| Use characters such as @, /, :, or , in query values | No | Many Query methods reject those values and stop the request without calling the callback. To match such a string exactly, use the three-argument regex method, which checks nothing. See Input checks on the Query class page. |