# Java SDK overview Integrate applications running on the Java Virtual Machine (JVM) with commercetools. The Java SDK enables you to use Java 8 methods and objects to interact with commercetools APIs. This includes the [HTTP API](/api/), [Import API](/api/import-export/overview.md), [Audit Log API](/api/history/overview.md), and [Checkout API](/checkout). With the Java SDK, you benefit from IDE autocompletion, type-safety, encapsulation, and an internal domain-specific language for formulating valid requests. The Java SDK supports multiple languages that run on the JVM, including Java, Scala, Groovy, Clojure, and Kotlin. Learn more about configuring your integrated developer environment in our self-paced Prepare your work environment module. ## Get started Learn how to set up and use the Java SDK with our [get started guide](/dev-tooling/java-sdk-getting-started.md). Refer to our [integration tests](https://github.com/commercetools/commercetools-sdk-java-v2/blob/main/commercetools/commercetools-sdk-java-api/src/integrationTest) for examples of creating, querying, updating, and deleting resources in your commercetools Project. The Java SDK is open source and is available on [GitHub](https://github.com/commercetools/commercetools-sdk-java-v2) under the [Apache License](https://github.com/commercetools/commercetools-sdk-java-v2/blob/main/LICENSE). You can view the full Javadoc reference on [GitHub](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/index.html). ## SDK features The Java SDK uses various Java 8 language constructs and classes, including: - [CompletionStage](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html) - [Functional interfaces](https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html) - Java Date API: - [ZonedDateTime](https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html) - [LocalDate](https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html) - [LocalTime](https://docs.oracle.com/javase/8/docs/api/java/time/LocalTime.html) The Java SDK is unsuitable for Android development as Java 8 dependencies are not supported on its virtual machine. The SDK simplifies development with: - **Default implementations for equals() and hashCode()**: automatically using reflection in model implementation classes. - **Client interfaces**: the HTTP client abstract is a functional interface, and you can replace it with test doubles. - **Model factory methods**: each model has a factory method `::of()` to create a new empty instance. The method `::builder()` returns a new builder instance. - **Helper methods**: you can find a complete list of helper methods including example usage in the [Javadoc](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/com/commercetools/docs/meta/HelperMethods.html). ## Release schedule The Java SDK is autogenerated from our [API specifications](/dev-tooling/api-specifications.md) to ensure it is up to date with the latest enhancements. New releases are published on the first Monday of the month, though occasional updates can occur. To stay informed about new releases, subscribe to the [GitHub releases](https://github.com/commercetools/commercetools-sdk-java-v2/releases.atom) or watch the [GitHub repository](https://github.com/commercetools/commercetools-sdk-java-v2). ## Reporting issues Report SDK bugs and unexpected behaviors as [GitHub issues](https://github.com/commercetools/commercetools-sdk-java-v2/issues). Include as much detail as possible: the SDK version, the specific error message, and the relevant log or stack trace. You can also contact the [support team](https://support.commercetools.com/) directly. ## Logging and error handling For best observability, use an Application Performance Monitoring (APM) service. For server-side logs, integrate [Platform Insights](/api/platform-insights.md) with your APM provider. ### Exceptions The Java SDK uses exceptions from the Java Development Kit (such as [IllegalArgumentException](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalArgumentException.html)) and provides its own exceptions which inherit from [BaseException](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/io/vrap/rmf/base/client/error/BaseException.html). - Problems related to the [ApiHttpClient](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/io/vrap/rmf/base/client/ApiHttpClient.html) result in an [ApiHttpException](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/io/vrap/rmf/base/client/ApiHttpException.html), which is the base exception for all error responses (HTTP status codes `4xx` and `5xx`). - [ApiClientException](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/io/vrap/rmf/base/client/error/ApiClientException.html) indicates recoverable client-side errors (HTTP status codes `4xx`). - [ApiServerException](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/io/vrap/rmf/base/client/error/ApiServerException.html) represents server errors (HTTP status codes `5xx`). - JSON serializing and deserializing problems result in a [JsonException](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/io/vrap/rmf/base/client/utils/json/JsonException.html). ### Errors If a command cannot run due to unfulfilled preconditions, one error response with multiple errors can be returned (for more information, see [HTTP API Errors](/api/errors.md)). The Java SDK then adds a [BadRequestException](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/io/vrap/rmf/base/client/error/BadRequestException.html) into a [CompletionStage](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html). ### Custom HttpExceptionFactory The Java SDK treats responses with HTTP status codes `4xx` and `5xx` as errors and raises exceptions. The [DefaultHttpExceptionFactory](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/io/vrap/rmf/base/client/error/DefaultHttpExceptionFactory.html) creates these exceptions. To customize the handling, you must implement this interface and override its default methods as needed. ```java title="Implement a custom HttpExceptionFactory" public class HttpExceptionFactoryTest { static class CustomExceptionFactory implements HttpExceptionFactory { @Override public ApiHttpException create( ApiHttpRequest request, ApiHttpResponse response ) { return new ApiHttpException( response.getStatusCode(), request.getSecuredBody(), response.getHeaders(), "something bad happened", response, request ); } @Override public ResponseSerializer getResponseSerializer() { return ResponseSerializer.of(); } } @Test public void customFactory() { ProjectApiRoot client = ApiRootBuilder .of() .defaultClient(ServiceRegion.GCP_EUROPE_WEST1.getApiUrl()) .withHttpExceptionFactory(CustomExceptionFactory::new) .build("my-project-key"); assertThatExceptionOfType(ApiHttpException.class) .isThrownBy(() -> client.get().executeBlocking()) .withMessageStartingWith("detailMessage: something bad happened"); } } ``` ### Logging Internal logging used by the commercetools client itself uses a [SLF4J](https://github.com/qos-ch/slf4j) logger named `commercetools`. The default logger middleware logs the following information per level: - **Error**: logs HTTP method, URI, and response status code for [ApiHttpException](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/io/vrap/rmf/base/client/ApiHttpException.html), and cause and exceptions for all other exceptions. - **Information**: logs HTTP method, URI, response status code, and any deprecation notices. You can configure the log level when instantiating the [InternalLoggerMiddleware](/dev-tooling/java-sdk-middleware.md#internalloggermiddleware). - **Debug**: logs string representations of the request and the response, including headers and body, with sensitive data like auth tokens and passwords, redacted. - **Trace**: Logs request and response with pretty-printed output, with sensitive information redacted. ### Logger hierarchy The loggers form a hierarchy separated by a period. The root logger is `commercetools`. The child loggers of commercetools are the endpoints. For example `commercetools.categories` for Categories and `commercetools.product-types` for Product Types. The grandchild loggers refer to the action. `commercetools.categories.request` refers to performing requests per HTTPS to commercetools for Categories, `commercetools.categories.response` refers to the responses. The logger makes use of different log levels, so for example `commercetools.categories.response` logs the HTTP response on debug level: ```java title="Example debug log output" [OkHttp https://api.europe-west1.gcp.commercetools.com/...] DEBUG commercetools.categories.response - io.vrap.rmf.base.client.ApiHttpResponse@33e37acd[statusCode=200,headers=...,textInterpretedBody={"limit":20,"offset":0,"count":4,"total":4,"results":[{"id":"ca7f64dc-ab41-4e7f-b65b-bfc25bf01111","version":1,"createdAt":"2021-01-06T09:21:55.445Z","lastModifiedAt":"2021-01-06T09:21:55.445Z","key":"random-key-15aab6ee-9a48-4fdc-a8c3-8ff9ff390d60","name":{"key-6bc3cc62-1995-43f4":"value-random-string-c3ff7f1a-6371-4c0c-a3b9-5060eca08b8a"},"slug":{"key-6bc3cc62-1995-43f4":"value-random-string-c3ff7f1a-6371-4c0c-a3b9-5060eca08b8a"},"description":{"key-6bc3cc62-1995-43f4":"value-random-string-c3ff7f1a-6371-4c0c-a3b9-5060eca08b8a"},"ancestors":[],"orderHint":"random-string-a99e6941-3225-4766-923a-4a654652532f","externalId":"random-id-100b3851-29b4-47c1-aef3-860b4cd28f54"}]}] ``` Additionally, `commercetools.categories.response` logs the formatted HTTP response on trace level: ```java title="Example trace log output" [OkHttp https://api.europe-west1.gcp.commercetools.com/...] TRACE commercetools.categories.response - 200 { "limit" : 20, "offset" : 0, "count" : 4, "total" : 4, "results" : [ { "id" : "bcb15128-b69e-47b6-81c4-1ea5f9a63b83", "version" : 1, "createdAt" : "2021-01-06T09:21:50.485Z", "lastModifiedAt" : "2021-01-06T09:21:50.485Z", "createdBy" : { "clientId" : "h-QvaF3NpsjPBWeXa6TUOnq0", "isPlatformClient" : false }, "key" : "random-key-f45535f5-1111-4bfb-98ac-164234ac2c73", "name" : { "key-b7d87008-9526-47b3-8b80" : "value-random-string-baf1a1ae-3726-4573-bec5-2c53c7d1114a" }, "slug" : { "key-b7d87008-9526-47b3-8b80" : "value-random-string-baf1a1ae-3726-4573-bec5-2c53c7d1114a" }, "description" : { "key-b7d87008-9526-47b3-8b80" : "value-random-string-baf1a1ae-3726-4573-bec5-2c53c7d1114a" }, "ancestors" : [ ], "orderHint" : "random-string-6b88f299-d4ca-491a-9d7c-3463e718c8d2", "externalId" : "random-id-b98a5ab4-5413-40b3-8119-eb5ac2b5afbb", "metaTitle" : { "key-b7d87008-9526-47b3-8b80" : "value-random-string-baf1a1ae-3726-4573-bec5-2c53c7d1114a" }, "metaKeywords" : { "key-b7d87008-9526-47b3-8b80" : "value-random-string-baf1a1ae-3726-4573-bec5-2c53c7d1114a" }, "metaDescription" : { "key-b7d87008-9526-47b3-8b80" : "value-random-string-baf1a1ae-3726-4573-bec5-2c53c7d1114a" } }, { ... } ] } ``` `commercetools.products.responses.queries` only logs HTTP GET requests and `commercetools.products.responses.commands` only logs HTTP POST/DELETE requests. ```java title="Example log output for commands and queries" [pool-1-thread-1] DEBUG commercetools.products.request.commands - io.vrap.rmf.base.client.ApiHttpRequest@1d2c6948[method=POST,uri="https://api.europe-west1.gcp.commercetools.com/test-php-dev-integration-1/products",headers=[...],textInterpretedBody={"productType":{"id":"cda39953-23af-4e85-abb0-5b89517ec5f2","typeId":"product-type"},"name":{"random-string-b66de021-d2fa-4262-8837-94a6992a8cdc":"random-string-da28a010-e66b-49d4-a18b-f1bfc145d2f6"},...}] [pool-1-thread-1] DEBUG commercetools.products.request.queries - io.vrap.rmf.base.client.ApiHttpRequest@53667fdb[method=GET,uri="https://api.europe-west1.gcp.commercetools.com/test-php-dev-integration-1/products/ef745227-b115-4132-ba2c-4e46db80df79",headers=[...],textInterpretedBody=empty body] ``` ### Configure logging The [ClientBuilder](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/io/vrap/rmf/base/client/ClientBuilder.html) allows customization of the log levels used for different events. By default, responses are logged at `INFO` level and errors at `ERROR` level. Use the `withInternalLoggerFactory()` method to change these defaults: ```java title="Configure log levels" ProjectApiRoot apiRoot = ApiRootBuilder .of() .defaultClient( ClientCredentials .of() .withClientId("your-client-id") .withClientSecret("your-client-secret") .build(), ServiceRegion.GCP_EUROPE_WEST1 ) .withInternalLoggerFactory( InternalLoggerFactory.of(Level.DEBUG), Level.DEBUG, Level.WARN ) .build("my-project-key"); ``` ### Mapped Diagnostic Context (MDC) The SDK uses [CompletableFutures](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html) extensively, which means futures can execute on different threads. If your application uses [SLF4J MDC](https://www.slf4j.org/api/org/slf4j/MDC.html), the context may be lost when switching threads. The SDK supports attaching a [Context](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/io/vrap/rmf/base/client/Context.html) to a client, requests, and responses through the [ContextAware](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/io/vrap/rmf/base/client/ContextAware.html) interface. [ProjectApiRoot](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/com/commercetools/api/client/ProjectApiRoot.html) allows adding a `Context` to create a context-aware root from a global instance: ```java title="Create a context-aware API root for MDC propagation" Map mdcContext = MDC.getCopyOfContextMap(); MDCContext context = MDCContext.of(mdcContext); ProjectApiRoot contextAwareRoot = apiRoot.withContext(context); ``` The [InternalLoggerMiddleware](/dev-tooling/java-sdk-middleware.md#internalloggermiddleware) restores the MDC before logging and cleans up afterwards to avoid polluting threads with unrelated context data. The same applies to [ConcurrentModificationMiddleware](/dev-tooling/java-sdk-middleware.md#concurrentmodificationmiddleware). ## Related pages - [Area overview page with navigation](/dev-tooling.md) - [Next page: Get started](/dev-tooling/java-sdk-getting-started.md)