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:
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
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 importsimport 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 value | Region |
---|---|
ServiceRegion.GCP_EUROPE_WEST1 | europe-west1.gcp |
ServiceRegion.GCP_US_CENTRAL1 | us-central1.gcp |
ServiceRegion.AWS_US_EAST_2 | us-east-2.aws |
ServiceRegion.AWS_EU_CENTRAL_1 | eu-central-1.aws |
ServiceRegion.GCP_AUSTRALIA_SOUTHEAST1 | australia-southeast1.gcp |
Test the Client
In your Java program, add the following code:
// Required importsimport com.commercetools.api.client.ProjectApiRoot;import com.commercetools.api.models.project.*;// Create the apiRoot with your ClientProjectApiRoot apiRoot = Client.createApiClient();// Make a get call to the ProjectProject myProject = apiRoot.get().executeBlocking().getBody();// Output the Project nameSystem.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 LocalizedStringLocalizedString multiLanguageString = LocalizedString.builder().addValue("en", "English value").addValue("de", "German value").build();// Create US$100.00Money money = Money.builder().currencyCode("USD").centAmount(10000l).build();// Create a CategoryCategoryDraft 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 CustomerCustomer customerInfo// ...// Return all CustomersCustomerPagedQueryResponse allCustomers// ...// Create an update action for setting a Customer keyCustomerSetKeyAction customerSetKeyAction// ...
Retrieving data
When retrieving, include the apiRoot
and the associated endpoint.
// Get information of a specific CustomerCustomer customerInfo = apiRoot.customers()// ...// Return all CustomersCustomerPagedQueryResponse 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 IDCustomer customerInfo = apiRoot.customers().withId("{customerID}").get().executeBlocking().getBody();
// Information of a specific Customer by keyCustomer 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:
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 PagedQueryResponseCustomerPagedQueryResponse 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:
Viewing results
A list of resources within a PagedQueryResponse
can be accessed using .getResults()
:
// Return all CustomersCustomerPagedQueryResponse allCustomers = apiRoot.customers().get().executeBlocking().getBody();// Put the returned Customers in a new listList<Customer> listOfCustomers = allCustomers.getResults();// Create a String containing the first Customer's full nameString 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 CustomerCustomer newCustomer = apiRoot.customers()// ...// Update a CustomerCustomer 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 fieldsCustomerDraft 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 CustomerCustomer 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 CustomerCustomer 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 CustomerCustomer 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 arraybyte[] customers = apiRoot.customers().get().sendBlocking().getBody();// Convert to a String and output to the consoleString 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 consoleString 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 consoleString 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:
// 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 CustomerCustomer customer = apiRoot.customers().post(newCustomerDetails).executeBlocking().getBody().getCustomer();// Output the Customer IDString 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:
// Query a Customer by their IDCustomer queryCustomer = apiRoot.customers().withId("{customerID}").get().executeBlocking().getBody();// Output the Customer's email addressString 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.
// Query the Customer to updateCustomer customerToUpdate = apiRoot.customers().withId("{customerID}").get().executeBlocking().getBody();// Create the CustomerUpdate with the current version of the Customer and add the actionsCustomerUpdate 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 CustomerCustomer updatedCustomer = apiRoot.customers().withId(customerToUpdate.getId()).post(customerUpdate).executeBlocking().getBody();// Output the updated Customer's full nameString 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:
// Search for Customers whose email address matches the predicate variableCustomerPagedQueryResponse 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 accurateString 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:
// Create ProductTypeProductTypeDraft newProductTypeDetails = ProductTypeDraft.builder().name("The name of your ProductType").description("The description of your ProductType").build();// Post the ProductTypeDraft and get the new ProductTypeProductType productType = apiRoot.productTypes().post(newProductTypeDetails).executeBlocking().getBody();// Output the ProductType IDString 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:
// Create ProductProductDraft 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 ProductProduct product = apiRoot.products().post(newProductDetails).executeBlocking().getBody();// Output the Product IDString productID = product.getId();System.out.println(productID);
Query your Product
Your new Product can be queried by adding .withId("{productID}")
after the .products()
endpoint:
// Query the new ProductProduct queryProduct = apiRoot.products().withId("{productID}").get().executeBlocking().getBody();// Output the Product's versionSystem.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.
// Query the Product to updateProduct productToUpdate = apiRoot.products().withId("{productID}").get().executeBlocking().getBody();// Create the ProductUpdate with the current version of the Product and the update actionsProductUpdate productUpdate = ProductUpdate.builder().version(productToUpdate.getVersion()).plusActions(actionBuilder ->actionBuilder.setKeyBuilder().key("new-product-key")).build();// Post the ProductUpdate and return the updated ProductProduct updatedProduct = apiRoot.products().withId(productToUpdate.getId()).post(productUpdate).executeBlocking().getBody();// Output the updated Product's keyString 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:
Product findProductByKey = apiRoot.products().withKey("{productKey}").get().executeBlocking().getBody();String productID = findProductByKey.getId();System.out.println(productID);