Get started with the Java SDK

Learn how to set up the Java SDK and how to use example code.

This step-by-step guide leads you through setting up and making API calls using the Java SDK.

Objectives of the get started guide

By the end of this guide you will have:

Requirements

A commercetools Project with a configured API Client.

Java 8 (or later) is required.

Placeholder values

Example code in this getting started guide uses placeholders that should be replaced with the following values:

PlaceholderReplace withFrom
{projectKey}project_keyyour API Client
{clientID}client_idyour API Client
{clientSecret}secretyour API Client
{scope}scopeyour API Client
{region}your RegionHosts

Install the Java SDK

Gradle

Add the following to your build.gradle file.

This has been configured to install the latest version of each dependency. To use a specific version, replace 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}"
implementation "com.commercetools.sdk:commercetools-sdk-java-importapi:${versions.commercetools}"
implementation "com.commercetools.sdk:commercetools-sdk-java-ml:${versions.commercetools}"
implementation "com.commercetools.sdk:commercetools-sdk-java-history:${versions.commercetools}"
}

Maven

Add the following to your pom.xml file.

This has been configured to install the latest version of each dependency. To use a specific version, replace 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>
</dependency>
<dependency>
<groupId>com.commercetools.sdk</groupId>
<artifactId>commercetools-sdk-java-importapi</artifactId>
<version>${commercetools.version}</version>
</dependency>
<dependency>
<groupId>com.commercetools.sdk</groupId>
<artifactId>commercetools-sdk-java-ml</artifactId>
<version>${commercetools.version}</version>
</dependency>
<dependency>
<groupId>com.commercetools.sdk</groupId>
<artifactId>commercetools-sdk-java-history</artifactId>
<version>${commercetools.version}</version>
</dependency>
</dependencies>

Maven Central

A full list of commercetools SDKs and the latest versions can be found at Maven Central Repository Search.

For any of the SDK modules an HTTP client module must be installed. The default one is commercetools-http-client.

The commercetools-sdk-java-importapi (Import API), commercetools-sdk-java-ml (Machine Learning API), and commercetools-sdk-java-history (Change History API) are only needed for more specific use cases.

Troubleshooting with the Spring Framework

The Spring Framework has an optional dependency to OkHttp in version 3.x.

To avoid problems use the commercetools-okhttp-client3 or commercetools-apachehttp-client module instead of the module commercetools-http-client.

Create the Client class

Create a class called Client and add the following code:

// Add your package information here
// 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.*;
public class Client {
public static ProjectApiRoot createApiClient() {
final ProjectApiRoot apiRoot = ApiRootBuilder.of()
.defaultClient(ClientCredentials.of()
.withClientId("{clientID}")
.withClientSecret("{clientSecret}")
.build(),
ServiceRegion.YOUR_SERVICE_REGION)
.build("{projectKey}");
return apiRoot;
}
}

ServiceRegion is an enum and you should use one of the following values based on where your commercetools Project is hosted:

ServiceRegion valueRegion
ServiceRegion.GCP_EUROPE_WEST1europe-west1.gcp
ServiceRegion.GCP_US_CENTRAL1us-central1.gcp
ServiceRegion.AWS_US_EAST_2us-east-2.aws
ServiceRegion.AWS_EU_CENTRAL_1eu-central-1.aws
ServiceRegion.GCP_AUSTRALIA_SOUTHEAST1australia-southeast1.gcp

Test the Client

In your Java program, add the following code:

// Required imports
import com.commercetools.api.client.ProjectApiRoot;
import com.commercetools.api.models.project.*;
// Create the apiRoot with your Client
ProjectApiRoot apiRoot = Client.createApiClient();
// Make a get call to the Project
Project myProject = apiRoot
.get()
.executeBlocking()
.getBody();
// Output the Project name
System.out.println(myProject.getName());

apiRoot can now be used to build requests to the Composable Commerce API.

This code includes an example API call that gets your Project to the myProject object and outputs the Project's name using .getName().

Using the Java SDK

Imports

Without importing resource-specific packages and interfaces you will be unable to use/access specific objects and methods.

For example, to use or create a Customer you must import:

import com.commercetools.api.models.customer.Customer;
import com.commercetools.api.models.customer.CustomerDraft;

Alternatively, you can include everything from the com.commercetools.api.models.customer package using:

import com.commercetools.api.models.customer.*;

A list of the available packages to import can be found in the Javadoc.

Using builders

The Java SDK follows a builder pattern when constructing 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 Category
CategoryDraft categoryDraft = CategoryDraft.builder()
.name(LocalizedString.ofEnglish("english name"))
.slug(stringBuilder -> stringBuilder
.addValue("en", "english-slug"))
.key("category-key")
.build();

Consult the HTTP API reference to ensure that all required fields are included.

Once the fields/values are added, .build() finishes building the object.

How to structure your API call

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 Customer
Customer customerInfo
// ...
// Return all Customers
CustomerPagedQueryResponse allCustomers
// ...
// Create an update action for setting a Customer key
CustomerSetKeyAction customerSetKeyAction
// ...

Retrieving data

When retrieving, include the apiRoot and the associated endpoint.

// Get information of a specific Customer
Customer customerInfo = apiRoot
.customers()
// ...
// Return all Customers
CustomerPagedQueryResponse allCustomers = apiRoot
.customers()
// ...

Get a single resource

When getting a specific resource, you should include its ID or key followed by .get(), .executeBlocking() and .getBody();.

// Information of a specific Customer by ID
Customer customerInfo = apiRoot
.customers()
.withId("{customerID}")
.get()
.executeBlocking()
.getBody();
// Information of a specific Customer by key
Customer customerInfo = apiRoot
.customers()
.withKey("{customerKey}")
.get()
.executeBlocking()
.getBody();

The customerInfo object would then contain all the data of the specified Customer. Individual information can be accessed from the fields within that object:

Screenshot of autocomplete for Customer object

Get multiple resources

When returning a list of resources, a PagedQueryResponse should be used based on the resource you want to return. For example, a CustomerPagedQueryResponse returns Customers and a ProductPagedQueryResponse returns Products.

PagedQueryResponse is identical to the PagedQueryResults in the HTTP API.

// Return all Customers in a PagedQueryResponse
CustomerPagedQueryResponse allCustomers = apiRoot
.customers()
.get()
.executeBlocking()
.getBody();

The results of these calls can be altered by including .withWhere(), .withSort(), .withExpand(), .withLimit(), or .withOffset() after .get().

These are identical to the parameters you can add to standard HTTP API calls. If your IDE supports autocomplete you can view a full list of methods available:

Screenshot of autocomplete for parameters

Viewing results

A list of resources within a PagedQueryResponse can be accessed using .getResults():

// Return all Customers
CustomerPagedQueryResponse allCustomers = apiRoot
.customers()
.get()
.executeBlocking()
.getBody();
// Put the returned Customers in a new list
List<Customer> listOfCustomers = allCustomers.getResults();
// Create a String containing the first Customer's full name
String firstCustomerName = listOfCustomers.get(0).getFirstName() + " " + listOfCustomers.get(0).getLastName();

Writing a resource

When writing to a resource, include the apiRoot and the associated endpoint.

// Create a Customer
Customer newCustomer = apiRoot
.customers()
// ...
// Update a Customer
Customer updatedCustomer = apiRoot
.customers()
// ...

Creating a new resource

Creating a new resource requires a draft of the resource to create. For Customers this would be a CustomerDraft, for Products a ProductDraft. These drafts are created using builders:

// Create CustomerDraft with required fields
CustomerDraft newCustomerDraft = CustomerDraft.builder()
.email("java-sdk@example.com")
.password("password")
.build();

This draft should be included within post() followed by .executeBlocking() and .getBody().

// Create a Customer
Customer newCustomer = apiRoot
.customers()
.post(newCustomerDraft)
.executeBlocking()
.getBody() // As creating a Customer returns a CustomerSignInResult, .getCustomer() is required to get the new Customer object
.getCustomer();

Updating an existing resource

Updating an existing resource requires a .withId() or .withKey() that references a unique identifier of the resource.

// Update a Customer
Customer updatedCustomer = apiRoot
.customers()
.withId("{customerID}")
// ...

When posting to a specific resource, a payload must be included. This payload (in the case of Customers, a CustomerUpdate) contains an array of update actions and the last seen version of the resource.

Update actions and payloads are created using builders.

// Create the payload - a CustomerUpdate - with the current version of the Customer and the update actions.
CustomerUpdate customerUpdate = CustomerUpdateBuilder.of()
.version(1L)
.plusActions(actionBuilder -> actionBuilder.setKeyBuilder()
.key("a-unique-customer-key"))
.build();

The payload must then be passed as an argument to the .post() method.

// Update a Customer
Customer updatedCustomer = apiRoot
.customers()
.withId("{customerID}")
.post(customerUpdate)
.executeBlocking()
.getBody();

Retrieving the raw API response

The above examples use .executeBlocking() to return the resource as an instance of an object.

To return the response as a byte array instead, use .sendBlocking(). Note that with this approach you must create a byte array as the value to return:

// Return a CustomerPagedQueryResponse as a byte array
byte[] customers = apiRoot
.customers()
.get()
.sendBlocking()
.getBody();
// Convert to a String and output to the console
String customerDetails = new String(customers, java.nio.charset.StandardCharsets.UTF_8);
System.out.println(customerDetails);

Using non-blocking calls

The Java SDK also allows non-blocking calls which return a CompletableFuture.

To return the resource as an instance of an object use .execute(). To return a byte array use .send():

// Return all Customers using a CompletableFuture - execute()
apiRoot.customers()
.get()
.execute()
.thenAccept(response -> {
CustomerPagedQueryResponse allCustomers = response.getBody();
// Assign the first Customer's ID to a string and output it to the console
String firstCustomerId = allCustomers.getResults().get(0).getId();
System.out.println(firstCustomerId);
})
.join();
// Return all Customers in a byte array using a CompletableFuture - send()
apiRoot
.customers()
.get()
.send()
.thenAccept(response -> {
byte[] customers = response.getBody();
// Convert to a String and output to the console
String customerDetails = new String(customers, java.nio.charset.StandardCharsets.UTF_8);
System.out.println(customerDetails);
})
.join();

Try our example code

The following example code covers some basic operations and is intended to provide you with an insight into how to create, query, and modify entities.

This code can be easily adapted and built upon to help you learn how to use the Java SDK to interact with your commercetools Project.

Manage Customers

Create a Customer

When creating Customers using the HTTP API, a CustomerDraft must be created and posted to the Customers endpoint.

The CustomerDraft has two required fields: email and password.

This example code builds a CustomerDraft and posts it to the .customers() endpoint. .getBody() returns a CustomerSignInResult. The new Customer is accessed by chaining the .getCustomer() method:

Java code for creating a CustomerJava
// Create a CustomerDraft with the required fields (email address and password)
CustomerDraft newCustomerDetails = CustomerDraft
.builder()
.email("java-sdk@example.com")
.password("password")
.build();
// Post the CustomerDraft and get the new Customer
Customer customer = apiRoot
.customers()
.post(newCustomerDetails)
.executeBlocking()
.getBody()
.getCustomer();
// Output the Customer ID
String customerID = customer.getId();
System.out.println(customerID);

This example code outputs the ID of the new Customer. Take note of this Customer ID and use it in place of {customerID} in following examples.

Query a Customer

Your new Customer can be queried by adding .withId("{customerID}") after the .customers() endpoint:

Java code for querying a CustomerJava
// Query a Customer by their ID
Customer queryCustomer = apiRoot
.customers()
.withId("{customerID}")
.get()
.executeBlocking()
.getBody();
// Output the Customer's email address
String customerEmail = queryCustomer.getEmail();
System.out.println(customerEmail);

If you query a Customer with an ID that does not exist, the API returns a 404 Not Found error.

Add a Customer name

The commercetools API uses update actions to change existing entities.

When an array of update actions is posted to a Customer, the Customer is updated based on the specified update actions and their values.

The required update actions for changing a Customer's name are Set First Name and Set Last Name.

The current version of the Customer is also required.

The version of a new Customer is 1. This value is incremented every time an update action is applied to the Customer.

If the specified version does not match the current version, the request returns an error.

Java code for updating a CustomerJava
// Query the Customer to update
Customer customerToUpdate = apiRoot
.customers()
.withId("{customerID}")
.get()
.executeBlocking()
.getBody();
// Create the CustomerUpdate with the current version of the Customer and add the actions
CustomerUpdate customerUpdate = CustomerUpdate
.builder()
.version(customerToUpdate.getVersion())
.plusActions(actionBuilder ->
actionBuilder.setFirstNameBuilder().firstName("John")
)
.plusActions(actionBuilder ->
actionBuilder.setLastNameBuilder().lastName("Smith")
)
.build();
// Post the CustomerUpdate and return the updated Customer
Customer updatedCustomer = apiRoot
.customers()
.withId(customerToUpdate.getId())
.post(customerUpdate)
.executeBlocking()
.getBody();
// Output the updated Customer's full name
String updatedCustomerName =
updatedCustomer.getFirstName() + " " + updatedCustomer.getLastName();
System.out.println(updatedCustomerName);

Find a Customer by their email address

As the email of a Customer is unique, it is a dependable way to find a Customer.

Customers can be found by their email address by querying the Customers endpoint with a where parameter.

In the commercetools API, where uses a Query Predicate.

This example code finds a Customer by their email address with the Java SDK and returns the Customer resource:

Java code for finding a Customer by email addressJava
// Search for Customers whose email address matches the predicate variable
CustomerPagedQueryResponse customerToFind = apiRoot
.customers()
.get()
.withWhere("email = :customerEmail", "customerEmail", "java-sdk@example.com")
.executeBlocking()
.getBody();
// Output the Customer's details. As email addresses must be unique, the first value of the results (0) should be accurate
String customerID = customerToFind.getResults().get(0).getId();
System.out.println(customerID);

If there is no Customer with the specified email address, then a zero-length List is returned by .getResults().

Manage Products

Creating Products requires more steps than creating Customers. This is due to how Products are modeled in commercetools.

Before a Product can be created, you must first create a ProductType.

Create a ProductType

When creating ProductTypes using the HTTP API, a ProductTypeDraft must be created and posted to the ProductTypes endpoint.

The ProductTypeDraft has two required fields: name and description.

This example code builds a ProductTypeDraft, posts it to the ProductTypes endpoint, and returns the new ProductType resource:

Java code for creating a ProductTypeJava
// Create ProductType
ProductTypeDraft newProductTypeDetails = ProductTypeDraft
.builder()
.name("The name of your ProductType")
.description("The description of your ProductType")
.build();
// Post the ProductTypeDraft and get the new ProductType
ProductType productType = apiRoot
.productTypes()
.post(newProductTypeDetails)
.executeBlocking()
.getBody();
// Output the ProductType ID
String productTypeID = productType.getId();
System.out.println(productTypeID);

This example code outputs the ID of the new Product Type. Take note of this Product Type ID and use it in place of {productType} in following examples.

Create a Product

When creating Products using the HTTP API, a ProductDraft must be created and posted to the Products endpoint.

The ProductDraft has three required fields: name, productType, and slug. All three fields must be built.

This example code builds a ProductDraft, posts it to the .products() endpoint, and returns the new Product resource:

Java code for creating a ProductJava
// Create Product
ProductDraft newProductDetails = ProductDraft
.builder()
.name(stringBuilder ->
stringBuilder
.addValue("en", "English name for your Product")
.addValue("de", "German name for your Product")
)
.productType(typeBuilder -> typeBuilder.id(productTypeID))
.slug(stringBuilder ->
stringBuilder
.addValue("en", "human-readable-url-for-english-product")
.addValue("de", "human-readable-url-for-german-product")
)
.build();
// Post the ProductDraft and get the new Product
Product product = apiRoot
.products()
.post(newProductDetails)
.executeBlocking()
.getBody();
// Output the Product ID
String productID = product.getId();
System.out.println(productID);

Query your Product

Your new Product can be queried by adding .withId("{productID}") after the .products() endpoint:

Java code for querying a ProductJava
// Query the new Product
Product queryProduct = apiRoot
.products()
.withId("{productID}")
.get()
.executeBlocking()
.getBody();
// Output the Product's version
System.out.println(queryProduct.getVersion());

If you query a Product with an ID that does not exist, the API returns a 404 Not Found error.

Add a Product key

Adding a key to a Product requires the Set Key update action.

The current version of the Product is also required.

The version of a new Product is 1. This value is incremented every time an update action is applied to the Product.

If the specified version does not match the current version, the request returns an error.

Java code for updating a ProductJava
// Query the Product to update
Product productToUpdate = apiRoot
.products()
.withId("{productID}")
.get()
.executeBlocking()
.getBody();
// Create the ProductUpdate with the current version of the Product and the update actions
ProductUpdate productUpdate = ProductUpdate
.builder()
.version(productToUpdate.getVersion())
.plusActions(actionBuilder ->
actionBuilder.setKeyBuilder().key("new-product-key")
)
.build();
// Post the ProductUpdate and return the updated Product
Product updatedProduct = apiRoot
.products()
.withId(productToUpdate.getId())
.post(productUpdate)
.executeBlocking()
.getBody();
// Output the updated Product's key
String updatedProductKey = updatedProduct.getKey();
System.out.println(updatedProductKey);

Return a Product by its Key

Your new Product key can be queried by adding .withKey(productKey) after the .products() endpoint:

Java code for querying a Product by its keyJava
Product findProductByKey = apiRoot
.products()
.withKey("{productKey}")
.get()
.executeBlocking()
.getBody();
String productID = findProductByKey.getId();
System.out.println(productID);