Migrate from v1 to v2
How to migrate from the v1 SDK to the v2 SDK .
The Java v1 SDK will be deprecated on 1 January 2024. This guide helps developers migrate from the v1 SDK to the Java v2 SDK.
Placeholder values
Example code in this migration 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 |
Client configuration and creation
SphereClientFactory
has been replaced by ApiRootBuilder
.
The benefit is that after the ApiRoot
has been instantiated, requests can be created directly from it.
final SphereClient sphereClient = SphereClientFactory.of().createClient("{projectKey}", "{clientID}", "{clientSecret}");
final ProjectApiRoot projectRoot = ApiRootBuilder.of().defaultClient(ClientCredentials.of().withClientId("{clientID}").withClientSecret("{clientSecret}").build(),ServiceRegion.GCP_EUROPE_WEST1).build("{projectKey}");
Timeout setting
Both SDKs use the method executeBlocking()
to set the timeout.
PagedQueryResult<Category> response = blockingClient().executeBlocking(CategoryQuery.of(), 45, TimeUnit.SECONDS);
CategoryPagedQueryResponse response = projectClient().categories().get().executeBlocking(Duration.ofSeconds(45)).getBody();
Headers
To set headers, in the v1 SDK there is the HttpRequest
class and in the v2 SDK the ApiHttpRequest
class.
The main difference, as you can see in the example below, is that the ApiHttpRequest
can be directly instantiated and it can set the type of method (GET or POST), the URI, the headers, and the body.
// Not in SDK v1
final CartPagedQueryResponse carts = projectClient().carts().get().addHeader("foo", "bar").executeBlocking().getBody();
Implementing retry
In the examples below there is a significant difference in the retry mechanisms between the v1 SDK and the v2 SDK.
In the v1 SDK, the retry mechanism has to be defined piece by piece: first the retry rules, then the SphereClient
, and then the request, in this case, a PagedQueryResult
In the v2 SDK, the setup of the request can be built directly during the client creation. ByProjectKeyRequestBuilder
can be created with a built-in retry mechanism using the RetryMiddleware
. It is also possible to set up additional parameters to the request, like the logger InternalLoggerFactory
.
final int maxAttempts = 5;final List<RetryRule> retryRules = singletonList(RetryRule.of(RetryPredicate.ofMatchingStatusCodes(BAD_GATEWAY_502,SERVICE_UNAVAILABLE_503,GATEWAY_TIMEOUT_504),RetryAction.ofExponentialBackoff(maxAttempts, 100, 2000)));final SphereClient client = RetrySphereClientDecorator.of(sphereClient(),retryRules);final PagedQueryResult<Category> categoryPagedQueryResult = client.execute(CategoryQuery.of()).toCompletableFuture().get();
final ByProjectKeyRequestBuilder projectClient = ApiRootBuilder.of().defaultClient(ServiceRegion.GCP_EUROPE_WEST1.getApiUrl(),ClientCredentials.of().withClientId("{clientId}").withClientSecret("{clientSecret}").build(),ServiceRegion.GCP_EUROPE_WEST1.getOAuthTokenUrl()).withRetryMiddleware(5, Arrays.asList(502, 503, 504)).buildForProject("{projectKey}");final CategoryPagedQueryResponse body = projectClient.categories().get().executeBlocking().getBody();
Using DraftBuilders
In the v2 SDK there are not inheritances for DraftBuilder classes, but the differences are minor.
LocalizedString name = LocalizedString.ofEnglish("name");LocalizedString slug = LocalizedString.ofEnglish("slug");LocalizedString metaDescription = LocalizedString.ofEnglish("metaDescription");LocalizedString metaTitle = LocalizedString.ofEnglish("metaTitle");LocalizedString metaKeywords = LocalizedString.ofEnglish("metaKeywords");CategoryDraft categoryDraft = CategoryDraftBuilder.of(name, slug).metaDescription(metaDescription).metaTitle(metaTitle).metaKeywords(metaKeywords).externalId("externalId").build();
CategoryDraft categoryDraft = CategoryDraft.builder().name(LocalizedString.ofEnglish("name")).slug(LocalizedString.ofEnglish("slug")).externalId("externalId").metaTitle(LocalizedString.ofEnglish("metaTitle")).metaDescription(LocalizedString.ofEnglish("metaDescription")).metaKeywords(LocalizedString.ofEnglish("metaKeywords")).build();
Create resources
In the v2 SDK there are no dedicated classes for the create command, but there are builders instead. The Create Command needs a Draft that is built and passed to the post()
method.
LocalizedString name = LocalizedString.ofEnglish("name");LocalizedString slug = LocalizedString.ofEnglish("slug");CategoryDraft categoryDraft = CategoryDraftBuilder.of(name, slug).build();Category category = blockingClient().executeBlocking(CategoryCreateCommand.of(categoryDraft));
CategoryDraft categoryDraft = CategoryDraft.builder().name(LocalizedString.ofEnglish("name")).slug(LocalizedString.ofEnglish("slug")).build();Category category = projectClient().categories().post(categoryDraft).executeBlocking().getBody();
Create resources from JSON
In the v2 SDK, the JsonUtils
class replaces the SphereJsonUtils
class.
final CategoryDraft categoryDraft = SphereJsonUtils.readObjectFromResource("category.json",CategoryDraft.class);final Category category = blockingClient().executeBlocking(CategoryCreateCommand.of(categoryDraft));
final CategoryDraft categoryDraft = JsonUtils.fromJsonString(TestUtils.stringFromResource("category.json"),CategoryDraft.class);final Category category = projectClient().categories().post(categoryDraft).executeBlocking().getBody();
Update resources
In the v2 SDK there are no dedicated classes for the update command. The UpdateBuilder
is used to create the type of update action to apply in the post()
method.
LocalizedString newName = LocalizedString.ofEnglish("new name");CategoryUpdateCommand command = CategoryUpdateCommand.of(category,Collections.singletonList(ChangeName.of(newName)));Category updatedCategory = blockingClient().executeBlocking(command);
CategoryUpdate categoryUpdate = CategoryUpdate.builder().version(category.getVersion()).plusActions(actionBuilder ->actionBuilder.changeNameBuilder().name(LocalizedString.ofEnglish("new name"))).build();Category updatedCategory = projectClient().categories().withId(category.getId()).post(categoryUpdate).executeBlocking().getBody();
Get a resource by ID
Retrieving resources by ID in the v2 SDK requires .withId()
before .get()
, after which additional filters or requests (such as .withExpand()
) can be included before the request is executed.
Category loadedCategory = blockingClient().executeBlocking(CategoryByIdGet.of(category.getId()).withExpansionPaths(m -> m.parent()));
Category queriedCategory = projectClient().categories().withId(category.getId()).get().withExpand("parent").executeBlocking().getBody();
Query resources
To build complex queries, the v2 SDK uses ResourcePagedQueryResponse
(as opposed to PagedQueryResult
in the v1 SDK). ResourcePagedQueryResponse
can apply the limit, count, total, offset, and result to the query.
PagedQueryResult<Category> pagedQueryResult = blockingClient().executeBlocking(CategoryQuery.of().byId("id123"));
CategoryPagedQueryResponse response = projectClient().categories().get().withWhere("id = :id", "id", "id123").executeBlocking().getBody();
Compatibility layer for JVM SDK
The commercetools-sdk-compat-v1 module allows the usage of the v2 SDK in conjunction with the v1 SDK.
Using Requests from the JVM SDK
The CompatClient can be used to execute a SphereRequest with an ApiHttpClient
.
import com.commercetools.api.defaultconfig.ApiRootBuilder;import com.commercetools.api.models.project.Project;import io.sphere.sdk.projects.queries.ProjectGet;import io.vrap.rmf.base.client.ApiHttpClient;import io.vrap.rmf.base.client.oauth2.ClientCredentials;import org.assertj.core.api.Assertions;import org.junit.jupiter.api.Test;public class CompatClientUsageTest {@Testpublic void compatClient() {final ApiHttpClient apiHttpClient = ApiRootBuilder.of().defaultClient(ClientCredentials.of().withClientId(CommercetoolsTestUtils.getClientId()).withClientSecret(CommercetoolsTestUtils.getClientSecret()).build()).buildClient();final String projectKey = CommercetoolsTestUtils.getProjectKey();CompatClient client = CompatClient.of(apiHttpClient, projectKey);Project project = client.executeBlocking(ProjectGet.of(), Project.class).getBody();Assertions.assertThat(project).isInstanceOf(Project.class);Assertions.assertThat(project.getKey()).isEqualTo(projectKey);}}
Creating a SphereClient with the V2 SDK
The CompatSphereClient acts as a replacement SphereClient for applications using the v1 SDK.
public class CompatSphereClientUsageTest {@Testpublic void sphereCompatClient() throws ExecutionException, InterruptedException {SphereClientConfig clientConfig = SphereClientConfig.of(CommercetoolsTestUtils.getProjectKey(),CommercetoolsTestUtils.getClientId(), CommercetoolsTestUtils.getClientSecret());SphereClient client = CompatSphereClient.of(clientConfig);Project project = client.execute(ProjectGet.of()).toCompletableFuture().get();Assertions.assertThat(project).isInstanceOf(Project.class);}}