Learn how to set up and use the Java SDK.
This step-by-step guide leads you through setting up and making API calls using the Java SDK.
Requirements
To follow this guide you should have the following:
- A commercetools Project
- An API Client
- Java 8 (or later)
Objectives of the get started guide
After following this guide you will have:
Placeholder values
Example code in this guide uses the following placeholder values. You should replace these placeholders with the following values.
| Placeholder | Replace with | From |
|---|---|---|
{projectKey} | project_key | your API Client |
{clientID} | client_id | your API Client |
{clientSecret} | secret | your API Client |
{scope} | scope | your API Client |
{region} | your Region | Hosts |
Install the Java SDK
Gradle
build.gradle file.latest.release with the version number. ext {
versions = [
commercetools: "latest.release"
]
}
repositories {
mavenCentral()
}
dependencies {
implementation "com.commercetools.sdk:commercetools-http-client:${versions.commercetools}"
implementation "com.commercetools.sdk:commercetools-sdk-java-api:${versions.commercetools}"
}
For Import API
For Audit Log API
For Checkout API
implementation "com.commercetools.sdk:commercetools-sdk-java-importapi:${versions.commercetools}"
Maven
pom.xml file.LATEST with the version number. <properties>
<commercetools.version>LATEST</commercetools.version>
</properties>
<dependencies>
<dependency>
<groupId>com.commercetools.sdk</groupId>
<artifactId>commercetools-http-client</artifactId>
<version>${commercetools.version}</version>
</dependency>
<dependency>
<groupId>com.commercetools.sdk</groupId>
<artifactId>commercetools-sdk-java-api</artifactId>
<version>${commercetools.version}</version>
</dependencies>
For Import API
For Audit Log API
For Checkout API
<dependency>
<groupId>com.commercetools.sdk</groupId>
<artifactId>commercetools-sdk-java-importapi</artifactId>
<version>${commercetools.version}</version>
</dependency>
Maven Central
commercetools-http-client.HTTP client modules
The following HTTP client modules are available. Choose based on your environment and dependencies:
| Module | Underlying client |
|---|---|
commercetools-http-client | Alias for commercetools-async-http-client (default) |
commercetools-async-http-client | Async HTTP client 2.12 |
commercetools-okhttp-client4 | OkHttp 4.0 |
commercetools-okhttp-client3 | OkHttp 3.0 |
commercetools-apachehttp-client | Apache HTTP async client 5.1 |
commercetools-reactornetty-client | Reactor Netty HTTP client |
commercetools-javanet-client | java.net.http.HttpClient (JDK 11+) |
Troubleshoot with the Spring Framework
The Spring Framework has an optional dependency to OkHttp in version 3.x.
commercetools-okhttp-client3 or commercetools-apachehttp-client module instead of the module commercetools-http-client.Create the Client class
Client and add the following code:For HTTP API
For Import API
For Audit Log API
For Checkout API
// Package declaration
// Required imports
import com.commercetools.api.client.ProjectApiRoot;
import com.commercetools.api.defaultconfig.ApiRootBuilder;
import com.commercetools.api.defaultconfig.ServiceRegion;
import io.vrap.rmf.base.client.oauth2.ClientCredentials;
public class HTTPApiClient {
public static ProjectApiRoot createApiClient() {
final ProjectApiRoot httpApiRoot = ApiRootBuilder.of()
.defaultClient(ClientCredentials.of()
.withClientId("{clientID}")
.withClientSecret("{clientSecret}")
.build(),
ServiceRegion.GCP_EUROPE_WEST1)
.build("{projectKey}");
return httpApiRoot;
}
}
ServiceRegion.GCP_EUROPE_WEST1 to match the Region where your Project is hosted. For more information about the supported values, see ServiceRegion.clientId, clientSecret, and projectKey from environment variables or a secrets management service. Do not hardcode these values in your source code.Test the Client
ApiRoot from the client. The code also contains test calls which outputs to the log.For HTTP API
For Import API
For Audit Log API
For Checkout API
// Required imports
import com.commercetools.api.client.ProjectApiRoot;
import com.commercetools.api.models.project.Project;
// Create httpApiRoot from your HTTPApiClient
ProjectApiRoot httpApiRoot = HTTPApiClient.createApiClient();
// Make a get call to the Project
Project myProject = httpApiRoot
.get()
.executeBlocking()
.getBody();
// Output the Project name
System.out.println(myProject.getName());
httpApiRoot to build requests to the HTTP API.Use the Java SDK
Imports
Without importing resource-specific packages and interfaces you cannot use/access specific objects and methods.
For example, to use or create a Shopping List you must import:
import com.commercetools.api.models.shopping_list.ShoppingList;
import com.commercetools.api.models.shopping_list.ShoppingListDraft;
com.commercetools.api.models.shopping_list package using:import com.commercetools.api.models.shopping_list.*;
Asset interface. Always use API-specific resources to avoid errors and conflicts.Create objects
The Java SDK follows a builder pattern to construct drafts, update actions, and other objects/types that contain multiple fields.
// Create a LocalizedString
LocalizedString multiLanguageString = LocalizedString
.builder()
.addValue("en", "English value")
.addValue("de", "German value")
.build();
// Create US$100.00
Money money = Money.builder().currencyCode("USD").centAmount(10000l).build();
// Create a CategoryDraft
CategoryDraft categoryDraft = CategoryDraft
.builder()
.name(LocalizedString.ofEnglish("english name"))
.slug(stringBuilder -> stringBuilder.addValue("en", "english-slug"))
.key("category-key")
.build();
.build() finishes building the object and validates that all required fields are set. If you need to create an instance without this validation, use buildUnchecked() instead. This creates the instance without checking for required fields.Debug object state
reflectionString() method for debugging. It returns a human-readable string representation of the instance:CustomerDraft customerDraft = CustomerDraft.builder().email("john.doe@example.com").build();
// All three forms are equivalent
String s1 = ModelBase.reflectionString(customerDraft);
String s2 = ((ModelBase) customerDraft).reflectionString();
String s3 = customerDraft.withCustomerDraft(ModelBase::reflectionString);
Apply a function to a model object
with{ModelName}() method that applies a function to the model instance and returns the result. This is used to access typed accessors defined on other classes:// Apply AttributesAccessor to a ProductVariant to get typed attribute access
ProductVariant variant = masterVariant;
AttributesAccessor attributes = variant.withProductVariant(AttributesAccessor::of);
String isbn = attributes.asString("isbn");
AttributePlainEnumValue size = attributes.asEnum("size");
with{ModelName}() pattern is a general extension mechanism. Any function that takes the model type as input can be applied.Structure your API call
The following examples demonstrate how to structure calls to the HTTP API using the Java SDK. The examples use the Shopping Lists endpoint, but the structure is identical for most other endpoints in the HTTP API.
/categories/{id}/images maps directly to .categories().withId("{id}").images(). This makes it straightforward to discover available endpoints using your IDE's autocomplete.Using the Import API, Audit Log API, or Checkout API may differ slightly, but the structure of building requests remains the same.
Calls to the Java SDK require you to make an instance of the type you want returned, or an instance of an action to take:
// Return the information of a specific Shopping List
ShoppingList shoppingListInfo
// ...
// Return all Shopping Lists
ShoppingListPagedQueryResponse allShoppingLists
// ...
// Create an update action for setting a Shopping List key
ShoppingListSetKeyAction shoppingListSetKeyAction
// ...
Retrieve data
httpApiRoot and the associated endpoint.// Get information of a specific Shopping List
ShoppingList shoppingListInfo = httpApiRoot
.shoppingLists()
// ...
// Return all Shopping Lists
ShoppingListPagedQueryResponse allShoppingLists = httpApiRoot
.shoppingLists()
// ...
Get a single resource
.get(), .executeBlocking() and .getBody();.ShoppingList shoppingListInfo = httpApiRoot
.shoppingLists()
.withId("{shoppingListID}")
.get()
.executeBlocking()
.getBody();
ShoppingList shoppingListInfo = httpApiRoot
.shoppingLists()
.withKey("{shoppingListKey}")
.get()
.executeBlocking()
.getBody();
shoppingListInfo object would then contain all the data of the specified Shopping List. You can access information from the fields within that object:
Get multiple resources
PagedQueryResponse based on the resource you want to return. For example, a ShoppingListPagedQueryResponse returns Shopping Lists.PagedQueryResponse is identical to PagedQueryResult in the HTTP API.ShoppingListPagedQueryResponse allShoppingLists = httpApiRoot
.shoppingLists()
.get()
.executeBlocking()
.getBody();
.withWhere(), .withSort(), .withExpand(), .withLimit(), or .withOffset() after .get().Query parameter methods come in two variants:
with*(): sets the parameter value, replacing any previously set value (for example,withLimit(20)sets the limit to 20).add*(): adds an additional value alongside any already set (for example,addSort("name asc")followed byaddSort("createdAt desc")applies both sort criteria).
Use the Query Predicate builder
withQuery method.// Return all Customers that have not verified their email address
final CustomerPagedQueryResponse response = httpApiRoot
.customers()
.get()
.withQuery(c -> c.isEmailVerified().is(false))
.executeBlocking()
.getBody();
Access query results
PagedQueryResponse using .getResults():ShoppingListPagedQueryResponse allShoppingLists = httpApiRoot
.shoppingLists()
.get()
.executeBlocking()
.getBody();
// Put the returned Shopping Lists in a new list
List<ShoppingList> listOfShoppingLists = allShoppingLists.getResults();
// Create a String containing the first Shopping List's English name
String firstShoppingListName = listOfShoppingLists.get(0).getName().get("en");
Write a resource
httpApiRoot and the associated endpoint.// Create a Shopping List
ShoppingList newShoppingList = httpApiRoot
.shoppingLists()
// ...
// Update a Shopping List
ShoppingList updatedShoppingList = httpApiRoot
.shoppingLists()
// ...
Create a new resource
ShoppingListDraft newShoppingListDraft = ShoppingListDraft
.builder()
.name(
LocalizedString
.builder()
.addValue("en", "English name of Shopping List")
.build()
)
.build();
post() followed by .executeBlocking() and .getBody().ShoppingList newShoppingList = httpApiRoot
.shoppingLists()
.post(newShoppingListDraft)
.executeBlocking()
.getBody();
Update an existing resource
.withId() or .withKey() that references a unique identifier of the resource.// Update a Shopping List
ShoppingList updatedShoppingList = httpApiRoot
.shoppingLists()
.withId("{shoppingListID}")
// ...
ShoppingListUpdate) contains an array of update actions and the last seen version of the resource.// Create the payload - a ShoppingListUpdate - with the current version of the Shopping List and the update actions.
ShoppingListUpdate shoppingListUpdate = ShoppingListUpdateBuilder
.of()
.version(1L)
.plusActions(actionBuilder ->
actionBuilder.setKeyBuilder().key("a-new-shoppinglist-key")
)
.build();
.post() method.ShoppingList updatedShoppingList = httpApiRoot
.shoppingLists()
.withId("{shoppingListID}")
.post(shoppingListUpdate)
.executeBlocking()
.getBody();
Delete a resource
.delete() method with the last seen version of the resource. You must identify the resource to delete using withId() or withKey().ShoppingList deletedShoppingList = httpApiRoot
.shoppingLists()
.withId("{shoppingListID}")
.delete()
.withVersion(1l)
.withDataErasure(true) // Include to erase related personal data
.executeBlocking()
.getBody();
Retrieve the raw API response
.executeBlocking() to return the resource as an instance of an object..sendBlocking(). Note that with this approach you must create a byte array as the value to return:byte[] shoppingLists = httpApiRoot.shoppingLists().get().sendBlocking().getBody();
// Convert to a String and output to the console
String shoppingListDetails = new String(
shoppingLists,
java.nio.charset.StandardCharsets.UTF_8
);
System.out.println(shoppingListDetails);
Use GraphQL
The response types have all available fields, but only the projected will contain a value.
final GraphQLRequest<ProductQueryResult> productQuery = GraphQL
.products(query -> query.localeProjection(Collections.singletonList("en")))
.projection(root ->
root.results().id().key().productType().key().getParent().createdAt()
);
final ApiHttpResponse<GraphQLResponse<ProductQueryResult>> response =
projectRoot.graphql().query(productQuery).executeBlocking();
final ProductQueryResult data = response.getBody().getData();
Use non-blocking calls
.execute(). To return a byte array use .send():// Return all Shopping Lists using a CompletableFuture - execute()
apiRoot
.shoppingLists()
.get()
.execute()
.thenAccept(response -> {
ShoppingListPagedQueryResponse allShoppingLists = response.getBody();
// Assign the first Shopping List's ID to a string and output it to the console
String firstshoppingListID = allShoppingLists.getResults().get(0).getId();
System.out.println(firstshoppingListID);
})
.join();
// Return all Shopping Lists in a byte array using a CompletableFuture - send()
apiRoot
.shoppingLists()
.get()
.send()
.thenAccept(response -> {
byte[] shoppingLists = response.getBody();
// Convert to a String and output to the console
String shoppingListDetails = new String(
shoppingLists,
java.nio.charset.StandardCharsets.UTF_8
);
System.out.println(shoppingListDetails);
})
.join();
Close the client
close() on the client when your application shuts down to release these resources:httpApiRoot.getApiHttpClient().close();
@PreDestroy annotation.