From 5de344bcb8f58e070ec5b445b25e3ba255a42c72 Mon Sep 17 00:00:00 2001 From: lojzatran Date: Thu, 7 Sep 2023 16:49:04 +0200 Subject: [PATCH] Update docs --- README.md | 14 +- docs/{sdk2 => }/MIGRATION_GUIDE.md | 44 +- docs/README.md | 14 +- docs/RELEASE_NOTES.md | 8 + docs/sdk2/usage/CART_DISCOUNT_SYNC.md | 390 ---------------- docs/sdk2/usage/CATEGORY_SYNC.md | 468 ------------------- docs/sdk2/usage/CLEANUP_GUIDE.md | 3 - docs/sdk2/usage/CUSTOMER_SYNC.md | 277 ------------ docs/sdk2/usage/CUSTOM_OBJECT_SYNC.md | 258 ----------- docs/sdk2/usage/IMPORTANT_USAGE_TIPS.md | 48 -- docs/sdk2/usage/INVENTORY_SYNC.md | 382 ---------------- docs/sdk2/usage/PRODUCT_SYNC.md | 578 ------------------------ docs/sdk2/usage/PRODUCT_TYPE_SYNC.md | 392 ---------------- docs/sdk2/usage/QUICK_START.md | 71 --- docs/sdk2/usage/SHOPPING_LIST_SYNC.md | 397 ---------------- docs/sdk2/usage/STATE_SYNC.md | 417 ----------------- docs/sdk2/usage/SYNC_OPTIONS.md | 84 ---- docs/sdk2/usage/TAX_CATEGORY_SYNC.md | 301 ------------ docs/sdk2/usage/TYPE_SYNC.md | 304 ------------- docs/usage/CART_DISCOUNT_SYNC.md | 220 +++++++-- docs/usage/CATEGORY_SYNC.md | 238 +++++++--- docs/usage/CLEANUP_GUIDE.md | 29 +- docs/usage/CUSTOMER_SYNC.md | 102 +++-- docs/usage/CUSTOM_OBJECT_SYNC.md | 143 +++++- docs/usage/IMPORTANT_USAGE_TIPS.md | 36 +- docs/usage/INVENTORY_SYNC.md | 204 +++++++-- docs/usage/PRODUCT_SYNC.md | 294 ++++++++---- docs/usage/PRODUCT_TYPE_SYNC.md | 243 +++++++--- docs/usage/QUICK_START.md | 12 +- docs/usage/SHOPPING_LIST_SYNC.md | 219 ++++++--- docs/usage/STATE_SYNC.md | 219 ++++++--- docs/usage/TAX_CATEGORY_SYNC.md | 162 +++++-- docs/usage/TYPE_SYNC.md | 157 +++++-- 33 files changed, 1730 insertions(+), 4998 deletions(-) rename docs/{sdk2 => }/MIGRATION_GUIDE.md (60%) delete mode 100644 docs/sdk2/usage/CART_DISCOUNT_SYNC.md delete mode 100644 docs/sdk2/usage/CATEGORY_SYNC.md delete mode 100644 docs/sdk2/usage/CLEANUP_GUIDE.md delete mode 100644 docs/sdk2/usage/CUSTOMER_SYNC.md delete mode 100644 docs/sdk2/usage/CUSTOM_OBJECT_SYNC.md delete mode 100644 docs/sdk2/usage/IMPORTANT_USAGE_TIPS.md delete mode 100644 docs/sdk2/usage/INVENTORY_SYNC.md delete mode 100644 docs/sdk2/usage/PRODUCT_SYNC.md delete mode 100644 docs/sdk2/usage/PRODUCT_TYPE_SYNC.md delete mode 100644 docs/sdk2/usage/QUICK_START.md delete mode 100644 docs/sdk2/usage/SHOPPING_LIST_SYNC.md delete mode 100644 docs/sdk2/usage/STATE_SYNC.md delete mode 100644 docs/sdk2/usage/SYNC_OPTIONS.md delete mode 100644 docs/sdk2/usage/TAX_CATEGORY_SYNC.md delete mode 100644 docs/sdk2/usage/TYPE_SYNC.md diff --git a/README.md b/README.md index 69df2ce9cb..f2c71e12f3 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,25 @@ ![commercetools-java-sync-logos 002](https://user-images.githubusercontent.com/9512131/31182587-90d47f0a-a924-11e7-9716-66e6bec7f79b.png) -# commercetools sync (version 10) +# commercetools sync java [![CI](https://github.com/commercetools/commercetools-sync-java/workflows/CI/badge.svg)](https://github.com/commercetools/commercetools-sync-java/actions?query=workflow%3ACI) [![codecov](https://codecov.io/gh/commercetools/commercetools-sync-java/branch/master/graph/badge.svg)](https://codecov.io/gh/commercetools/commercetools-sync-java) -[![Javadoc](https://javadoc.io/badge2/com.commercetools/commercetools-sync-java/javadoc.svg?label=Javadoc)](https://commercetools.github.io/commercetools-sync-java/v/9.2.3/) +[![Javadoc](https://javadoc.io/badge2/com.commercetools/commercetools-sync-java/javadoc.svg?label=Javadoc)](https://commercetools.github.io/commercetools-sync-java/v/10.0.0/) [![Known Vulnerabilities](https://snyk.io/test/github/commercetools/commercetools-sync-java/4b2e26113d591bda158217c5dc1cf80a88665646/badge.svg)](https://snyk.io/test/github/commercetools/commercetools-sync-java/4b2e26113d591bda158217c5dc1cf80a88665646) -> Note: The current version of this library uses [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2). This doc already contains updated information. Please migrate to this version, using our [Migration Guide](/docs/sdk2/MIGRATION_GUIDE.md). -> If migration isn't an option for you, you can still use deprecated versions of this library available at [Maven central](https://search.maven.org/artifact/com.commercetools/commercetools-sync-java/9.2.3/jar). +> Note: The current version of this library uses [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2). This doc already contains updated information. Please migrate to this version, using our [Migration Guide](/docs/MIGRATION_GUIDE.md). +> If migration isn't an option for you, you can still use deprecated versions of this library available at [Maven central](https://search.maven.org/artifact/com.commercetools/commercetools-sync-java/10.0.0/jar). More at https://commercetools.github.io/commercetools-sync-java Java library which allows to import/synchronise (import changes) the data from any arbitrary source to commercetools project. -Supported resources: [Categories](/docs/sdk2/usage/CATEGORY_SYNC.md), [Products](/docs/sdk2/usage/PRODUCT_SYNC.md), [InventoryEntries](/docs/sdk2/usage/INVENTORY_SYNC.md), [ProductTypes](/docs/sdk2/usage/PRODUCT_TYPE_SYNC.md), [Types](/docs/sdk2/usage/TYPE_SYNC.md), [CartDiscounts](/docs/sdk2/usage/CART_DISCOUNT_SYNC.md), [States](/docs/sdk2/usage/STATE_SYNC.md), [TaxCategories](/docs/sdk2/usage/TAX_CATEGORY_SYNC.md), [CustomObjects](/docs/sdk2/usage/CUSTOM_OBJECT_SYNC.md), [Customers](/docs/sdk2/usage/CUSTOMER_SYNC.md), [ShoppingLists](/docs/sdk2/usage/SHOPPING_LIST_SYNC.md) +Supported resources: [Categories](/docs/usage/CATEGORY_SYNC.md), [Products](/docs/usage/PRODUCT_SYNC.md), [InventoryEntries](/docs/usage/INVENTORY_SYNC.md), [ProductTypes](/docs/usage/PRODUCT_TYPE_SYNC.md), [Types](/docs/usage/TYPE_SYNC.md), [CartDiscounts](/docs/usage/CART_DISCOUNT_SYNC.md), [States](/docs/usage/STATE_SYNC.md), [TaxCategories](/docs/usage/TAX_CATEGORY_SYNC.md), [CustomObjects](/docs/usage/CUSTOM_OBJECT_SYNC.md), [Customers](/docs/usage/CUSTOMER_SYNC.md), [ShoppingLists](/docs/usage/SHOPPING_LIST_SYNC.md) - [Usage](#usage) - - [Quick Start](/docs/sdk2/usage/QUICK_START.md) + - [Quick Start](/docs/usage/QUICK_START.md) - [Prerequisites](#prerequisites) - [Installation](#installation) - [Maven](#maven) @@ -39,7 +39,7 @@ Notes: - There is dockerized ready-to-use CLI application [commercetools-project-sync](https://github.com/commercetools/commercetools-project-sync) which based on this library can synchronize entire data catalogue between the 2 commercetools projects. - During a synchronisation, resources are either created or updated, but **not** deleted. -⚡ See the [Quick Start Guide](/docs/sdk2/usage/QUICK_START.md) for more information on building a product importer! +⚡ See the [Quick Start Guide](/docs/usage/QUICK_START.md) for more information on building a product importer! ![commercetools-java-sync-final 001](https://user-images.githubusercontent.com/3469524/126317637-a946a81c-2948-4751-86bb-02bcecfeca95.png) diff --git a/docs/sdk2/MIGRATION_GUIDE.md b/docs/MIGRATION_GUIDE.md similarity index 60% rename from docs/sdk2/MIGRATION_GUIDE.md rename to docs/MIGRATION_GUIDE.md index 0fff426f70..aa91e77e57 100644 --- a/docs/sdk2/MIGRATION_GUIDE.md +++ b/docs/MIGRATION_GUIDE.md @@ -4,17 +4,17 @@ - [Migration Guide](#migration-guide) - [Migrate syncers of supported resources](#migrate-syncers-of-supported-resources) - - [Categories](/docs/sdk2/usage/CATEGORY_SYNC.md#migration-guide), - - [Products](/docs/sdk2/usage/PRODUCT_SYNC.md#migration-guide) - - [InventoryEntries](/docs/sdk2/usage/INVENTORY_SYNC.md#migration-guide) - - [ProductTypes](/docs/sdk2/usage/PRODUCT_TYPE_SYNC.md#migration-guide) - - [Types](/docs/sdk2/usage/TYPE_SYNC.md#migration-guide) - - [CartDiscounts](/docs/sdk2/usage/CART_DISCOUNT_SYNC.md#migration-guide) - - [States](/docs/sdk2/usage/STATE_SYNC.md#migration-guide) - - [TaxCategories](/docs/sdk2/usage/TAX_CATEGORY_SYNC.md#migration-guide) - - [CustomObjects](/docs/sdk2/usage/CUSTOM_OBJECT_SYNC.md#migration-guide) - - [Customers](/docs/sdk2/usage/CUSTOMER_SYNC.md#migration-guide) - - [ShoppingLists](/docs/sdk2/usage/SHOPPING_LIST_SYNC.md#migration-guide) + - [Categories](/docs/usage/CATEGORY_SYNC.md#migration-guide), + - [Products](/docs/usage/PRODUCT_SYNC.md#migration-guide) + - [InventoryEntries](/docs/usage/INVENTORY_SYNC.md#migration-guide) + - [ProductTypes](/docs/usage/PRODUCT_TYPE_SYNC.md#migration-guide) + - [Types](/docs/usage/TYPE_SYNC.md#migration-guide) + - [CartDiscounts](/docs/usage/CART_DISCOUNT_SYNC.md#migration-guide) + - [States](/docs/usage/STATE_SYNC.md#migration-guide) + - [TaxCategories](/docs/usage/TAX_CATEGORY_SYNC.md#migration-guide) + - [CustomObjects](/docs/usage/CUSTOM_OBJECT_SYNC.md#migration-guide) + - [Customers](/docs/usage/CUSTOMER_SYNC.md#migration-guide) + - [ShoppingLists](/docs/usage/SHOPPING_LIST_SYNC.md#migration-guide) # Migration Guide @@ -60,17 +60,17 @@ private static >> U mapValuesToF ``` ## Migrate syncers of supported resources -- [Categories](/docs/sdk2/usage/CATEGORY_SYNC.md#migration-guide), -- [Products](/docs/sdk2/usage/PRODUCT_SYNC.md#migration-guide) -- [InventoryEntries](/docs/sdk2/usage/INVENTORY_SYNC.md#migration-guide) -- [ProductTypes](/docs/sdk2/usage/PRODUCT_TYPE_SYNC.md#migration-guide) -- [Types](/docs/sdk2/usage/TYPE_SYNC.md#migration-guide) -- [CartDiscounts](/docs/sdk2/usage/CART_DISCOUNT_SYNC.md#migration-guide) -- [States](/docs/sdk2/usage/STATE_SYNC.md#migration-guide) -- [TaxCategories](/docs/sdk2/usage/TAX_CATEGORY_SYNC.md#migration-guide) -- [CustomObjects](/docs/sdk2/usage/CUSTOM_OBJECT_SYNC.md#migration-guide) -- [Customers](/docs/sdk2/usage/CUSTOMER_SYNC.md#migration-guide) -- [ShoppingLists](/docs/sdk2/usage/SHOPPING_LIST_SYNC.md#migration-guide) +- [Categories](/docs/usage/CATEGORY_SYNC.md#migration-guide), +- [Products](/docs/usage/PRODUCT_SYNC.md#migration-guide) +- [InventoryEntries](/docs/usage/INVENTORY_SYNC.md#migration-guide) +- [ProductTypes](/docs/usage/PRODUCT_TYPE_SYNC.md#migration-guide) +- [Types](/docs/usage/TYPE_SYNC.md#migration-guide) +- [CartDiscounts](/docs/usage/CART_DISCOUNT_SYNC.md#migration-guide) +- [States](/docs/usage/STATE_SYNC.md#migration-guide) +- [TaxCategories](/docs/usage/TAX_CATEGORY_SYNC.md#migration-guide) +- [CustomObjects](/docs/usage/CUSTOM_OBJECT_SYNC.md#migration-guide) +- [Customers](/docs/usage/CUSTOMER_SYNC.md#migration-guide) +- [ShoppingLists](/docs/usage/SHOPPING_LIST_SYNC.md#migration-guide) diff --git a/docs/README.md b/docs/README.md index a225cd2b98..bdb224c3d9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,9 +2,9 @@ # commercetools sync [![CI](https://github.com/commercetools/commercetools-sync-java/workflows/CI/badge.svg)](https://github.com/commercetools/commercetools-sync-java/actions?query=workflow%3ACI) [![codecov](https://codecov.io/gh/commercetools/commercetools-sync-java/branch/master/graph/badge.svg)](https://codecov.io/gh/commercetools/commercetools-sync-java) -[![Benchmarks 9.2.3](https://img.shields.io/badge/Benchmarks-9.2.3-orange.svg)](https://commercetools.github.io/commercetools-sync-java/benchmarks/) -[![Download from Maven Central](https://img.shields.io/badge/Maven_Central-9.2.3-blue.svg)](https://search.maven.org/artifact/com.commercetools/commercetools-sync-java/9.2.3/jar) -[![Javadoc](https://javadoc.io/badge2/com.commercetools/commercetools-sync-java/javadoc.svg?label=Javadoc)](https://commercetools.github.io/commercetools-sync-java/v/9.2.3/) +[![Benchmarks 10.0.0](https://img.shields.io/badge/Benchmarks-10.0.0-orange.svg)](https://commercetools.github.io/commercetools-sync-java/benchmarks/) +[![Download from Maven Central](https://img.shields.io/badge/Maven_Central-10.0.0-blue.svg)](https://search.maven.org/artifact/com.commercetools/commercetools-sync-java/10.0.0/jar) +[![Javadoc](https://javadoc.io/badge2/com.commercetools/commercetools-sync-java/javadoc.svg?label=Javadoc)](https://commercetools.github.io/commercetools-sync-java/v/10.0.0/) [![Known Vulnerabilities](https://snyk.io/test/github/commercetools/commercetools-sync-java/4b2e26113d591bda158217c5dc1cf80a88665646/badge.svg)](https://snyk.io/test/github/commercetools/commercetools-sync-java/4b2e26113d591bda158217c5dc1cf80a88665646) @@ -40,18 +40,18 @@ Here are the most popular ones: com.commercetools commercetools-sync-java - 9.2.3 + 10.0.0 ```` #### Gradle ````groovy -implementation 'com.commercetools:commercetools-sync-java:9.2.3' +implementation 'com.commercetools:commercetools-sync-java:10.0.0' ```` #### SBT ```` -libraryDependencies += "com.commercetools" % "commercetools-sync-java" % "9.2.3" +libraryDependencies += "com.commercetools" % "commercetools-sync-java" % "10.0.0" ```` #### Ivy ````xml - + ```` diff --git a/docs/RELEASE_NOTES.md b/docs/RELEASE_NOTES.md index 989bdb6732..8156ddf09b 100644 --- a/docs/RELEASE_NOTES.md +++ b/docs/RELEASE_NOTES.md @@ -27,6 +27,14 @@ 7. Add Migration guide section which specifies explicitly if there are breaking changes and how to tackle them. --> +### 10.0.0-beta.1 - Sep 8, 2023 +[Commits](https://github.com/commercetools/commercetools-sync-java/compare/9.2.3...10.0.0) | +[Javadoc](https://commercetools.github.io/commercetools-sync-java/v/10.0.0/) | +[Jar](https://search.maven.org/artifact/com.commercetools/commercetools-sync-java/10.0.0/jar) +- 🚧 **Breaking Changes** (1) + - commercetools-sync-java is now fully migrated to `commercetools-sdk-java-v2`. See [Migration Guide](./MIGRATION_GUIDE.md) on how to use this library version. + + ### 9.2.3 - Mar 21, 2023 [Commits](https://github.com/commercetools/commercetools-sync-java/compare/9.2.1...9.2.3) | [Javadoc](https://commercetools.github.io/commercetools-sync-java/v/9.2.3/) | diff --git a/docs/sdk2/usage/CART_DISCOUNT_SYNC.md b/docs/sdk2/usage/CART_DISCOUNT_SYNC.md deleted file mode 100644 index 37e3d060b1..0000000000 --- a/docs/sdk2/usage/CART_DISCOUNT_SYNC.md +++ /dev/null @@ -1,390 +0,0 @@ -# CartDiscount Sync - -The module used for importing/syncing CartDiscounts into a commercetools project. -It also provides utilities for generating update actions based on the comparison of a [CartDiscount](https://docs.commercetools.com/api/projects/cartDiscounts#cartdiscount) -against a [CartDiscountDraft](https://docs.commercetools.com/api/projects/cartDiscounts#cartdiscountdraft). - - - - -- [Usage](#usage) - - [Prerequisites](#prerequisites) - - [ProjectApiRoot](#projectapiroot) - - [Required Fields](#required-fields) - - [Reference Resolution](#reference-resolution) - - [Syncing from a commercetools project](#syncing-from-a-commercetools-project) - - [Syncing from an external resource](#syncing-from-an-external-resource) - - [SyncOptions](#syncoptions) - - [errorCallback](#errorcallback) - - [warningCallback](#warningcallback) - - [beforeUpdateCallback](#beforeupdatecallback) - - [beforeCreateCallback](#beforecreatecallback) - - [batchSize](#batchsize) - - [cacheSize](#cachesize) - - [Running the sync](#running-the-sync) - - [More examples of how to use the sync](#more-examples-of-how-to-use-the-sync) - - [Build all update actions](#build-all-update-actions) - - [Build particular update action(s)](#build-particular-update-actions) -- [Migration Guide](#migration-guide) - - [Client configuration and creation](#client-configuration-and-creation) - - [Signature of CartDiscountSyncOptions](#signature-of-cartdiscountsyncoptions) - - [Build CartDiscountDraft (syncing from external project)](#build-cartdiscountdraft-syncing-from-external-project) - - [Query for Cart Discounts (syncing from CTP project)](#query-for-cart-discounts-syncing-from-ctp-project) -- [Caveats](#caveats) - - - -## Usage - -### Prerequisites - -#### ProjectApiRoot - -Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](#todo) -If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). - -````java -final ClientCredentials clientCredentials = - new ClientCredentialsBuilder() - .withClientId("client-id") - .withClientSecret("client-secret") - .withScopes("scopes") - .build(); -final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); -```` - -#### Required Fields - -The following fields are **required** to be set in, otherwise, they won't be matched by sync: - -|Draft|Required Fields|Note| -|---|---|---| -| [CartDiscountDraft](https://docs.commercetools.com/api/projects/cartDiscounts#cartdiscountdraft) | `key` | Also, the cart discounts in the target project are expected to have the `key` fields set. | - -#### Reference Resolution - -In commercetools, a reference can be created by providing the key instead of the ID with the type [ResourceIdentifier](https://docs.commercetools.com/api/types#resourceidentifier). -When the reference key is provided with a `ResourceIdentifier`, the sync will resolve the resource with the given key and use the ID of the found resource to create or update a reference. -Therefore, in order to resolve the actual ids of those references in the sync process, `ResourceIdentifier`s with their `key`s have to be supplied. - -|Reference Field|Type| -|:---|:---| -| `custom.type` | ResourceIdentifier to a Type | - -> Note that a reference without the key field will be considered as an existing resource on the target commercetools project and the library will issue an update/create an API request without reference resolution. - -##### Syncing from a commercetools project - -When syncing from a source commercetools project, you can use [`toCartDiscountDrafts`](#todo) -method that transforms(resolves by querying and caching key-id pairs) and maps from a `CartDiscount` to `CartDiscountDraft` using cache in order to make them ready for reference resolution by the sync, for example: - -````java -// Build a ByProjectKeyCartDiscountsGet for fetching cart discounts from a source CTP project without any references expanded for the sync: -final ByProjectKeyCartDiscountsGet byProjectKeyCartDiscountsGet = client.cartDiscounts().get(); - -// Query all cart discounts (NOTE this is just for example, please adjust your logic) -final List cartDiscounts = QueryUtils.queryAll(byProjectKeyCartDiscountsGet, - (cartDiscounts) -> cartDiscounts) - .thenApply(lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())) - .toCompletableFuture() - .join(); -```` - -In order to transform and map the `CartDiscount` to `CartDiscountDraft`, -Utils method `toCartDiscountDrafts` requires `projectApiRoot`, implementation of [`ReferenceIdToKeyCache`](#todo) and `cartDiscounts` as parameters. -For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](#todo). -Example as shown below: - -````java -//Implement the cache using library class. -final ReferenceIdToKeyCache referenceIdToKeyCache = new CaffeineReferenceIdToKeyCacheImpl(); - -//For every reference fetch its key using id, cache it and map from CartDiscount to CartDiscountDraft. With help of the cache same reference keys can be reused. -CompletableFuture> cartDiscountDrafts = CartDiscountTransformUtils.toCartDiscountDrafts(client, referenceIdToKeyCache, cartDiscounts); -```` - -##### Syncing from an external resource - -- When syncing from an external resource, `ResourceIdentifier`s with their `key`s have to be supplied as following example: - -```` java -final CartDiscountDraft cartDiscountDraft = CartDiscountDraftBuilder.of() - .cartPredicate("cartPredicate") - .name(LocalizedString.ofEnglish("foo")) - .requiresDiscountCode(true) - .sortOrder("0.1") - .target(CartDiscountTargetBuilder::shippingBuilder) - .value(CartDiscountValueAbsoluteDraftBuilder.of() - .money( - MoneyBuilder.of() - .centAmount(10L) - .currencyCode(DefaultCurrencyUnits.EUR.getCurrencyCode()) - .build()) - .build()) - .key("cart-discount-key") - .custom(CustomFieldsDraftBuilder.of().type(typeResourceIdentifierBuilder -> typeResourceIdentifierBuilder.key("type-key")).fields(fieldContainerBuilder -> fieldContainerBuilder.values(emptyMap())).build()) // note that custom type provided with key - .build(); -```` - -#### SyncOptions - -After the `ProjectApiRoot` is set up, a `CartDiscountSyncOptions` should be built as follows: - -````java -// instantiating a CartDiscountSyncOptions -final CartDiscountSyncOptions cartDiscountSyncOptions = CartDiscountSyncOptionsBuilder.of(projectApiRoot).build(); -```` - -`SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. -Available configurations: - -##### errorCallback -A callback that is called whenever an error event occurs during the sync process. Each resource executes its own -error-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the error-event: - -* sync exception -* cart discount draft from the source -* cart discount of the target project (only provided if an existing cart discount could be found) -* the update-actions, which failed (only provided if an existing cart discount could be found) - -````java - final Logger logger = LoggerFactory.getLogger(CartDiscountSync.class); - final CartDiscountSyncOptions cartDiscountSyncOptions = CartDiscountSyncOptionsBuilder - .of(sphereClient) - .errorCallback((syncException, draft, cartDiscount, updateActions) -> - logger.error(new SyncException("My customized message"), syncException)).build(); -```` - -##### warningCallback -A callback is called whenever a warning event occurs during the sync process. Each resource executes its own -warning-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the warning message: - -* sync exception -* cart discount draft from the source -* cart discount of the target project (only provided if an existing cart discount could be found) - -````java - final Logger logger = LoggerFactory.getLogger(CartDiscountSync.class); - final CartDiscountSyncOptions cartDiscountSyncOptions = CartDiscountSyncOptionsBuilder - .of(projectApiRoot) - .warningCallback((syncException, draft, cartDiscount, updateActions) -> - logger.warn(new SyncException("My customized message"), syncException)).build(); -```` - -##### beforeUpdateCallback -During the sync process, if a target cart discount and a cart discount draft are matched, this callback can be used to -intercept the **_update_** request just before it is sent to the commercetools platform. This allows the user to modify -update actions array with custom actions or discard unwanted actions. The callback provides the following information : - - * cart discount draft from the source - * cart discount from the target project - * update actions that were calculated after comparing both - -````java -final TriFunction< - List, CartDiscountDraft, CartDiscount, List> - beforeUpdateCartDiscountCallback = - (updateActions, newCartDiscountDraft, oldCartDiscount) -> updateActions.stream() - .filter(updateAction -> !(updateAction instanceof CartDiscountChangeCartPredicateAction)) - .collect(Collectors.toList()); - -final CartDiscountSyncOptions cartDiscountSyncOptions = - CartDiscountSyncOptionsBuilder.of(projectApiRoot).beforeUpdateCallback(beforeUpdateCartDiscountCallback).build(); -```` - -##### beforeCreateCallback -During the sync process, if a cart discount draft should be created, this callback can be used to intercept the **_create_** request just before it is sent to the commercetools platform. It contains the following information : - - * cart discount draft that should be created - -Please refer to [example in product sync document](PRODUCT_SYNC.md#beforeCreateCallback). - -##### batchSize -A number that could be used to set the batch size with which cart discounts are fetched and processed, -as cart discounts are obtained from the target project on the commercetools platform in batches for better performance. The algorithm accumulates up to `batchSize` resources from the input list, then fetches the corresponding cart discounts from the target project on the commecetools platform in a single request. Playing with this option can slightly improve or reduce processing speed. If it is not set, the default batch size is 50 for cart discount sync. - -````java -final CartDiscountSyncOptions cartDiscountSyncOptions = - CartDiscountSyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); -```` - -##### cacheSize -In the service classes of the commercetools-sync-java library, we have implemented an in-memory [LRU cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) to store a map used for the reference resolution of the library. -The cache reduces the reference resolution based calls to the commercetools API as the required fields of a resource will be fetched only one time. These cached fields then might be used by another resource referencing the already resolved resource instead of fetching from commercetools API. It turns out, having the in-memory LRU cache will improve the overall performance of the sync library and commercetools API. -which will improve the overall performance of the sync and commercetools API. - -Playing with this option can change the memory usage of the library. If it is not set, the default cache size is `10.000` for cart discount sync. -````java -final CartDiscountSyncOptions cartDiscountSyncOptions = - CartDiscountSyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); -```` - -### Running the sync -After all the aforementioned points in the previous section have been fulfilled, to run the sync: -````java -// instantiating a cart discount sync -final CartDiscountSync cartDiscountSync = new CartDiscountSync(cartDiscountSyncOptions); - -// execute the sync on your list of cart discounts -CompletionStage syncStatisticsStage = cartDiscountSync.sync(cartDiscountDrafts); -```` -The result of completing the `syncStatisticsStage` in the previous code snippet contains a `CartDiscountSyncStatistics` -which contains all the stats of the sync process; which includes a report message, the total number of updated, created, -failed, processed cart discounts and the processing time of the last sync batch in different time units and in a -human-readable format. - -````java -final CartDiscountSyncStatistics stats = syncStatisticsStage.toCompletebleFuture().join(); -stats.getReportMessage(); -/*"Summary: 100 cart discounts were processed in total (11 created, 87 updated, 2 failed to sync)."*/ -```` - -__Note__ The statistics object contains the processing time of the last batch only. This is due to two reasons: - - 1. The sync processing time should not take into account the time between supplying batches to the sync. - 2. It is not known by the sync which batch is going to be the last one supplied. - - -#### More examples of how to use the sync - - 1. [Sync from another CTP project as a source](#todo). - 2. [Sync from an external source](#todo). - -*Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* - -### Build all update actions - -A utility method provided by the library to compare a `CartDiscount` with a new `CartDiscountDraft` and results in a list of cart discount update actions. -```java -List updateActions = CartDiscountSyncUtils.buildActions(cartDiscount, cartDiscountDraft, cartDiscountSyncOptions); -``` - -### Build particular update action(s) - -Utility methods provided by the library to compare the specific fields of a `CartDiscount` and a new `CartDiscountDraft`, and in turn builds - the update action. One example is the `buildChangeNameUpdateAction` which compares names: -````java -Optional updateAction = CartDiscountUpdateActionUtils.buildChangeNameAction(oldCartDiscount, cartDiscountDraft); -```` -More examples of those utils for different cart discounts can be found [here](#todo). - -## Migration Guide - -The cart-discount-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with -any HTTP client module. The default one is `commercetools-http-client`. - -```xml - - - LATEST - - - - - com.commercetools.sdk - commercetools-http-client - ${commercetools.version} - - - com.commercetools.sdk - commercetools-sdk-java-api - ${commercetools.version} - - - -``` - -### Client configuration and creation - -For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). - -### Signature of CartDiscountSyncOptions - -As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `CartDiscount`, `CartDiscountDraft` and `CartDiscountUpdateAction` from `package com.commercetools.api.models.cart_discount.*` - -> Note: Type `UpdateAction` has changed to `CartDiscountUpdateAction`. Make sure you create and supply a specific CartDiscountUpdateAction in `beforeUpdateCallback`. For that you can use the [library-utilities](#todo) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): - -```java -// Example: Create a cart discount update action to change name taking the 'newName' of the cartDiscountDraft - final Function createBeforeUpdateAction = - (newName) -> CartDiscountChangeNameAction.builder().name(newName).build(); - -// Add the change name action to the list of update actions before update is executed - final TriFunction< - List, CartDiscountDraft, CartDiscount, List> - beforeUpdateCartDiscountCallback = - (updateActions, newCartDiscountDraft, oldCartDiscount) -> { - final CartDiscountUpdateAction beforeUpdateAction = - createBeforeUpdateAction.apply(newCartDiscountDraft.getName()); - updateActions.add(beforeUpdateAction); - return updateActions; - }; -``` - -### Build CartDiscountDraft (syncing from external project) - -The cartDiscount-sync expects a list of `CartDiscountDraft`s to process. If you use java-sync-library to sync your cart discounts from any external system into a commercetools platform project you have to convert your data into CTP compatible `CartDiscountDraft` type. This was done in previous version using `DraftBuilder`s. -The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: - -```java -// CartDiscountDraftBuilder in v1 takes parameters 'name', 'cartPredicate', 'value', 'target', 'sortOrder', 'requiresDiscountCode' -final CartDiscountDraft cartDiscountDraft = - CartDiscountDraftBuilder.of( - ofEnglish("name"), - "1 = 1", - CartDiscountValue.ofAbsolute(MoneyImpl.of(20, EUR)), - "sku = \"0123456789\" or sku = \"0246891213\"", - "0.2", - false) - .key("key") - .active(false) - .build() - -// CartDiscountDraftBuilder in v2 -final CartDiscountDraft cartDiscountDraft = - CartDiscountDraftBuilder.of() - .name(ofEnglish("name")) - .cartPredicate("1 = 1") - .value( - CartDiscountValueAbsoluteDraftBuilder.of() - .money( - CentPrecisionMoneyBuilder.of() - .centAmount(20L) - .fractionDigits(0) - .currencyCode(DefaultCurrencyUnits.EUR.getCurrencyCode()) - .build() - ) - .build() - ) - .target("sku = \"0123456789\" or sku = \"0246891213\"") - .sortOrder("0.2") - .requiresDiscountCode(false) - .key("key") - .isActive(false) - .build(); -``` -For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). - -### Query for Cart Discounts (syncing from CTP project) - -If you sync cart discounts between different commercetools projects you probably use [CartDiscountTransformUtils#toCartDiscountDrafts](#todo) to transform `CartDiscount` into `CartDiscountDraft` which can be used by the cartDiscount-sync. -However, if you need to query `Cart Discounts` from a commercetools project instead of passing `CartDiscountQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. -Here's an example: - -```java -// SDK v1: CartDiscountQuery to fetch all cart discounts -final CartDiscountQuery query = CartDiscountQuery.of(); - -final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); - -// SDK v2: Create and execute query to fetch all cart discounts in one line -final CartDiscountPagedQueryResponse result = apiRoot.cart discounts().get().executeBlocking().getBody(); -``` -[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. - -## Caveats -1. Syncing cart discounts with a `CartDiscountValue` of type `giftLineItem` is not supported yet. [#411](https://github.com/commercetools/commercetools-sync-java/issues/411). diff --git a/docs/sdk2/usage/CATEGORY_SYNC.md b/docs/sdk2/usage/CATEGORY_SYNC.md deleted file mode 100644 index 8c5a80d802..0000000000 --- a/docs/sdk2/usage/CATEGORY_SYNC.md +++ /dev/null @@ -1,468 +0,0 @@ -# Category Sync - -Module used for importing/syncing Categories into a commercetools project. -It also provides utilities for generating update actions based on the comparison of a [Category](https://docs.commercetools.com/api/projects/categories#category) -against a [CategoryDraft](https://docs.commercetools.com/api/projects/categories#categorydraft). - - - - -- [Usage](#usage) - - [Prerequisites](#prerequisites) - - [ProjectApiRoot](#projectapiroot) - - [Required Fields](#required-fields) - - [Reference Resolution](#reference-resolution) - - [Persistence of Category Drafts with irresolvable parent](#persistence-of-category-drafts-with-irresolvable-parent) - - [Syncing from a commercetools project](#syncing-from-a-commercetools-project) - - [Syncing from an external resource](#syncing-from-an-external-resource) - - [SyncOptions](#syncoptions) - - [errorCallback](#errorcallback) - - [warningCallback](#warningcallback) - - [beforeUpdateCallback](#beforeupdatecallback) - - [beforeCreateCallback](#beforecreatecallback) - - [batchSize](#batchsize) - - [cacheSize](#cachesize) - - [Running the sync](#running-the-sync) - - [More examples of how to use the sync](#more-examples-of-how-to-use-the-sync) - - [Build all update actions](#build-all-update-actions) - - [Build particular update action(s)](#build-particular-update-actions) -- [Migration Guide](#migration-guide) - - [Client configuration and creation](#client-configuration-and-creation) - - [Signature of CategorySyncOptions](#signature-of-categorysyncoptions) - - [Build CategoryDraft (syncing from external project)](#build-categorydraft-syncing-from-external-project) - - [Query for Categories (syncing from CTP project)](#query-for-categories-syncing-from-ctp-project) - - [JVM-SDK-V2 migration guide](#jvm-sdk-v2-migration-guide) - - - -## Usage - -### Prerequisites - -#### ProjectApiRoot - -Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](#todo) -If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). - -````java -final ClientCredentials clientCredentials = - new ClientCredentialsBuilder() - .withClientId("client-id") - .withClientSecret("client-secret") - .withScopes("scopes") - .build(); -final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); -```` - -#### Required Fields - -The following fields are **required** to be set in, otherwise they won't be matched by sync: - -|Draft|Required Fields|Note| -|---|---|---| -| [CategoryDraft](https://docs.commercetools.com/api/projects/categories#categorydraft) | `key` | Also, the categories in the target project are expected to have the `key` fields set. | - -#### Reference Resolution - -In commercetools, a reference can be created by providing the key instead of the ID with the type [ResourceIdentifier](https://docs.commercetools.com/api/types#resourceidentifier). -When the reference key is provided with a `ResourceIdentifier`, the sync will resolve the resource with the given key and use the ID of the found resource to create or update a reference. -Therefore, in order to resolve the actual ids of those references in sync process, `ResourceIdentifier`s with their `key`s have to be supplied. - -|Reference Field| Type | -|:---|:---------------------------------| -| `parent` | CategoryResourceIdentifier | -| `custom.type` | TypeResourceIdentifier | -| `assets.custom.type` | TypeResourceIdentifier | - -> Note that a reference without the key field will be considered as existing resource on the target commercetools project and the library will issue an update/create an API request without reference resolution. - -##### Persistence of Category Drafts with irresolvable parent - -A CategoryDraft X could have a parent Category Y. But It could be that the parent Category Y is not supplied before X, -which means the sync could fail to create/updating X. It could also be that Y is not supplied at all in this batch but at a later batch. - -The library keeps track of such "referencing" Category Drafts like X and persists them in storage -(**Commercetools platform `customObjects` in the target project** , in this case) -to keep them and create/update them accordingly whenever the referenced drafts exist in the target project. - -The `customObject` will have a `container:` **`"commercetools-sync-java.UnresolvedReferencesService.categoryDrafts"`** -and a `key` representing the key of the category Drafts that is waiting to be created/updated. - -Here is an example of a `CustomObject` in the target project that represents a category Draft with the key `categoryKey1`. -Being persisted as `CustomObject` means that the referenced parent Category with the key `nonExistingParent` does not exist yet. - -```json -{ - "id": "81dcb42f-1959-4412-a4bb-8ad420d0d11f", - "version": 1, - "createdAt": "2021-01-13T12:19:45.937Z", - "lastModifiedAt": "2021-01-13T12:19:45.937Z", - "lastModifiedBy": { - "clientId": "7OSAGVPscneW_KS4nqskFkrd", - "isPlatformClient": false - }, - "createdBy": { - "clientId": "7OSAGVPscneW_KS4nqskFkrd", - "isPlatformClient": false - }, - "container": "commercetools-sync-java.UnresolvedReferencesService.categoryDrafts", - "key": "8732a63fa8ca457e86f4075340d65154e7e2476a", - "value": { - "missingReferencedKeys": [ - "nonExistingParent" - ], - "waitingDraft": { - "custom": { - "type": { - "key": "oldCategoryCustomTypeKey" - }, - "fields": { - "backgroundColor": { - "de": "rot", - "en": "red" - }, - "invisibleInShop": false - } - }, - "key": "categoryKey1", - "name": { - "en": "furniture" - }, - "parent": { - "key": "nonExistingParent" - }, - "slug": { - "en": "new-furniture1" - } - } - } - } - -``` -As soon, as the referenced parent Category Draft is supplied to the sync, the Category will be created/updated and the -`CustomObject` will be removed from the target project. - -##### Syncing from a commercetools project - -When syncing from a source commercetools project, you can use [`toCategoryDrafts`](#todo) -method that transforms(resolves by querying and caching key-id pairs) and maps from a `Category` to `CategoryDraft` using cache in order to make them ready for reference resolution by the sync, for example: - -````java -// Build ByProjectKeyCategoriesGet for fetching categories from a source CTP project without any references expanded for the sync: -final ByProjectKeyCategoriesGet byProjectKeyCategoriesGet = client.categories().get(); - -// Query all categories (NOTE this is just for example, please adjust your logic) -final List categories = QueryUtils.queryAll(byProjectKeyCategoriesGet, - (categories) -> categories) - .thenApply(lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())) - .toCompletableFuture() - .join(); -```` - -In order to transform and map the `Category` to `CategoryDraft`, -Utils method `toCategoryDrafts` requires `projectApiRoot`, implementation of [`ReferenceIdToKeyCache`](#todo) and `categories` as parameters. -For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](#todo). -Example as shown below: - -````java -//Implement the cache using library class. -final ReferenceIdToKeyCache referenceIdToKeyCache = new CaffeineReferenceIdToKeyCacheImpl(); - -//For every reference fetch its key using id, cache it and map from Category to CategoryDraft. With help of the cache same reference keys can be reused. -final CompletableFuture> categoryDrafts = CategoryTransformUtils.toCategoryDrafts(client, referenceIdToKeyCache, categories); -```` - -##### Syncing from an external resource - -- When syncing from an external resource, `ResourceIdentifier`s with their `key`s have to be supplied as following example: - -````java -final CategoryDraft categoryDraft = - CategoryDraftBuilder.of(ofEnglish("name"), ofEnglish("slug")) - .parent(ResourceIdentifier.ofKey("parent-category-key")) // note that parent provided with key - .custom(CustomFieldsDraft.ofTypeKeyAndJson("type-key", emptyMap())) // note that custom type provided with key - .assets(singletonList( - AssetDraftBuilder.of(emptyList(), LocalizedString.ofEnglish("asset-name")) - .custom(CustomFieldsDraft.ofTypeKeyAndJson("type-key", emptyMap())) // note that custom type provided with key - .key("asset-key") - .build() - )) - .build(); -```` - - -````java -final CustomFieldsDraft customFields = CustomFieldsDraftBuilder.of() - .type(TypeResourceIdentifierBuilder.of().key("type-key").build()) // note that custom type provided with key - .fields(FieldContainerBuilder.of().values(Collections.emptyMap()).build()) - .build(); - -final CategoryResourceIdentifier categoryResourceIdentifier = CategoryResourceIdentifierBuilder.of() - .key("category-key") - .build(); - -final CategoryDraft categoryDraft = CategoryDraftBuilder.of() - .key("category-key") - .slug(LocalizedString.of(Locale.ENGLISH, "category-slug")) - .name(LocalizedString.of(Locale.ENGLISH, "category-name")) - .description(LocalizedString.of(Locale.ENGLISH, "category-description")) - .externalId("external-id") - .metaDescription(LocalizedString.of(Locale.ENGLISH, "meta-description")) - .metaKeywords(LocalizedString.of(Locale.ENGLISH, "meta-keywords")) - .metaTitle(LocalizedString.of(Locale.ENGLISH, "meta-title")) - .orderHint("order-hint") - .custom(customFields) - .parent(categoryResourceIdentifier) - .build() -```` - -#### SyncOptions - -After the `ProjectApiRoot` is set up, a `CategorySyncOptions` should be built as follows: -````java -// instantiating a CategorySyncOptions -final CategorySyncOptions categorySyncOptions = CategorySyncOptionsBuilder.of(projectApiRoot).build(); -```` - -`SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. -Available configurations: - -##### errorCallback -A callback that is called whenever an error event occurs during the sync process. Each resource executes its own -error-callback. When sync process of particular resource runs successfully, it is not triggered. It contains the -following context about the error-event: - -* sync exception -* category draft from the source -* category of the target project (only provided if an existing category could be found) -* the update-actions, which failed (only provided if an existing category could be found) - -````java - final Logger logger = LoggerFactory.getLogger(CategorySync.class); - final CategorySyncOptions categorySyncOptions = CategorySyncOptionsBuilder - .of(projectApiRoot) - .errorCallback((syncException, draft, category, updateActions) -> - logger.error(new SyncException("My customized message"), syncException)).build(); -```` - -##### warningCallback -A callback that is called whenever a warning event occurs during the sync process. Each resource executes its own -warning-callback. When sync process of particular resource runs successfully, it is not triggered. It contains the -following context about the warning message: - -* sync exception -* category draft from the source -* category of the target project (only provided if an existing category could be found) - -````java - final Logger logger = LoggerFactory.getLogger(CategorySync.class); - final CategorySyncOptions categorySyncOptions = CategorySyncOptionsBuilder - .of(projectApiRoot) - .warningCallback((syncException, draft, category, updateActions) -> - logger.warn(new SyncException("My customized message"), syncException)).build(); -```` - -##### beforeUpdateCallback -During the sync process if a target category and a category draft are matched, this callback can be used to -intercept the **_update_** request just before it is sent to commercetools platform. This allows the user to modify -update actions array with custom actions or discard unwanted actions. The callback provides the following information : - - * category draft from the source - * category from the target project - * update actions that were calculated after comparing both - -````java -// Example: Ignore update actions that change category name -final TriFunction< - List, CategoryDraft, Category, List> - beforeUpdateCategoryCallback = - (updateActions, newCategoryDraft, oldCategory) -> updateActions.stream() - .filter(updateAction -> !(updateAction instanceof CategoryChangeNameAction)) - .collect(Collectors.toList()); - -final CategorySyncOptions categorySyncOptions = - CategorySyncOptionsBuilder.of(projectApiRoot).beforeUpdateCallback(beforeUpdateCategoryCallback).build(); -```` - -##### beforeCreateCallback -During the sync process if a category draft should be created, this callback can be used to intercept -the **_create_** request just before it is sent to commercetools platform. It contains following information : - - * category draft that should be created - -Please refer to [example in product sync document](PRODUCT_SYNC.md#beforeCreateCallback). - -##### batchSize -A number that could be used to set the batch size with which categories are fetched and processed, -as categories are obtained from the target project on commercetools platform in batches for better performance. The -algorithm accumulates up to `batchSize` resources from the input list, then fetches the corresponding categories -from the target project on commecetools platform in a single request. Playing with this option can slightly improve or -reduce processing speed. If it is not set, the default batch size is **50** for category sync. - -````java -final CategorySyncOptions categorySyncOptions = - CategorySyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); -```` - -##### cacheSize -In the service classes of the commercetools-sync-java library, we have implemented an in-memory [LRU cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) to store a map used for the reference resolution of the library. -The cache reduces the reference resolution based calls to the commercetools API as the required fields of a resource will be fetched only one time. This cached fields then might be used by another resource referencing the already resolved resource instead of fetching from commercetools API. It turns out, having the in-memory LRU cache will improve overall performance of the sync library and commercetools API. -which will improve the overall performance of the sync and commercetools API. - -Playing with this option can change the memory usage of the library. If it is not set, the default cache size is `10.000` for category sync. -````java -final CategorySyncOptions categorySyncOptions = - CategorySyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); -```` - -### Running the sync -After all the aforementioned points in the previous section have been fulfilled, to run the sync: -````java -// instantiating a category sync -final CategorySync categorySync = new CategorySync(categorySyncOptions); - -// execute the sync on your list of categories -CompletionStage syncStatisticsStage = categorySync.sync(categoryDrafts); -```` -The result of the completing the `syncStatisticsStage` in the previous code snippet contains a `CategorySyncStatistics` -which contains all the stats of the sync process; which includes a report message, the total number of updated, created, -failed, processed categories and the processing time of the last sync batch in different time units and in a -human-readable format. - -````java -final CategorySyncStatistics stats = syncStatisticsStage.toCompletebleFuture().join(); -stats.getReportMessage(); -/*"Summary: 2000 categories were processed in total (1000 created, 995 updated, 5 failed to sync and 0 categories with a missing parent)."*/ -```` - -__Note__ The statistics object contains the processing time of the last batch only. This is due to two reasons: - - 1. The sync processing time should not take into account the time between supplying batches to the sync. - 2. It is not known by the sync which batch is going to be the last one supplied. - -##### More examples of how to use the sync - -1. [Sync from another CTP project as a source](#todo). -2. [Sync from an external source](#todo). - -*Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* - -### Build all update actions - -A utility method provided by the library to compare a Category with a new CategoryDraft and results in a list of category update actions. -```java -final List updateActions = CategorySyncUtils.buildActions(category, categoryDraft, categorySyncOptions); -``` - -Examples of its usage can be found in the tests -[here](#todo). - - -### Build particular update action(s) - -Utility methods provided by the library to compare the specific fields of a Category and a new CategoryDraft, and in turn, build - the update action. One example is the `buildChangeNameUpdateAction` which compares names: -````java -final Optional updateAction = buildChangeNameUpdateAction(oldCategory, categoryDraft); -```` -More examples of those utils for different fields can be found [here](#todo). - -## Migration Guide - -The category-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with -any HTTP client module. The default one is `commercetools-http-client`. - -```xml - - - LATEST - - - - - com.commercetools.sdk - commercetools-http-client - ${commercetools.version} - - - com.commercetools.sdk - commercetools-sdk-java-api - ${commercetools.version} - - - -``` - -### Client configuration and creation - -For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). - -### Signature of CategorySyncOptions - -As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `CategoryDraft`, `Category` and `CategoryUpdateAction` from `package com.commercetools.api.models.category.*` - -> Note: Type `UpdateAction` has changed to `CategoryUpdateAction`. Make sure you create and supply a specific CategoryUpdateAction in `beforeUpdateCallback`. For that you can use the [library-utilities](#todo) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): - -```java -// Example: Create a category update action to change name taking the 'newName' of the categoryDraft - final Function createBeforeUpdateAction = - (newName) -> CategoryChangeNameAction.builder().name(newName).build(); - -// Add the change name action to the list of update actions before update is executed - final TriFunction< - List, CategoryDraft, Category, List> - beforeUpdateCategoryCallback = - (updateActions, newCategoryDraft, oldCategory) -> { - final CategoryUpdateAction beforeUpdateAction = - createBeforeUpdateAction.apply(newCategoryDraft.getName()); - updateActions.add(beforeUpdateAction); - return updateActions; - }; -``` - -### Build CategoryDraft (syncing from external project) - -The category-sync expects a list of `CategoryDraft`s to process. If you use java-sync-library to sync your categories from any external system into a commercetools platform project you have to convert your data into CTP compatible `CategoryDraft` type. This was done in previous version using `DraftBuilder`s. -The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: - -```java -// CategoryDraftBuilder in v1 takes parameters 'name' and 'slug' -final CategoryDraft categoryDraft = - CategoryDraftBuilder - .of(ofEnglish("name"), ofEnglish("slug")) - .key("category-key") - .build(); - -// CategoryDraftBuilder in v2 -final CategoryDraft categoryDraft = - CategoryDraftBuilder - .of() - .name(LocalizedString.ofEnglish("name")) - .slug(LocalizedString.ofEnglish("slug")) - .key("category-key") - .build(); -``` -For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). - -### Query for Categories (syncing from CTP project) - -If you sync categories between different commercetools projects you probably use [CategoryTransformUtils#toCategoryDrafts](#todo) to transform `Category` into `CategoryDraft` which can be used by the category-sync. -However, if you need to query `Categories` from a commercetools project instead of passing `CategoryQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. -Here's an example: - -```java -// SDK v1: CategoryQuery to fetch all categories -final CategoryQuery query = CategoryQuery.of(); - -final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); - -// SDK v2: Create and execute query to fetch all categories in one line -final CategoryPagedQueryResponse result = apiRoot.categories().get().executeBlocking().getBody(); -``` -[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. - -### JVM-SDK-V2 migration guide - -On any other needs to migrate your project using jvm-sdk-v2 please refer to it's [Migration Guide](https://docs.commercetools.com/sdk/java-sdk-migrate). diff --git a/docs/sdk2/usage/CLEANUP_GUIDE.md b/docs/sdk2/usage/CLEANUP_GUIDE.md deleted file mode 100644 index eeba9d3bbf..0000000000 --- a/docs/sdk2/usage/CLEANUP_GUIDE.md +++ /dev/null @@ -1,3 +0,0 @@ -# Cleanup of old unresolved reference custom objects - -TODO diff --git a/docs/sdk2/usage/CUSTOMER_SYNC.md b/docs/sdk2/usage/CUSTOMER_SYNC.md deleted file mode 100644 index 27e1ab9607..0000000000 --- a/docs/sdk2/usage/CUSTOMER_SYNC.md +++ /dev/null @@ -1,277 +0,0 @@ -# Customer Sync - -The module used for importing/syncing Customers into a commercetools project. -It also provides utilities for generating update actions based on the comparison of a [Customer](https://docs.commercetools.com/api/projects/customers#customer) -against a [CustomerDraft](https://docs.commercetools.com/api/projects/customers#customerdraft). - - - - -- [Usage](#usage) - - [Prerequisites](#prerequisites) - - [ProjectApiRoot](#projectapiroot) - - [Required Fields](#required-fields) - - [Reference Resolution](#reference-resolution) - - [Syncing from a commercetools project](#syncing-from-a-commercetools-project) - - [Syncing from an external resource](#syncing-from-an-external-resource) - - [SyncOptions](#syncoptions) - - [errorCallback](#errorcallback) - - [warningCallback](#warningcallback) - - [beforeUpdateCallback](#beforeupdatecallback) - - [beforeCreateCallback](#beforecreatecallback) - - [batchSize](#batchsize) - - [cacheSize](#cachesize) - - [Running the sync](#running-the-sync) - - [More examples of how to use the sync](#more-examples-of-how-to-use-the-sync) - - [Build all update actions](#build-all-update-actions) - - [Build particular update action(s)](#build-particular-update-actions) -- [Caveats](#caveats) - - - -## Usage - -### Prerequisites -#### ProjectApiRoot - -Use the [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/java-sdk-v2-product-sync-migration/src/main/java/com/commercetools/sync/sdk2/commons/utils/ClientConfigurationUtils.java) which apply the best practices for `ProjectApiRoot` creation. -To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](https://github.com/commercetools/commercetools-sdk-java-v2/blob/main/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/oauth2/ClientCredentialsBuilder.java) -If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). - -````java -final ClientCredentials clientCredentials = - new ClientCredentialsBuilder() - .withClientId("client-id") - .withClientSecret("client-secret") - .withScopes("scopes") - .build(); -final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); -```` - -#### Required Fields - -The following fields are **required** to be set in, otherwise, they won't be matched by sync: - -|Draft|Required Fields|Note| -|---|---|---| -| [CustomerDraft](https://docs.commercetools.com/api/projects/customers#customerdraft) | `key` | Also, the customers in the target project are expected to have the `key` fields set. | -| [CustomerDraft](https://docs.commercetools.com/api/projects/customers#customerdraft) | `address.key` | Every customer [BaseAddress](https://docs.commercetools.com/api/types#ctp:api:type:BaseAddress) needs a unique key to match the existing `Address` with the new `AddressDraft`. | - -#### Reference Resolution - -In commercetools, a reference can be created by providing the key instead of the ID with the type [ResourceIdentifier](https://docs.commercetools.com/api/types#resourceidentifier). -When the reference key is provided with a `ResourceIdentifier`, the sync will resolve the resource with the given key and use the ID of the found resource to create or update a reference. -Therefore, in order to resolve the actual ids of those references in the sync process, `ResourceIdentifier`s with their `key`s have to be supplied. - -|Reference Field|Type| -|:---|:---| -| `customerGroup` | CustomerGroupResourceIdentifier | -| `stores` | List of StoreResourceIdentifier | -| `custom.type` | TypeResourceIdentifier | - -> Note that a reference without the key field will be considered as an existing resource on the target commercetools project and the library will issue an update/create an API request without reference resolution. - -##### Syncing from a commercetools project - -When syncing from a source commercetools project, you can use [`toCustomerDrafts`](https://github.com/commercetools/commercetools-sync-java/blob/java-sdk-v2-product-sync-migration/src/main/java/com/commercetools/sync/sdk2/customers/utils/CustomerTransformUtils.java#L42) - method that transforms(resolves by querying and caching key-id pairs) and maps from a `Customer` to `CustomerDraft` using cache in order to make them ready for reference resolution by the sync, for example: - -````java -// Build ByProjectKeyCustomersGet for fetching customers from a source CTP project without any references expanded for the sync: -final ByProjectKeyCustomersGet byProjectKeyCustomersGet = client.customers().get(); - -// Query all customers (NOTE this is just for example, please adjust your logic) -final List customers = QueryUtils.queryAll(byProjectKeyCustomersGet, - (customers) -> customers) - .thenApply(lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())) - .toCompletableFuture() - .join(); -```` - -In order to transform and map the `Customer` to `CustomerDraft`, -Utils method `toCustomerDrafts` requires `projectApiRoot`, implementation of [`ReferenceIdToKeyCache`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ReferenceIdToKeyCache.java) and `customers` as parameters. -For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/CaffeineReferenceIdToKeyCacheImpl.java). -Example as shown below: - -````java -//Implement the cache using library class. -final ReferenceIdToKeyCache referenceIdToKeyCache = new CaffeineReferenceIdToKeyCacheImpl(); - -//For every reference fetch its key using id, cache it and map from Customer to CustomerDraft. With help of the cache same reference keys can be reused. -CompletableFuture> customerDrafts = CustomerTransformUtils.toCustomerDrafts(client, referenceIdToKeyCache, customers); -```` - -##### Syncing from an external resource - -- When syncing from an external resource, `ResourceIdentifier`s with their `key`s have to be supplied as following example: - -````java -final CustomFieldsDraft customFields = CustomFieldsDraftBuilder.of() - .type(TypeResourceIdentifierBuilder.of().key("type-key").build()) // note that custom type provided with key - .fields(FieldContainerBuilder.of().values(Collections.emptyMap()).build()) - .build(); -final AddressDraft address = AddressDraftBuilder.of() - .key("address-key-1") // note that addresses has to be provided with their keys - .country("DE") - .build(); -final CustomerDraft customerDraft = CustomerDraftBuilder.of() - .email("email@example.com") - .password("password") - .key("customer-key") - .customerGroup(CustomerGroupRescourceIdentifierBuilder.of().key("customer-group-key").build()) // note that customergroup reference provided with key - .addresses(address) - .custom(customFields) - .stores(StoresResourceIdentifierBuilder.of().key("store-key1").build(), StoresResourceIdentifierBuilder.of().key("store-key2").build()) // note that store reference provided with key - .build(); -```` - -#### SyncOptions - -After the `ProjectApiRoot` is set up, a `CustomerSyncOptions` should be built as follows: -````java -// instantiating a CustomerSyncOptions -final CustomerSyncOptions customerSyncOptions = CustomerSyncOptionsBuilder.of(projectApiRoot).build(); -```` - -`SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. -Available configurations: - -##### errorCallback -A callback that is called whenever an error event occurs during the sync process. Each resource executes its own -error-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the error-event: - -* sync exception -* customer draft from the source -* customer of the target project (only provided if an existing customer could be found) -* the update-actions, which failed (only provided if an existing customer could be found) - -````java - final Logger logger = LoggerFactory.getLogger(CustomerSync.class); - final CustomerSyncOptions customerSyncOptions = CustomerSyncOptionsBuilder - .of(projectApiRoot) - .errorCallback((syncException, draft, customer, updateActions) -> - logger.error(new SyncException("My customized message"), syncException)).build(); -```` - -##### warningCallback -A callback is called whenever a warning event occurs during the sync process. Each resource executes its own -warning-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the warning message: - -* sync exception -* customer draft from the source -* customer of the target project (only provided if an existing customer could be found) - -````java - final Logger logger = LoggerFactory.getLogger(CustomerSync.class); - final CustomerSyncOptions customerSyncOptions = CustomerSyncOptionsBuilder - .of(projectApiRoot) - .warningCallback((syncException, draft, customer) -> - logger.warn(new SyncException("My customized message"), syncException)).build(); -```` - -##### beforeUpdateCallback -During the sync process, if a target customer and a customer draft are matched, this callback can be used to -intercept the **_update_** request just before it is sent to the commercetools platform. This allows the user to modify -update actions array with custom actions or discard unwanted actions. The callback provides the following information : - - * customer draft from the source - * customer from the target project - * update actions that were calculated after comparing both - -````java -// Example: Ignore update actions which contain setting of lastName action -final TriFunction, CustomerDraft, Customer, - List> beforeUpdateCallback, = - (updateActions, newCustomerDraft, oldCustomer) -> updateActions - .stream() - .filter(updateAction -> !(updateAction instanceof CustomerSetLastNameActionImpl)) - .collect(Collectors.toList()); - -final CustomerSyncOptions customerSyncOptions = CustomerSyncOptionsBuilder - .of(projectApiRoot) - .beforeUpdateCallback(beforeUpdateCallback) - .build(); -```` - -##### beforeCreateCallback -During the sync process, if a customer draft should be created, this callback can be used to intercept the **_create_** request just before it is sent to the commercetools platform. It contains the following information : - - * customer draft that should be created - - Please refer to the [example in the product sync document](https://github.com/commercetools/commercetools-sync-java/blob/master/docs/usage/PRODUCT_SYNC.md#example-set-publish-stage-if-category-references-of-given-product-draft-exists). - -##### batchSize -A number that could be used to set the batch size with which customers are fetched and processed, -as customers are obtained from the target project on the commercetools platform in batches for better performance. The algorithm accumulates up to `batchSize` resources from the input list, then fetches the corresponding customers -from the target project on the commercetools platform in a single request. Playing with this option can slightly improve or reduce processing speed. If it is not set, the default batch size is 50 for customer sync. - -````java -final CustomerSyncOptions customerSyncOptions = - CustomerSyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); -```` - -##### cacheSize -In the service classes of the commercetools-sync-java library, we have implemented an in-memory [LRU cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) to store a map used for the reference resolution of the library. -The cache reduces the reference resolution based calls to the commercetools API as the required fields of a resource will be fetched only one time. These cached fields then might be used by another resource referencing the already resolved resource instead of fetching from commercetools API. It turns out, having the in-memory LRU cache will improve the overall performance of the sync library and commercetools API. -which will improve the overall performance of the sync and commercetools API. - -Playing with this option can change the memory usage of the library. If it is not set, the default cache size is `10.000` for customer sync. - -````java -final CustomerSyncOptions customerSyncOptions = - CustomerSyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); -```` - -### Running the sync -When all prerequisites are fulfilled, follow those steps to run the sync: - -````java -// instantiating a customer sync -final CustomerSync customerSync = new CustomerSync(customerSyncOptions); - -// execute the sync on your list of customers -CompletionStage syncStatisticsStage = customerSync.sync(customerDrafts); -```` -The result of completing the `syncStatisticsStage` in the previous code snippet contains a `CustomerSyncStatistics` -which contains all the stats of the sync process; which includes a report message, the total number of updated, created, -failed, processed customers, and the processing time of the last sync batch in different time units and in a -human-readable format. - -````java -final CustomerSyncStatistics stats = syncStatisticsStage.toCompletebleFuture().join(); -stats.getReportMessage(); -/*"Summary: 100 customers were processed in total (11 created, 87 updated, 2 failed to sync)."*/ -```` - -__Note__ The statistics object contains the processing time of the last batch only. This is due to two reasons: - - 1. The sync processing time should not take into account the time between supplying batches to the sync. - 2. It is not known by the sync which batch is going to be the last one supplied. - -#### More examples of how to use the sync - - [Sync from an external source](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/externalsource/customers/CustomerSyncIT.java). - -*Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* - -### Build all update actions -A utility method provided by the library to compare a `Customer` to a new `CustomerDraft`. The results are collected in a list of customer update actions. -```java -List updateActions = CustomerSyncUtils.buildActions(customer, customerDraft, customerSyncOptions); -``` - -### Build particular update action(s) -The library provides utility methods to compare specific fields of a `Customer` and a new `CustomerDraft`, and builds the update action(s) as a result. -One example is the `buildChangeEmailUpdateAction` which compare email addresses: -````java -Optional updateAction = CustomerUpdateActionUtils.buildChangeEmailUpdateAction(oldCustomer, customerDraft); -```` - -More examples for particular update actions can be found in the test scenarios for [CustomerUpdateActionUtils](https://github.com/commercetools/commercetools-sync-java/tree/master/src/test/java/com/commercetools/sync/customers/utils/CustomerUpdateActionUtilsTest.java) -and [AddressUpdateActionUtils](https://github.com/commercetools/commercetools-sync-java/tree/master/src/test/java/com/commercetools/sync/customers/utils/AddressUpdateActionUtilsTest.java). - -## Caveats -The library does not support the synchronization of the `password` field of existing customers. -For customers that do not exist in the project, a password will be created with the given customer draft’s password. diff --git a/docs/sdk2/usage/CUSTOM_OBJECT_SYNC.md b/docs/sdk2/usage/CUSTOM_OBJECT_SYNC.md deleted file mode 100644 index 23aebe18fe..0000000000 --- a/docs/sdk2/usage/CUSTOM_OBJECT_SYNC.md +++ /dev/null @@ -1,258 +0,0 @@ -# Custom Object Sync - -Module used for importing/syncing CustomObject into a commercetools project. -It also provides utilities for correlating a custom object to a given custom object draft based on the -comparison of a [CustomObject](https://docs.commercetools.com/api/projects/custom-objects#customobject) -against a [CustomObjectDraft](https://docs.commercetools.com/api/projects/custom-objects#customobjectdraft). - - - - -- [Usage](#usage) - - [Prerequisites](#prerequisites) - - [ProjectApiRoot](#projectapiroot) - - [Required Fields](#required-fields) - - [SyncOptions](#syncoptions) - - [errorCallback](#errorcallback) - - [warningCallback](#warningcallback) - - [beforeUpdateCallback](#beforeupdatecallback) - - [beforeCreateCallback](#beforecreatecallback) - - [batchSize](#batchsize) - - [cacheSize](#cachesize) - - [Running the sync](#running-the-sync) - - [More examples of how to use the sync](#more-examples-of-how-to-use-the-sync) -- [Migration Guide](#migration-guide) - - [Client configuration and creation](#client-configuration-and-creation) - - [Signature of CustomObjectSyncOptions](#signature-of-customobjectsyncoptions) - - [Build CustomObjectDraft (syncing from external project)](#build-customobjectdraft-syncing-from-external-project) - - [Query for CustomObjects](#query-for-customobjects) - - [JVM-SDK-V2 migration guide](#jvm-sdk-v2-migration-guide) - - - -## Usage - -### Prerequisites - -#### ProjectApiRoot - -Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](#todo) -If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). - -````java -final ClientCredentials clientCredentials = - new ClientCredentialsBuilder() - .withClientId("client-id") - .withClientSecret("client-secret") - .withScopes("scopes") - .build(); -final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); -```` - -#### Required Fields - -The following fields are **required** to be set in, otherwise, they won't be matched by sync: - -|Draft|Required Fields|Note| -|---|---|---| -| [CustomObjectDraft](https://docs.commercetools.com/api/projects/custom-objects#customobjectdraft) | `key` | Also, the custom objects in the target project are expected to have the `key` fields set. | -| [CustomObjectDraft](https://docs.commercetools.com/api/projects/custom-objects#customobjectdraft) | `container` | Also, the custom objects in the target project are expected to have the `container` fields set. | - -#### SyncOptions - -After the `projectApiRoot` is set up, a `CustomObjectSyncOptions` should be built as follows: -````java -// instantiating a CustomObjectSyncOptions -final CustomObjectSyncOptions customObjectSyncOptions = CustomObjectSyncOptionsBuilder.of(projectApiRoot).build(); -```` - -`SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. -Available configurations: - -##### errorCallback -A callback that is called whenever an error event occurs during the sync process. Each resource executes its own -error-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the error-event: - -* sync exception -* custom object draft from the source -* custom object of the target project (only provided if an existing custom object could be found) -* a fake list of update actions, as custom objects API does not provide update actions. [NoopResourceUpdateAction.java](#todo) - -````java - final Logger logger = LoggerFactory.getLogger(CustomObjectSync.class); - final CustomObjectSyncOptions customObjectSyncOptions = CustomObjectSyncOptionsBuilder - .of(projectApiRoot) - .errorCallback((syncException, draft, customObject, updateActions) -> - logger.error(new SyncException("My customized message"), syncException)).build(); -```` - -##### warningCallback -A callback is called whenever a warning event occurs during the sync process. Each resource executes its own -warning-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the warning message: - -* sync exception -* custom object draft from the source -* custom object of the target project (only provided if an existing custom object could be found) - -````java - final Logger logger = LoggerFactory.getLogger(CustomObjectSync.class); - final CustomObjectSyncOptions customObjectSyncOptions = CustomObjectSyncOptionsBuilder - .of(projectApiRoot) - .warningCallback((syncException, draft, customObject) -> - logger.warn(new SyncException("My customized message"), syncException)).build(); -```` - -##### beforeUpdateCallback -In theory, `CustomObjectSyncOptions` provides callback before update operation. User can customize their own callback and inject -into sync options. However, in the actual case, `beforeUpdateCallback`is not triggered in the custom object sync process. When -the new custom object draft has the same key and container as an existing custom object but different in custom object values, -the sync process automatically performs the create/update operation. The value of a corresponding custom object in the target project is overwritten. This approach is different from other resources and no update action is involved. - -Also see the API documentation of [Create-or-update-customobject](https://docs.commercetools.com/api/projects/custom-objects#create-or-update-customobject) - -##### beforeCreateCallback -During the sync process, if a custom object draft should be created, this callback can be used to intercept the **_create_** request just before it is sent to the commercetools platform. It contains the following information : - - * custom object draft that should be created - -Please refer to [example in product sync document](PRODUCT_SYNC.md#beforecreatecallback). - -##### batchSize -A number that could be used to set the batch size with which custom objects are fetched and processed, -as custom objects are obtained from the target project on the commercetools platform in batches for better performance. The algorithm accumulates up to `batchSize` resources from the input list, then fetches the corresponding custom objects from the target project on the commecetools platform in a single request. Playing with this option can slightly improve or reduce processing speed. If it is not set, the default batch size is 50 for custom object sync. - -````java -final CustomObjectSyncOptions customObjectSyncOptions = - CustomObjectSyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); -```` - -##### cacheSize -In the service classes of the commercetools-sync-java library, we have implemented an in-memory [LRU cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) to store a map used for the reference resolution of the library. -The cache reduces the reference resolution based calls to the commercetools API as the required fields of a resource will be fetched only one time. These cached fields then might be used by another resource referencing the already resolved resource instead of fetching from commercetools API. It turns out, having the in-memory LRU cache will improve the overall performance of the sync library and commercetools API. -which will improve the overall performance of the sync and commercetools API. - -Playing with this option can change the memory usage of the library. If it is not set, the default cache size is `10.000` for custom object sync. - -````java -final CustomObjectSyncOptions customObjectSyncOptions = - CustomObjectSyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); -```` - -### Running the sync -After all the aforementioned points in the previous section have been fulfilled, to run the sync: -````java -// instantiating a CustomObjectSync -final CustomObjectSync customObjectSync = new CustomObjectSync(customObjectSyncOptions); - -// execute the sync on your list of custom object drafts -CompletionStage syncStatisticsStage = customObjectSync.sync(customObjectDrafts); -```` -The result of completing the `syncStatisticsStage` in the previous code snippet contains a `CustomObjectSyncStatistics` -which contains all the stats of the sync process; which includes a report message, the total number of updated, created, -failed, processed custom objects and the processing time of the last sync batch in different time units and in a -human-readable format. - -````java -final CustomObjectSyncStatistics stats = syncStatisticsStage.toCompletebleFuture().join(); -stats.getReportMessage(); -/*"Summary: 2000 custom objects were processed in total (1000 created, 995 updated, 5 failed to sync)."*/ -```` - -__Note__ The statistics object contains the processing time of the last batch only. This is due to two reasons: - - 1. The sync processing time should not take into account the time between supplying batches to the sync. - 2. It is not known by the sync which batch is going to be the last one supplied. - -#### More examples of how to use the sync - -- [Sync from an external source](#todo). - -*Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* - -More examples of those utils for different custom objects can be found [here](#todo). - -## Migration Guide - -The custom-object-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with -any HTTP client module. The default one is `commercetools-http-client`. - -```maven - // Sample maven pom.xml - - LATEST - - - - - com.commercetools.sdk - commercetools-http-client - ${commercetools.version} - - - com.commercetools.sdk - commercetools-sdk-java-api - ${commercetools.version} - - - -``` - -### Client configuration and creation - -For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). - -### Signature of CustomObjectSyncOptions - -As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `CustomObjectDraft`, `CustomObject` (without type parameter as in v1) from `package com.commercetools.api.models.custom_object.*` and `NoopResourceUpdateAction` which is a fake class representing resource without update actions like custom-object. - -> Note: Make sure `beforeUpdateCallback` isn't used as the sync will **not** trigger it in the process. -> Note: Further make sure on `errorCallback` to not operate on`NoopResourceUpdateAction`'s actions field as it is null. - -### Build CustomObjectDraft (syncing from external project) - -The custom-object-sync expects a list of `CustomObjectDraft`s to process. To sync your categories from anywhere (including other CTP project) into a commercetools platform project you have to convert your data into CTP compatible `CategoryDraft` type. This was done in previous version using `DraftBuilder`s. -The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: - -> Note: In v1 the value in CustomObjectDraft is of generic type and custom-object-sync was expecting `JsonNode` as value. This changed in V2 SDK and the sync-library, and value field is of type `Object` now. -```java -// CategoryDraft builder in v1 takes parameters 'container', 'key' and 'value' -final CustomObjectDraft cutomObjectDraft = - CustomObjectDraft.ofUnversionedUpsert( - "someContainer", - "someKey", - JsonNodeFactory.instance.objectNode().put("json-field", "json-value")); - -// CustomObjectDraftBuilder in v2 -final CustomObjectDraft newCustomObjectDraft = - CustomObjectDraftBuilder.of() - .container("someContainer") - .key("someKey") - .value("someValue") - .build(); -``` -For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). - -### Query for CustomObjects - -If you need to query `CustomObjects` from a commercetools project instead of passing `CustomObjectQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. -Here's an example: - -```java -// SDK v1: CategoryQuery to fetch all categories -final CustomObjectQuery query = CustomObjectQuery.ofJsonNode(); - -final PagedQueryResult> pagedQueryResult = sphereClient.executeBlocking(query); - -// SDK v2: Create and execute query to fetch all custom objects in one line -final CustomObjectPagedQueryResponse result = apiRoot.customObjects().get().executeBlocking().getBody(); -``` -[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. - -### JVM-SDK-V2 migration guide - -On any other needs to migrate your project using jvm-sdk-v2 please refer to it's [Migration Guide](https://docs.commercetools.com/sdk/java-sdk-migrate). - diff --git a/docs/sdk2/usage/IMPORTANT_USAGE_TIPS.md b/docs/sdk2/usage/IMPORTANT_USAGE_TIPS.md deleted file mode 100644 index 80a07f5763..0000000000 --- a/docs/sdk2/usage/IMPORTANT_USAGE_TIPS.md +++ /dev/null @@ -1,48 +0,0 @@ -# Important Usage Tips - - - -- [Customized `ProjectApiRoot` Creation](#customized-projectapiroot-creation) -- [Tuning the Sync Process](#tuning-the-sync-process) - - - -#### Customized `ProjectApiRoot` Creation -When creating a customized `ProjectApiRoot` the following remarks should be considered: - -- Limit the number of concurrent requests done to CTP. This can be done by adding a QueueMiddleware to the ApiRootBuilder [QueueMiddleware](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/com/commercetools/docs/meta/ClientTuning.html#limit-requests) - -- Retry on 5xx errors with a retry strategy. This can be achieved by adding a RetryRequestMiddleware to the ApiRootBuilder [RetryRequestMiddleware](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/com/commercetools/docs/meta/ClientTuning.html#retry-middleware) - -If you have no special requirements on the client creation, then you can use the `ClientConfigurationUtils#createClient` -util which applies the best practices for `ProjectApiRoot` creation. -To understand how to initialize those method arguments, please refer to the [unit test](https://github.com/commercetools/commercetools-sync-java/blob/master/src/test/java/com/commercetools/sync/commons/utils/ClientV2ConfigurationUtilsTest.java#L20) - -To tune / customize your client please refer to [Client Tuning](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/com/commercetools/docs/meta/ClientTuning.html) - -#### Tuning the Sync Process -The sync library is not meant to be executed in a parallel fashion. For example: -````java -final ProductSync productSync = new ProductSync(syncOptions); -final CompletableFuture syncFuture1 = productSync.sync(batch1).toCompletableFuture(); -final CompletableFuture syncFuture2 = productSync.sync(batch2).toCompletableFuture(); -CompletableFuture.allOf(syncFuture1, syncFuture2).join; -```` -The aforementioned example demonstrates how the library should **NOT** be used. The library, however, should be instead -used in a sequential fashion: -````java -final ProductSync productSync = new ProductSync(syncOptions); -productSync.sync(batch1) - .thenCompose(result -> productSync.sync(batch2)) - .toCompletableFuture() - .join(); -```` -By design, scaling the sync process should **not** be done by executing the batches themselves in parallel. However, it can be done either by: - - - Changing the number of [max parallel requests](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L116) within the `projectApiRoot` configuration. It defines how many requests the client can execute in parallel. - - or changing the draft [batch size](https://commercetools.github.io/commercetools-sync-java/v/9.2.1/com/commercetools/sync/commons/BaseSyncOptionsBuilder.html#batchSize-int-). It defines how many drafts can one batch contains. - -The current overridable default [configuration](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L45) of the `projectApiRoot` -is the recommended good balance for stability and performance for the sync process. - -In order to exploit the number of `max parallel requests`, the `batch size` should have a value set that is equal or higher. diff --git a/docs/sdk2/usage/INVENTORY_SYNC.md b/docs/sdk2/usage/INVENTORY_SYNC.md deleted file mode 100644 index f2fa705cd5..0000000000 --- a/docs/sdk2/usage/INVENTORY_SYNC.md +++ /dev/null @@ -1,382 +0,0 @@ -# InventoryEntry Sync - -The module used for importing/syncing InventoryEntries into a commercetools project. -It also provides utilities for generating update actions based on the comparison of a [InventoryEntry](https://docs.commercetools.com/api/projects/inventory#inventoryentry) -against a [InventoryEntryDraft](https://docs.commercetools.com/api/projects/inventory#inventoryentrydraft). - - - - -- [Usage](#usage) - - [Prerequisites](#prerequisites) - - [ProjectApiRoot](#projectapiroot) - - [Required Fields](#required-fields) - - [Reference Resolution](#reference-resolution) - - [Syncing from a commercetools project](#syncing-from-a-commercetools-project) - - [Syncing from an external resource](#syncing-from-an-external-resource) - - [SyncOptions](#syncoptions) - - [errorCallback](#errorcallback) - - [warningCallback](#warningcallback) - - [beforeUpdateCallback](#beforeupdatecallback) - - [beforeCreateCallback](#beforecreatecallback) - - [batchSize](#batchsize) - - [cacheSize](#cachesize) - - [ensureChannels](#ensurechannels) - - [Running the sync](#running-the-sync) - - [Build all update actions](#build-all-update-actions) - - [Build particular update action(s)](#build-particular-update-actions) -- [Migration Guide](#migration-guide) - - [Client configuration and creation](#client-configuration-and-creation) - - [Signature of InventorySyncOptions](#signature-of-inventorysyncoptions) - - [Build InventoryEntryDraft (syncing from external project)](#build-inventoryentrydraft-syncing-from-external-project) - - [Query for Inventories (syncing from CTP project)](#query-for-inventories-syncing-from-ctp-project) - - [JVM-SDK-V2 migration guide](#jvm-sdk-v2-migration-guide) - - - -## Usage - -### Prerequisites - -#### ProjectApiRoot - -Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](#todo) -If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). - -````java -final ClientCredentials clientCredentials = - new ClientCredentialsBuilder() - .withClientId("client-id") - .withClientSecret("client-secret") - .withScopes("scopes") - .build(); -final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); -```` - -#### Required Fields - -The following fields are **required** to be set in, otherwise, they won't be matched by sync: - -|Draft|Required Fields|Note| -|---|---|---| -| [InventoryEntryDraft](https://docs.commercetools.com/api/projects/inventory#inventoryentrydraft) | `sku` | Also, the inventory entries in the target project are expected to have the `sku` fields set. | - -#### Reference Resolution - -In commercetools, a reference can be created by providing the key instead of the ID with the type [ResourceIdentifier](https://docs.commercetools.com/api/types#ctp:api:type:ResourceIdentifier). -When the reference key is provided with a `ResourceIdentifier`, the sync will resolve the resource with the given key and use the ID of the found resource to create or update a reference. -Therefore, in order to resolve the actual ids of those references in the sync process, `ResourceIdentifier`s with their `key`s have to be supplied. - -|Reference Field|Type| -|:---|:---| -| `supplyChannel` | [ChannelResourceIdentifier](https://docs.commercetools.com/api/projects/channels#ctp:api:type:ChannelResourceIdentifier)| -| `custom.type` | [TypeResourceIdentifier](https://docs.commercetools.com/api/projects/types#ctp:api:type:TypeResourceIdentifier) | - -> Note that a reference without the key field will be considered as an existing resource on the target commercetools project and the library will issue an update/create an API request without reference resolution. - -##### Syncing from a commercetools project - -When syncing from a source commercetools project, you can use [`toInventoryEntryDrafts`](#todo) - method that transforms(resolves by querying and caching key-id pairs) and maps from a `InventoryEntry` to `InventoryEntryDraft` using cache in order to make them ready for reference resolution by the sync, for example: - -````java -// Build an ByProjectKeyInventoryGet for fetching inventories from a source CTP project without any references expanded for the sync: -final ByProjectKeyInventoryEntriesGet inventoryEntryQuery = client.inventory().get(); - -// Query all inventories (NOTE this is just for example, please adjust your logic) -final List categories = QueryUtils.queryAll(inventoryEntryQuery, - (inventories) -> inventories) - .thenApply(lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())) - .toCompletableFuture() - .join(); -```` - -In order to transform and map the `InventoryEntry` to `InventoryEntryDraft`, -Utils method `toInventoryEntryDrafts` requires `projectApiRoot`, implementation of [`ReferenceIdToKeyCache`](#todo) and `inventoryEntries` as parameters. -For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](#todo). -Example as shown below: - -````java -//Implement the cache using library class. -final ReferenceIdToKeyCache referenceIdToKeyCache = new CaffeineReferenceIdToKeyCacheImpl(); - -//For every reference fetch its key using id, cache it and map from InventoryEntry to InventoryEntryDraft. With help of the cache same reference keys can be reused. -CompletableFuture> inventoryEntryDrafts = InventoryTransformUtils.toInventoryEntryDrafts(client, referenceIdToKeyCache, inventoryEntries); -```` - -##### Syncing from an external resource - -- When syncing from an external resource, `ResourceIdentifier`s with their `key`s have to be supplied as following example: - -````java -final InventoryEntryDraft inventoryEntryDraft = InventoryEntryDraftBuilder - .of() - .sku("sku1") - .quantityOnStock(1L) - .custom(CustomFieldsDraftBuilder.of().type(typeResourceIdentifierBuilder -> typeResourceIdentifierBuilder.key("type-key")).fields(fieldContainerBuilder -> fieldContainerBuilder.values(emptyMap())).build())) // note that custom type provided with key - .supplyChannel(ChannelResourceIdentifierBuilder.of().key("channel-key").build()) // note that channel reference provided with key - .build(); -```` - -#### SyncOptions -After the `projectApiRoot` is set up, an `InventorySyncOptions` should be built as follows: -````java -// instantiating a InventorySyncOptions -final InventorySyncOptions inventorySyncOptions = InventorySyncOptionsBuilder.of(projectApiRoot).build(); -```` - -`SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. -Available configurations: - -##### errorCallback -A callback that is called whenever an error event occurs during the sync process. Each resource executes its own -error-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the error-event: - -* sync exception -* inventory entry draft from the source -* inventory entry of the target project (only provided if an existing inventory entry could be found) -* the update-actions, which failed (only provided if an existing inventory entry could be found) - -````java - final Logger logger = LoggerFactory.getLogger(InventorySync.class); - final InventorySyncOptions inventorySyncOptions = InventorySyncOptionsBuilder - .of(projectApiRoot) - .errorCallback((syncException, draft, inventoryEntry, updateActions) -> - logger.error(new SyncException("My customized message"), syncException)).build(); -```` - -##### warningCallback -A callback is called whenever a warning event occurs during the sync process. Each resource executes its own -warning-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the warning message: - -* sync exception -* inventory entry draft from the source -* inventory entry of the target project (only provided if an existing inventory entry could be found) - -````java - final Logger logger = LoggerFactory.getLogger(InventorySync.class); - final InventorySyncOptions inventorySyncOptions = InventorySyncOptionsBuilder - .of(projectApiRoot) - .warningCallback((syncException, draft, inventoryEntry) -> - logger.warn(new SyncException("My customized message"), syncException)).build(); -```` - -##### beforeUpdateCallback -During the sync process, if a target inventory entry and an inventory entry draft are matched, this callback can be used -to intercept the **_update_** request just before it is sent to the commercetools platform. This allows the user to modify -update actions array with custom actions or discard unwanted actions. The callback provides the following information : - - * inventory entry draft from the source - * inventory from the target project - * update actions that were calculated after comparing both - -````java -final TriFunction< - List, - InventoryEntryDraft, - InventoryEntry, - List> beforeUpdateInventoryCallback = - (updateActions, newInventoryEntryDraft, oldInventoryEntry) -> updateActions.stream() - .filter(updateAction -> !(updateAction instanceof InventoryEntryRemoveQuantityAction)) - .collect(Collectors.toList()); - -final InventorySyncOptions inventorySyncOptions = - InventorySyncOptionsBuilder.of(projectApiRoot).beforeUpdateCallback(beforeUpdateInventoryCallback).build(); -```` - -##### beforeCreateCallback -During the sync process, if an inventory entry draft should be created, this callback can be used to intercept the **_create_** request just before it is sent to the commercetools platform. It contains the following information : - - * inventory entry draft that should be created - -Please refer to [example in product sync document](PRODUCT_SYNC.md#example-set-publish-stage-if-category-references-of-given-product-draft-exists). - -##### batchSize -A number that could be used to set the batch size with which inventories are fetched and processed, -as inventories are obtained from the target project on the commercetools platform in batches for better performance. The algorithm accumulates up to `batchSize` resources from the input list, then fetches the corresponding inventories from the target project on the commecetools platform in a single request. Playing with this option can slightly improve or reduce processing speed. If it is not set, the default batch size is 150 for inventory sync. - -````java -final InventorySyncOptions inventorySyncOptions = - InventorySyncOptionsBuilder.of(projectApiRoot).batchSize(100).build(); -```` - -##### cacheSize -In the service classes of the commercetools-sync-java library, we have implemented an in-memory [LRU cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) to store a map used for the reference resolution of the library. -The cache reduces the reference resolution based calls to the commercetools API as the required fields of a resource will be fetched only one time. These cached fields then might be used by another resource referencing the already resolved resource instead of fetching from commercetools API. It turns out, having the in-memory LRU cache will improve the overall performance of the sync library and commercetools API. -which will improve the overall performance of the sync and commercetools API. - -Playing with this option can change the memory usage of the library. If it is not set, the default cache size is `10.000` for inventory sync. - -````java -final InventorySyncOptions inventorySyncOptions = - InventorySyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); -```` - - -##### ensureChannels -A flag to indicate whether the sync process should create a supply channel of the given key when it doesn't exist in a -target project yet. -- If `ensureChannels` is set to `false` this inventory won't be synced and the `errorCallback` will be triggered. -- If `ensureChannels` is set to `true` the sync will attempt to create the missing supply channel with the given key. -If it fails to create the supply channel, the inventory won't sync and `errorCallback` will be triggered. -- If not provided, it is set to `false` by default. - -````java -final InventorySyncOptions inventorySyncOptions = - InventorySyncOptionsBuilder.of(projectApiRoot).ensureChannels(true).build(); -```` - -### Running the sync -After all the aforementioned points in the previous section have been fulfilled, to run the sync: -````java -// instantiating an inventory sync -final InventorySync inventorySync = new InventorySync(inventorySyncOptions); - -// execute the sync on your list of inventories -CompletionStage syncStatisticsStage = inventorySync.sync(inventoryEntryDrafts); -```` -The result of completing the `syncStatisticsStage` in the previous code snippet contains a `InventorySyncStatistics` -which contains all the stats of the sync process; which includes a report message, the total number of updated, created, -failed, processed inventories and the processing time of the sync in different time units and in a -human-readable format. -````java -final InventorySyncStatistics stats = syncStatisticsStage.toCompletebleFuture().join(); -stats.getReportMessage(); -/*"Summary: 25 inventory entries were processed in total (9 created, 5 updated, 2 failed to sync)."*/ -```` - -__Note__ The statistics object contains the processing time of the last batch only. This is due to two reasons: - - 1. The sync processing time should not take into account the time between supplying batches to the sync. - 2. It is not known by the sync which batch is going to be the last one supplied. - - -More examples of how to use the sync [here](#todo). - -*Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* - - -### Build all update actions - -A utility method provided by the library to compare an InventoryEntry with a new InventoryEntryDraft and results in a list of InventoryEntry - update actions. -```java -List updateActions = InventorySyncUtils.buildActions(oldEntry, newEntry, inventorySyncOptions); -``` - -Examples of its usage can be found in the tests -[here](https://github.com/commercetools/commercetools-sync-java/tree/master/src/test/java/com/commercetools/sync/inventories/utils/InventorySyncUtilsTest.java). - -### Build particular update action(s) - -Utility methods provided by the library to compare the specific fields of an InventoryEntry and a new InventoryEntryDraft, and in turn builds - the update action. One example is the `buildChangeQuantityAction` which compares quantities: - -````java -Optional updateAction = buildChangeQuantityAction(oldEntry, newEntry); -```` - -## Migration Guide - -The inventory-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with -any HTTP client module. The default one is `commercetools-http-client`. - -```xml - - - LATEST - - - - - com.commercetools.sdk - commercetools-http-client - ${commercetools.version} - - - com.commercetools.sdk - commercetools-sdk-java-api - ${commercetools.version} - - - -``` - -### Client configuration and creation - -For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). - -### Signature of InventorySyncOptions - -As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `InventoryEntryDraft`, `InventoryEntry` and `InventoryEntryUpdateAction` from `package com.commercetools.api.models.inventory.*` - -> Note: Type `UpdateAction` has changed to `InventoryEntryUpdateAction`. Make sure you create and supply a specific InventoryEntryUpdateAction in `beforeUpdateCallback`. For that you can use the [library-utilities](#todo) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): - -```java -// Example: Create a inventory update action to change quantity taking the 'newQuantity' of the InventoryEntryDraft - final Function createBeforeUpdateAction = - (newQuantity) -> InventoryEntryChangeQuantityAction.builder().quantity(newQuantity).build(); - -// Add the change quantity action to the list of update actions before update is executed - final TriFunction< - List, InventoryEntryDraft, InventoryEntry, List> - beforeUpdateInventoryCallback = - (updateActions, newInventoryEntryDraft, oldInventoryEntry) -> { - final InventoryEntryUpdateAction beforeUpdateAction = - createBeforeUpdateAction.apply(newInventoryDraft.getQuantity()); - updateActions.add(beforeUpdateAction); - return updateActions; - }; -``` - -### Build InventoryEntryDraft (syncing from external project) - -The inventory-sync expects a list of `InventoryEntryDraft`s to process. If you use java-sync-library to sync your inventories from any external system into a commercetools platform project you have to convert your data into CTP compatible `InventoryEntryDraft` type. This was done in previous version using `DraftBuilder`s. -The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: - -```java -// InventoryEntryDraftBuilder in v1 takes parameters 'sku' and 'quantityOnStock' -final InventoryEntryDraft inventoryEntryDraft = - InventoryEntryDraftBuilder - .of("sku", 10L) - .restockableInDays(10) //Note: Field 'restockableInDays' is of type Integer - .build(); - -// InventoryEntryDraftBuilder in v2 -final InventoryEntryDraft inventoryEntryDraft = - InventoryEntryDraftBuilder - .of() - .sku("sku") - .quantityOnStock(10L) - .restockableInDays(10L) //Note: Field 'restockableInDays' is of type Long - .build(); -``` -For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). - -### Query for Inventories (syncing from CTP project) - -If you sync inventories between different commercetools projects you probably use [InventoryTransformUtils#toInventoryEntryDrafts](#todo) to transform `InventoryEntry` into `InventoryEntryDraft` which can be used by the inventory-sync. -However, if you need to query `Inventories` from a commercetools project instead of passing `InventoryEntryQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. -Here's an example: - -```java -// SDK v1: InventoryEntryQuery to fetch all inventories -final InventoryEntryQuery query = InventoryEntryQuery.of(); - -final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); - -// SDK v2: Create and execute query to fetch all inventories in one line -final InventoryEntryPagedQueryResponse result = apiRoot.inventory().get().executeBlocking().getBody(); -``` -[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. - -> Note: If you use predicates to query resources please keep in mind the URI length is limited to ~8kB. Therefore, consider limiting the query-predicates (max. 10.000 characters), because above this size it could return - Error 414 (Request-URI Too Large). - -### JVM-SDK-V2 migration guide - -On any other needs to migrate your project using jvm-sdk-v2 please refer to it's [Migration Guide](https://docs.commercetools.com/sdk/java-sdk-migrate). - diff --git a/docs/sdk2/usage/PRODUCT_SYNC.md b/docs/sdk2/usage/PRODUCT_SYNC.md deleted file mode 100644 index 79fc37b1ff..0000000000 --- a/docs/sdk2/usage/PRODUCT_SYNC.md +++ /dev/null @@ -1,578 +0,0 @@ -# Product Sync - -The module used for importing/syncing Products into a commercetools project. -It also provides utilities for generating update actions based on the comparison of a [ProductProjection](https://docs.commercetools.com/api/projects/productProjections#productprojection) -against a [ProductDraft](https://docs.commercetools.com/api/projects/products#productdraft). - - - - -- [Usage](#usage) - - [Prerequisites](#prerequisites) - - [ProjectApiRoot](#projectapiroot) - - [Required Fields](#required-fields) - - [Reference Resolution](#reference-resolution) - - [Syncing from a commercetools project](#syncing-from-a-commercetools-project) - - [Syncing from an external resource](#syncing-from-an-external-resource) - - [SyncOptions](#syncoptions) - - [errorCallback](#errorcallback) - - [warningCallback](#warningcallback) - - [beforeUpdateCallback](#beforeupdatecallback) - - [beforeCreateCallback](#beforecreatecallback) - - [batchSize](#batchsize) - - [cacheSize](#cachesize) - - [syncFilter](#syncfilter) - - [ensureChannels](#ensurechannels) - - [Running the sync](#running-the-sync) - - [Persistence of ProductDrafts with Irresolvable References](#persistence-of-productdrafts-with-irresolvable-references) - - [More examples of how to use the sync](#more-examples-of-how-to-use-the-sync) - - [Build all update actions](#build-all-update-actions) - - [Build particular update action(s)](#build-particular-update-actions) -- [Caveats](#caveats) -- [Migration Guide](#migration-guide) - - [Client configuration and creation](#client-configuration-and-creation) - - [Signature of ProductSyncOptions](#signature-of-productsyncoptions) - - [Build ProductDraft (syncing from external project)](#build-productdraft-syncing-from-external-project) - - [Query for Products (syncing from CTP project)](#query-for-products-syncing-from-ctp-project) - - [JVM-SDK-V2 migration guide](#jvm-sdk-v2-migration-guide) - - - -## Usage - -### Prerequisites - -#### ProjectApiRoot - -Use the [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/java-sdk-v2-product-sync-migration/src/main/java/com/commercetools/sync/sdk2/commons/utils/ClientConfigurationUtils.java) which apply the best practices for `ProjectApiRoot` creation. -To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](https://github.com/commercetools/commercetools-sdk-java-v2/blob/main/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/oauth2/ClientCredentialsBuilder.java) -If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). - -````java -final ClientCredentials clientCredentials = - new ClientCredentialsBuilder() - .withClientId("client-id") - .withClientSecret("client-secret") - .withScopes("scopes") - .build(); -final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); -```` - -#### Required Fields - -The following fields are **required** to be set in, otherwise, they won't be matched by sync: - -|Draft|Required Fields|Note| -|---|---|---| -| `ProductDraft` | `key` | Also, the products in the target project are expected to have the `key` fields set. | -| `ProductVariantDraft` | `key`, `sku` | Also, all the variants in the target project are expected to have the `key` and `sku` fields set. | - -#### Reference Resolution - -In commercetools, a reference can be created by providing the key instead of the ID with the type [ResourceIdentifier](https://docs.commercetools.com/api/types#resourceidentifier). -When the reference key is provided with a `ResourceIdentifier`, the sync will resolve the resource with the given key and use the ID of the found resource to create or update a reference. -Therefore, in order to resolve the actual ids of those references in the sync process, `ResourceIdentifier`s with their `key`s have to be supplied. - -|Reference Field|Type|Necessity| -|:---|:---|:---| -| `productType` | ProductTypeResourceIdentifier | **Required** | -| `categories` | List of CategoryResourceIdentifier | Optional | -| `taxCategory` | TaxCategoryResourceIdentifier | Optional | -| `state` | StateResourceIdentifier | Optional | -| `variants.prices.channel` | ChannelResourceIdentifier | Optional | -| `variants.prices.customerGroup` | CustomerGroupResourceIdentifier | Optional | -| `variants.prices.custom.type` | TypeResourceIdentifier | **Required** for `custom` (CustomFieldsDraft) | -| `variants.assets.custom.type` | TypeResourceIdentifier | **Required** for `custom` (CustomFieldsDraft) | -| `variants.attributes` | Only the attributes with type [ReferenceType](https://docs.commercetools.com/api/projects/productTypes#referencetype), [SetType](https://docs.commercetools.com/api/projects/productTypes#settype) with `elementType` as [ReferenceType](https://docs.commercetools.com/api/projects/productTypes#referencetype) and [NestedType](https://docs.commercetools.com/api/projects/productTypes#nestedtype) requires `key` on the `id` field of the `ReferenceType`. | Optional | - -> Note that a reference without the key field will be considered as existing -resource on the target commercetools project and the library will issue an update/create an API request without reference resolution. - -##### Syncing from a commercetools project - -When syncing from a source commercetools project, you can use [`toProductDrafts`](https://github.com/commercetools/commercetools-sync-java/blob/java-sdk-v2-product-sync-migration/src/main/java/com/commercetools/sync/sdk2/products/utils/ProductTransformUtils.java#L59) - method that transforms(resolves by querying and caching key-id pairs) and maps from a `ProductProjection` to `ProductDraft` using cache in order to make them ready for reference resolution by the sync, for example: - -````java -// Build a ProductQuery for fetching products from a source CTP project without any references expanded for the sync: -final ByProjectKeyProductProjectionsGet byProjectKeyProductsGet = getCtpClient().productProjections().get().addStaged(true); - -// Query all product projections (NOTE this is only for example, please adjust your logic) -final List products = QueryUtils.queryAll(byProjectKeyProductsGet, - (productProjections) -> productProjections) - .thenApply(lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())) - .toCompletableFuture() - .join(); -```` - -In order to transform and map the `ProductProjections` to `ProductDraft`, -Utils method `toProductDrafts` requires `ProjectApiRoot`, implementation of [`ReferenceIdToKeyCache`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ReferenceIdToKeyCache.java) and list of `ProductProjection` as parameters. -For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/CaffeineReferenceIdToKeyCacheImpl.java). -Example as shown below: - -````java -//Implement the cache using library class. -final ReferenceIdToKeyCache referenceIdToKeyCache = new CaffeineReferenceIdToKeyCacheImpl(); - -//For every reference fetch its key using id, cache it and map from ProductProjection to ProductDraft. With help of the cache same reference keys can be reused. -CompletableFuture> productDrafts = ProductTransformUtils.toProductDrafts(client, referenceIdToKeyCache, products); -```` -##### Syncing from an external resource - -- When syncing from an external resource, `ResourceIdentifier`s with their `key`s have to be supplied as following example: - -```` java -final ProductDraft productDraft = - ProductDraftBuilder - .of() - .productType(ProductTypeResourceIdentifierBuilder.of().key("product-type-key").build()) - .name(LocalizedString.ofEnglish("name")) - .slug(LocalizedString.ofEnglish("slug")) - .masterVariant(masterVariant) - .key("product-key") - .categories(CategoryResourceIdentifierBuilder.of().key("category1-key").build(), - CategoryResourceIdentifierBuilder.of().key("category2-key").build()) - .taxCategory(TaxCategoryResourceIdentifierBuilder.of().key("tax-category-key").build()) - .state(StateResourceIdentifierBuilder.of().key("tax-category-key").build()) - .build(); -```` - - ````java -final PriceDraft priceDraft = - PriceDraftBuilder.of() - .value(MoneyBuilder.of().centAmount(20L).currencyCode("EUR").build()) - .channel(ChannelResourceIdentifierBuilder.of().key("channel-key").build()) - .customerGroup( - CustomerGroupResourceIdentifierBuilder.of().key("customer-group-key").build()) - .custom( - CustomFieldsDraftBuilder.of() - .type(TypeResourceIdentifierBuilder.of().key("type-key").build()) - .fields(FieldContainerBuilder.of().values(Collections.emptyMap()).build()).build()) - .build(); -```` - -- The product projection variant attributes with a type `ReferenceType` do not support the `ResourceIdentifier` yet, for - those references you have to provide the `key` value on the `id` field of the reference. This means that calling `getId()` on the reference should return its `key`. - -````java -final ProductReference productReference = ProductReferenceBuilder.of().id("product-key").build(); -final Attribute attr = AttributeBuilder.of().name("attribute-name").value(productReference).build(); - -```` - -- For resolving `key-value-document` (custom object) references on attributes of type `Reference`, `Set` of `Reference`, `NestedType` or `Set` of `NestedType`, The `id` field of the reference in the attribute should be defined in the correct format. -The correct format must have a vertical bar `|` character between the values of the container and key. -For example, if the custom object has a container value `container` and key value `key`, the `id` field should be `container|key`, -also, the key and container value should match the pattern `[-_~.a-zA-Z0-9]+`. Please also keep in mind that length of the key is limited to 256 characters max: [CustomObject](https://docs.commercetools.com/api/projects/custom-objects#customobject) - -````java -final CustomObjectReference coReference = - CustomObjectReferenceBuilder.of().id("co-container|co-key").build(); -final Attribute attr = - AttributeBuilder.of().name("attribute-name").value(coReference).build(); -```` - -#### SyncOptions - -After the `ProjectApiRoot` is set up, a `ProductSyncOptions` should be built as follows: - -````java -// instantiating a ProductSyncOptions -final ProductSyncOptions productSyncOptions = ProductSyncOptionsBuilder.of(projectApiRoot).build(); -```` - -`SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. -Available configurations: - -##### errorCallback -A callback that is called whenever an error event occurs during the sync process. Each resource executes its own -error-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the error-event: - -* sync exception -* product draft from the source -* product projection of the target project (only provided if an existing product projection could be found) -* the update-actions, which failed (only provided if an existing product projection could be found) - -````java - final Logger logger = LoggerFactory.getLogger(ProductSync.class); - final ProductSyncOptions productSyncOptions = ProductSyncOptionsBuilder - .of(projectApiRoot) - .errorCallback((syncException, draft, productProjection, updateActions) -> - logger.error(new SyncException("My customized message"), syncException)).build(); -```` - -##### warningCallback -A callback is called whenever a warning event occurs during the sync process. Each resource executes its own -warning-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the warning message: - -* sync exception -* product draft from the source -* product projection of the target project (only provided if an existing product projection could be found) - -````java - final Logger logger = LoggerFactory.getLogger(ProductSync.class); - final ProductSyncOptions productSyncOptions = ProductSyncOptionsBuilder - .of(projectApiRoot) - .warningCallback((syncException, draft, productProjection) -> - logger.warn(new SyncException("My customized message"), syncException)).build(); -```` - -##### beforeUpdateCallback -During the sync process, if a target product projection and a product draft are matched, this callback can be used to -intercept the **_update_** request just before it is sent to the commercetools platform. This allows the user to modify the update -actions array with custom actions or discard unwanted actions. The callback provides the following information : - - * product draft from the source - * product projection from the target project - * update actions that were calculated after comparing both - -````java -// Example: Ignore update actions which contain deletion of variants -final TriFunction< - List, ProductDraft, ProductProjection, List> beforeUpdateProductCallback = - (updateActions, newProductDraft, oldProduct) -> updateActions.stream() - .filter(updateAction -> !(updateAction instanceof ProductRemoveVariantActionImpl)) - .collect(Collectors.toList()); - -final ProductSyncOptions productSyncOptions = - ProductSyncOptionsBuilder.of(projectApiRoot).beforeUpdateCallback(beforeUpdateProductCallback).build(); -```` - -##### beforeCreateCallback -During the sync process, if a product draft should be created, this callback can be used to intercept the **_create_** request just before it is sent to the commercetools platform. It contains the following information : - - * product draft that should be created - -````java -// Example: Set publish stage if category references of given product draft exist -final Function beforeCreateProductCallback = - (callbackDraft) -> { - List categoryResourceIdentifier = callbackDraft.getCategories(); - if (categoryResourceIdentifier!=null && !categoryResourceIdentifier.isEmpty()) { - return ProductDraftBuilder.of(callbackDraft).publish(true).build(); - } - return callbackDraft; - }; - -final ProductSyncOptions productSyncOptions = - ProductSyncOptionsBuilder.of(projectApiRoot).beforeCreateCallback(beforeCreateProductCallback).build(); -```` - -##### batchSize -A number that could be used to set the batch size with which product projections are fetched and processed, -as product projections are obtained from the target project on commercetools platform in batches for better performance. - The algorithm accumulates up to `batchSize` resources from the input list, then fetches the corresponding product -projections from the target project on the commercetools platform in a single request. Playing with this option can -slightly improve or reduce processing speed. If it is not set, the default batch size is 30 for product sync. - -````java -final ProductSyncOptions productSyncOptions = - ProductSyncOptionsBuilder.of(projectApiRoot).batchSize(50).build(); -```` - -##### cacheSize -In the service classes of the commercetools-sync-java library, we have implemented an in-memory [LRU cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) to store a map used for the reference resolution of the library. -The cache reduces the reference resolution based calls to the commercetools API as the required fields of a resource will be fetched only one time. These cached fields then might be used by another resource referencing the already resolved resource instead of fetching from commercetools API. It turns out, having the in-memory LRU cache will improve the overall performance of the sync library and commercetools API. -which will improve the overall performance of the sync and commercetools API. - -Playing with this option can change the memory usage of the library. If it is not set, the default cache size is `10.000` for product sync. - -````java -final ProductSyncOptions productSyncOptions = - ProductSyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); -```` - -##### syncFilter -It represents either a blacklist or a whitelist for filtering certain update action groups. - - - __Blacklisting__ an update action group means that everything in products will be synced except for any group in - the blacklist. A typical use case is to blacklist prices when syncing product projections. In other words, syncing - everything in product projections except for prices. - - ````java - final ProductSyncOptions syncOptions = syncOptionsBuilder.syncFilter(ofBlackList(ActionGroup.PRICES)).build(); - ```` - - - __Whitelisting__ an update action group means that the groups in this whitelist will be the *only* group synced in products. One use case could be to whitelist prices when syncing products. In other words, syncing prices only in - product projections and nothing else. - - ````java - final ProductSyncOptions syncOptions = syncOptionsBuilder.syncFilter(ofWhiteList(ActionGroup.PRICES)).build(); - ```` - - - The list of action groups allowed to be blacklisted or whitelisted on product projections can be found [here](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/products/ActionGroup.java). - -##### ensureChannels -A flag to indicate whether the sync process should create a price channel of the given key when it doesn't exist in a -target project yet. -- If `ensureChannels` is set to `false` this products won't be synced and the `errorCallback` will be triggered. -- If `ensureChannels` is set to `true` the sync will attempt to create the missing channel with the given key. -If it fails to create the price channel, the products won't sync and `errorCallback` will be triggered. -- If not provided, it is set to `false` by default. - -````java -final ProductSyncOptions productSyncOptions = - ProductSyncOptionsBuilder.of(projectApiRoot).ensureChannels(true).build(); -```` - -### Running the sync -After all the aforementioned points in the previous section have been fulfilled, to run the sync: -````java -// instantiating a product sync -final ProductSync productSync = new ProductSync(productSyncOptions); - -// execute the sync on your list of products -CompletionStage syncStatisticsStage = productSync.sync(productDrafts); -```` -The result of completing the `syncStatisticsStage` in the previous code snippet contains a `ProductSyncStatistics` -which contains all the stats of the sync process; which includes a report message, the total number of updated, created, -failed, processed products and the processing time of the sync in different time units and in a -human-readable format. -````java -final ProductSyncStatistics stats = syncStatisticsStage.toCompletableFuture().join(); -stats.getReportMessage(); -/*Summary: 2000 product(s) were processed in total (1000 created, 995 updated, 5 failed to sync and 0 product(s) with missing reference(s)).*/ -```` - -__Note__ The statistics object contains the processing time of the last batch only. This is due to two reasons: - - 1. The sync processing time should not take into account the time between supplying batches to the sync. - 2. It is not known by the sync which batch is going to be the last one supplied. - -##### Persistence of ProductDrafts with Irresolvable References - -A productDraft X could be supplied in with an attribute referencing productDraft Y. -It could be that Y is not supplied before X, which means the sync could fail to create/update X. -It could also be that Y is not supplied at all in this batch but at a later batch. - -The library keeps track of such "referencing" drafts like X and persists them in storage -(**Commercetools platform `customObjects` in the target project** , in this case) -to keep them and create/update them accordingly whenever the referenced drafts exist in the target project. - -The `customObject` will have a `container:` **`"commercetools-sync-java.UnresolvedReferencesService.productDrafts"`** -and a `key` representing the key of the productDraft that is waiting to be created/updated. - - -Here is an example of a `CustomObject` in the target project that represents a productDraft with `productKey1`. -It being persisted as `CustomObject` means that the referenced productDrafts with keys `foo` and `bar` do not exist yet. - -```json -{ - "id": "d0fbb69e-76e7-4ec0-893e-3aaab6f4f6b6", - "version": 1, - "container": "commercetools-sync-java.UnresolvedReferencesService.productDrafts", - "key": "productKey1", - "value": { - "dependantProductKeys": [ - "foo", - "bar" - ], - "productDraft": { - "productType": { - "typeId": "product-type", - "id": "main-product-type" - }, - "masterVariant": { - "id": 1, - "sku": "white-shirt-1", - "key": "white-shirt-1", - "prices": [], - "images": [], - "attributes": [ - { - "name": "product-reference-set", - "value": [ - { - "typeId": "product", - "id": "foo" - }, - { - "typeId": "product", - "id": "bar" - } - ] - } - ] - }, - "key": "productKey1" - } - }, - "createdAt": "2019-09-27T13:45:35.495Z", - "lastModifiedAt": "2019-09-27T13:45:35.495Z", - "lastModifiedBy": { - "clientId": "8bV3XSW-taCpi873-GQTa8lf", - "isPlatformClient": false - }, - "createdBy": { - "clientId": "8bV3XSW-taCpi873-GQTa8lf", - "isPlatformClient": false - } -} -``` - -As soon, as the referenced productDrafts are supplied to the sync, the draft will be created/updated and the -`CustomObject` will be removed from the target project. - -Keeping the old custom objects around forever can negatively influence the performance of your project and the time it takes to restore it from a backup. Deleting unused data ensures the best performance for your project. Please have a look into the [Cleanup guide](CLEANUP_GUIDE.md) to cleanup old unresolved custom objects. - -##### More examples of how to use the sync - -1. [Sync from another commercetools project as a source](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/ctpprojectsource/products/ProductSyncIT.java). -2. [Sync from an external source](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/externalsource/products/ProductSyncIT.java). -3. [Sync with blacklisting/whitelisting](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/externalsource/products/ProductSyncFilterIT.java). - -*Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* - -### Build all update actions - -A utility method provided by the library to compare a ProductProjection with a new ProductDraft and results in a - list of update actions. -```java -List updateActions = ProductSyncUtils.buildActions(productProjection, productDraft, productSyncOptions, attributesMetaData); -``` - -Examples of its usage can be found in the tests -[here](https://github.com/commercetools/commercetools-sync-java/blob/java-sdk-v2-product-sync-migration/src/test/java/com/commercetools/sync/sdk2/products/utils/ProductSyncUtilsTest.java). - -### Build particular update action(s) - -Utility methods provided by the library to compare the specific fields of a ProductProjection and a new ProductDraft, - build the update action. One example is the `buildChangeNameUpdateAction` which compares names: - -````java -Optional updateAction = buildChangeNameUpdateAction(oldProductProjection, productDraft); -```` -More examples of those utils for different fields can be found [here](https://github.com/commercetools/commercetools-sync-java/tree/master/src/test/java/com/commercetools/sync/products/utils). - -## Caveats - -The commercetools-java-sync library has some exceptions to the data it can sync, particularly around product variant -attributes. - -1. List of supported variant attributes, with an `AttributeType`: `ReferenceType`, - that can be synced: - - | `referenceTypeId` | supported | - |---|---| - | `“cart”` | ❌ | - | `“category”` | ✅ | - | `“channel”` | ❌ | - | `“customer”` | ✅ | - | `“key-value-document”` | ✅ | - | `“order”` | ❌ | - | `“product”` | ✅ | - | `“product-type”` | ✅ | - | `“review”` | ❌ | - | `“state”` | ✅ | - | `“shipping-method”` | ❌ | - | `“zone”` | ❌ | - -2. Support for syncing variant attributes with an `AttributeType` of `SetType` of `ReferenceType` -(of `elementType: ReferenceType`) with any of the aforementioned `referenceTypeId`, accordingly applies. -3. Support for syncing variant attributes with an `AttributeType` of `NestedType` which has an attribute inside of it of -`ReferenceType` with any of the aforementioned `referenceTypeId`, accordingly applies. -4. Syncing products with cyclic dependencies are not supported yet. An example of a cyclic dependency is a product `a` which references a product `b` and at the same time product `b` references product `a`. Cycles can contain more than 2 products. For example: `a` -> `b` -> `c` -> `a`. If there are such cycles, the sync will consider all the products in the cycle as products with missing parents. They will be persisted as custom objects in the target project. - -## Migration Guide - -The product-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with -any HTTP client module. The default one is `commercetools-http-client`. - -```xml - - - LATEST - - - - - com.commercetools.sdk - commercetools-http-client - ${commercetools.version} - - - com.commercetools.sdk - commercetools-sdk-java-api - ${commercetools.version} - - - -``` - -### Client configuration and creation - -For client creation use [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/java-sdk-v2-product-sync-migration/src/main/java/com/commercetools/sync/sdk2/commons/utils/ClientConfigurationUtils.java) which apply the best practices for `ProjectApiRoot` creation. -If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). - -### Signature of ProductSyncOptions - -As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `ProductDraft`, `ProductProjection` and `ProductUpdateAction` from `package com.commercetools.api.models.product.*` - -> Note: Type `UpdateAction` has changed to `ProductUpdateAction`. Make sure you create and supply a specific ProductUpdateAction in `beforeUpdateCallback`. Therefore you can use the [library-utilities](https://github.com/commercetools/commercetools-sync-java/blob/java-sdk-v2-product-sync-migration/src/main/java/com/commercetools/sync/sdk2/products/utils/ProductUpdateActionUtils.java) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): - -```java -// Example: Create a product update action to change name taking the 'newName' of the productDraft - final Function createBeforeUpdateAction = - (newName) -> ProductChangeNameAction.builder().name(newName).staged(true).build(); - -// Add the change name action to the list of update actions before update is executed - final TriFunction< - List, ProductDraft, ProductProjection, List> - beforeUpdateProductCallback = - (updateActions, newProductDraft, oldProduct) -> { - final ProductUpdateAction beforeUpdateAction = - createBeforeUpdateAction.apply(newProductDraft.getName()); - updateActions.add(beforeUpdateAction); - return updateActions; - }; -``` - -### Build ProductDraft (syncing from external project) - -The product-sync expects a list of `ProductDraft`s to process. If you use java-sync-library to sync your products from any external system into a commercetools platform project you have to convert your data into CTP compatible `ProductDraft` type. This was done in previous version using `DraftBuilder`s. -The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: - -```java -// ProductDraftBuilder in v1 takes parameters 'productType', 'name', 'slug' and optional 'masterVariant' -final ProductDraft productDraft = - ProductDraftBuilder - .of(mock(ProductType.class), ofEnglish("name"), ofEnglish("slug"), emptyList()) - .key("product-key") - .build(); - -// ProductDraftBuilder in v2 -final ProductDraft productDraft = - ProductDraftBuilder - .of() - .productType(ProductTypeResourceIdentifierBuilder.of().key("product-type-key").build()) - .name(LocalizedString.ofEnglish("name")) - .slug(LocalizedString.ofEnglish("slug")) - .masterVariant(masterVariant) - .key("product-key") - .build(); -``` -For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). - -### Query for Products (syncing from CTP project) - -If you sync products between different commercetools projects you probably use [ProductTransformUtils#toProductDrafts](https://github.com/commercetools/commercetools-sync-java/blob/java-sdk-v2-product-sync-migration/src/main/java/com/commercetools/sync/sdk2/products/utils/ProductTransformUtils.java#L59) to transform `ProductProjection` into `ProductDraft` which can be used by the product-sync. -However, if you need to query `Products` / `ProductProjections` from a commercetools project instead of passing `ProductQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. -Here's an example: - -```java -// SDK v1: ProductProjectionQuery to fetch all staged product projections -final ProductProjectionQuery query = ProductProjectionQuery.ofStaged(); - -final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); - -// SDK v2: Create and execute query to fetch all staged product projections in one line -final ProductProjectionPagedQueryResponse result = apiRoot.productProjections().get().addStaged(true).executeBlocking().getBody(); -``` -[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. - -### JVM-SDK-V2 migration guide - -On any other needs to migrate your project using jvm-sdk-v2 please refer to it's [Migration Guide](https://docs.commercetools.com/sdk/java-sdk-migrate). \ No newline at end of file diff --git a/docs/sdk2/usage/PRODUCT_TYPE_SYNC.md b/docs/sdk2/usage/PRODUCT_TYPE_SYNC.md deleted file mode 100644 index ca132b6873..0000000000 --- a/docs/sdk2/usage/PRODUCT_TYPE_SYNC.md +++ /dev/null @@ -1,392 +0,0 @@ -# ProductType Sync - -The module used for importing/syncing ProductTypes into a commercetools project. -It also provides utilities for generating update actions based on the comparison of a [ProductType](https://docs.commercetools.com/api/projects/productTypes#producttype) -against a [ProductTypeDraft](https://docs.commercetools.com/api/projects/productTypes#ctp:api:type:ProductTypeDraft). - - - - -- [Usage](#usage) - - [Prerequisites](#prerequisites) - - [ProjectApiRoot](#projectapiroot) - - [Required Fields](#required-fields) - - [Reference Resolution](#reference-resolution) - - [Syncing from a commercetools project](#syncing-from-a-commercetools-project) - - [Syncing from an external resource](#syncing-from-an-external-resource) - - [SyncOptions](#syncoptions) - - [errorCallback](#errorcallback) - - [warningCallback](#warningcallback) - - [beforeUpdateCallback](#beforeupdatecallback) - - [beforeCreateCallback](#beforecreatecallback) - - [batchSize](#batchsize) - - [cacheSize](#cachesize) - - [Running the sync](#running-the-sync) - - [Important to Note](#important-to-note) - - [More examples of how to use the sync](#more-examples-of-how-to-use-the-sync) - - [Build all update actions](#build-all-update-actions) - - [Build particular update action(s)](#build-particular-update-actions) -- [Caveats](#caveats) -- [Migration Guide](#migration-guide) - - [Client configuration and creation](#client-configuration-and-creation) - - [Signature of ProductTypeSyncOptions](#signature-of-producttypesyncoptions) - - [Build ProductTypeDraft (syncing from external project)](#build-producttypedraft-syncing-from-external-project) - - [Query for ProductTypes (syncing from CTP project)](#query-for-producttypes-syncing-from-ctp-project) - - [JVM-SDK-V2 migration guide](#jvm-sdk-v2-migration-guide) - - - -## Usage - -### Prerequisites -#### ProjectApiRoot - -Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -To create the required `ClientCredentials` for client creation, please utilize the `ClientCredentialsBuilder` provided in the java-sdk-v2 [Client OAUTH2 package](#todo). -If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). - -````java -final ClientCredentials clientCredentials = - new ClientCredentialsBuilder() - .withClientId("client-id") - .withClientSecret("client-secret") - .withScopes("scopes") - .build(); -final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); -```` -#### Required Fields - -The following fields are **required** to be set in, otherwise, they won't be matched by sync: - -|Draft|Required Fields|Note| -|---|---|---| -| [ProductTypeDraft](https://docs.commercetools.com/api/projects/productTypes#ctp:api:type:ProductTypeDraft) | `key` | Also, the product types in the target project are expected to have the `key` fields set. | - -#### Reference Resolution - -In commercetools, a reference can be created by providing the key instead of the ID with the type [ResourceIdentifier](https://docs.commercetools.com/api/types#resourceidentifier). -When the reference key is provided with a `ResourceIdentifier`, the sync will resolve the resource with the given key and use the ID of the found resource to create or update a reference. -Therefore, in order to resolve the actual ids of those references in the sync process, `ResourceIdentifier`s with their `key`s have to be supplied. - -|Reference Field|Type| -|:---|:---| -| `attributes` | Only the attributes with type [AttributeNestedType](https://docs.commercetools.com/api/projects/productTypes#attributenestedtype) and [AttributeSetType](https://docs.commercetools.com/api/projects/productTypes#attributesettype) with `elementType` as `AttributeNestedType` requires `key` on the `id` field of the [ProductTypeReference](https://docs.commercetools.com/api/projects/productTypes#ctp:api:type:ProductTypeReference). | - -> Note that a reference without the key field will be considered as an existing resource on the target commercetools project and the library will issue an update/create an API request without reference resolution. - -##### Syncing from a commercetools project - -When syncing from a source commercetools project, you can use [`toProductTypeDrafts`](#todo) - method that transforms(resolves by querying and caching key-id pairs) and maps from a `ProductType` to `ProductTypeDraft`. It can be configured to use a cache that will speed up the reference resolution performed during the sync, for example: - -````java -// Build ByProjectKeyProductTypesGet for fetching product-types from a source CTP project without any references expanded for the sync: -final ByProjectKeyProductTypesGet byProjectKeyProductTypesGet = client.productTypes().get(); - -// Query all product-types (NOTE this is just for example, please adjust your logic) -final List productTypes = QueryUtils.queryAll(byProjectKeyProductTypesGet, - (productTypes) -> productTypes) - .thenApply(lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())) - .toCompletableFuture() - .join(); -```` - -In order to transform and map the `ProductType` to `ProductTypeDraft`, -Utils method `toProductTypeDrafts` requires `projectApiRoot`, implementation of [`ReferenceIdToKeyCache`](#todo) and a list of `productTypes` as parameters. -For cache implementation, you have two options: you can either use your own cache implementation or utilize the class [`CaffeineReferenceIdToKeyCacheImpl`](#todo) provided in the library. This class implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy.Example as shown below: - -````java -//Implement the cache using library class. -final ReferenceIdToKeyCache referenceIdToKeyCache = new CaffeineReferenceIdToKeyCacheImpl(); - -//For every reference fetch its key using id, cache it and map from ProductType to ProductTypeDraft. With help of the cache same reference keys can be reused. -CompletableFuture> productTypeDrafts = ProductTransformUtils.toProductTypeDrafts(client, referenceIdToKeyCache, productTypes); -```` - -##### Syncing from an external resource - -- Attributes with type `AttributeNestedType` do not support the `ResourceIdentifier` yet, -for those references you have to provide the `key` value on the `id` field of the reference. This means that calling `getId()` on the reference should return its `key`. - -````java -final AttributeDefinitionDraft nestedTypeAttr = AttributeDefinitionDraftBuilder.of() - .type(AttributeNestedTypeBuilder.of() - .typeReference(ProductTypeReferenceBuilder.of().id("product-type-key").build()) // note that key is provided in the id field of reference - .build()) - .name("attrNestedType") - .label(LocalizedString.ofEnglish("attrNestedType")) - .isRequired(true) - .build(); - -final AttributeDefinitionDraft setOfNestedTypeAttr = AttributeDefinitionDraftBuilder.of() - .type(AttributeSetTypeBuilder.of() - .elementType(AttributeNestedTypeBuilder.of() - .typeReference(ProductTypeReferenceBuilder.of() - .id("product-type-key").build()) - .build()) - .build()) - .name("attrNestedType") - .label(LocalizedString.ofEnglish("attrNestedType")) - .isRequired(true) - .build(); - -final ProductTypeDraft productTypeDraft = - ProductTypeDraftBuilder.of() - .name("foo") - .description("description") - .key("key") - .attributes(nestedTypeAttr, setOfNestedTypeAttr) - .build(); -```` - -#### SyncOptions - -After the `projectApiRoot` is setup, a `ProductTypeSyncOptions` should be built as follows: -````java -// instantiating a ProductTypeSyncOptions -final ProductTypeSyncOptions productTypeSyncOptions = ProductTypeSyncOptionsBuilder.of(projectApiRoot).build(); -```` - -`SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. -Available configurations: - -##### errorCallback -A callback that is called whenever an error event occurs during the sync process. Each resource executes its own -error-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the error-event: - -* sync exception -* product type draft from the source -* product type of the target project (only provided if an existing product type could be found) -* the update-actions, which failed (only provided if an existing product type could be found) - -````java - final Logger logger = LoggerFactory.getLogger(ProductTypeSync.class); - final ProductTypeSyncOptions productTypeSyncOptions = ProductTypeSyncOptionsBuilder - .of(projectApiRoot) - .errorCallback((syncException, draft, productType, updateActions) -> - logger.error(new SyncException("My customized message"), syncException)).build(); -```` - -##### warningCallback -A callback is called whenever a warning event occurs during the sync process. Each resource executes its own -warning-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the warning message: - -* sync exception -* product type draft from the source -* product type of the target project (only provided if an existing product type could be found) - -````java - final Logger logger = LoggerFactory.getLogger(ProductTypeSync.class); - final ProductTypeSyncOptions productTypeSyncOptions = ProductTypeSyncOptionsBuilder - .of(projectApiRoot) - .warningCallback((syncException, draft, productType) -> - logger.warn(new SyncException("My customized message"), syncException)).build(); -```` - -##### beforeUpdateCallback -During the sync process, if a target product type and a product type draft are matched, this callback can be used to -intercept the **_update_** request just before it is sent to the commercetools platform. This allows the user to modify -update actions array with custom actions or discard unwanted actions. The callback provides the following information : - - * product type draft from the source - * product type from the target project - * update actions that were calculated after comparing both - -````java -final TriFunction< - List, ProductTypeDraft, ProductType, List> - beforeUpdateProductTypeCallback = - (updateActions, newProductTypeDraft, oldProductType) -> updateActions.stream() - .filter(updateAction -> !(updateAction instanceof ProductTypeRemoveAttributeDefinitionAction)) - .collect(Collectors.toList()); - -final ProductTypeSyncOptions productTypeSyncOptions = - ProductTypeSyncOptionsBuilder.of(projectApiRoot).beforeUpdateCallback(beforeUpdateProductTypeCallback).build(); -```` - -##### beforeCreateCallback -During the sync process, if a product type draft should be created, this callback can be used to intercept the **_create_** request just before it is sent to the commercetools platform. It contains the following information : - - * product type draft that should be created - -Please refer to [example in product sync document](PRODUCT_SYNC.md#beforeCreateCallback). - -##### batchSize -A number that could be used to set the batch size with which product types are fetched and processed, -as product types are obtained from the target project on the commercetools platform in batches for better performance. The algorithm accumulates up to `batchSize` resources from the input list, then fetches the corresponding product types from the target project on the commecetools platform in a single request. Playing with this option can slightly improve or reduce processing speed. If it is not set, the default batch size is `50` for product type sync. - -````java -final ProductTypeSyncOptions productTypeSyncOptions = - ProductTypeSyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); -```` - -##### cacheSize -In the service classes of the commercetools-sync-java library, we have implemented an in-memory [LRU cache](#todo) to store a map used for the reference resolution of the library. -The cache reduces the reference resolution based calls to the commercetools API as the required fields of a resource will be fetched only one time. These cached fields then might be used by another resource referencing the already resolved resource instead of fetching from commercetools API. It turns out, having the in-memory LRU cache will improve the overall performance of the sync library and commercetools API. -which will improve the overall performance of the sync and commercetools API. - -Playing with this option can change the memory usage of the library. If it is not set, the default cache size is `10.000` for product type sync. - -````java -final ProductTypeSyncOptions productTypeSyncOptions = - ProductTypeSyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); -```` - -### Running the sync -After all the aforementioned points in the previous section have been fulfilled, to run the sync: -````java -// instantiating a product type sync -final ProductTypeSync productTypeSync = new ProductTypeSync(productTypeSyncOptions); - -// execute the sync on your list of product types -CompletionStage syncStatisticsStage = productTypeSync.sync(productTypeDrafts); -```` -The result of completing the `syncStatisticsStage` in the previous code snippet contains a `ProductTypeSyncStatistics` -which contains all the stats of the sync process; which includes a report message, the total number of updated, created, -failed, processed product types and the processing time of the last sync batch in different time units and in a -human-readable format. - -````java -final ProductTypeSyncStatistics stats = syncStatisticsStage.toCompletebleFuture().join(); -stats.getReportMessage(); -/*"Summary: 2000 products types were processed in total (1000 created, 995 updated, 5 failed to sync)."*/ -```` - -__Note__ The statistics object contains the processing time of the last batch only. This is due to two reasons: - - 1. The sync processing time should not take into account the time between supplying batches to the sync. - 2. It is not known by the sync which batch is going to be the last one supplied. - -#### Important to Note - -1. If two matching `attributeDefinition`s (old and new) on the matching `productType`s (old and new) have a different `AttributeType`, the sync will -**remove** the existing `attributeDefinition` and then **add** a new `attributeDefinition` with the new `AttributeType`. - -2. The `attributeDefinition` for which the `AttributeType` is not defined (`null`) will not be synced. - -#### More examples of how to use the sync - - 1. [Sync from another CTP project as a source](#todo). - 2. [Sync from an external source](#todo). - -*Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* - -### Build all update actions - -A utility method provided by the library to compare a ProductType with a new ProductTypeDraft and results in a list of product type update actions. -```java -List updateActions = ProductTypeSyncUtils.buildActions(productType, productTypeDraft, productTypeSyncOptions); -``` - -### Build particular update action(s) - -Utility methods provided by the library to compare the specific fields of a ProductType and a new ProductTypeDraft, and in turn, build - the update action. One example is the `buildChangeNameUpdateAction` which compares names: -````java -Optional updateAction = ProductTypeUpdateActionUtils.buildChangeNameAction(oldProductType, productTypeDraft); -```` -More examples of those utils for different fields can be found [here](#todo). - - -## Caveats -1. The order of attribute definitions in the synced product types is not guaranteed. -2. Changing the attribute definition type is not supported. Instead, remove and re-add it with a new type manually, either over API or merchant center. For more information please [check](#todo). - - -## Migration Guide - -The producttype-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with -any HTTP client module. The default one is `commercetools-http-client`. - -```xml - - - LATEST - - - - - com.commercetools.sdk - commercetools-http-client - ${commercetools.version} - - - com.commercetools.sdk - commercetools-sdk-java-api - ${commercetools.version} - - -``` - -### Client configuration and creation - -For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). - -### Signature of ProductTypeSyncOptions - -As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `ProductTypeDraft`, `ProductType` and `ProductTypeUpdateAction` from `package com.commercetools.api.models.product_type.*` - -> Note: Type `UpdateAction` has changed to `ProductTypeUpdateAction`. Make sure you create and supply a specific ProductTypeUpdateAction in `beforeUpdateCallback`. For that you can use the [library-utilities](#todo) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): - -```java -// Example: Create a producttype update action to change name taking the 'newName' of the productTypeDraft - final Function createBeforeUpdateAction = - (newName) -> ProductTypeChangeNameAction.builder().name(newName).build(); - -// Add the change name action to the list of update actions before update is executed - final TriFunction< - List, ProductTypeDraft, ProductType, List> - beforeUpdateProductTypeCallback = - (updateActions, newProductTypeDraft, oldProductType) -> { - final ProductTypeUpdateAction beforeUpdateAction = - createBeforeUpdateAction.apply(newProductTypeDraft.getName()); - updateActions.add(beforeUpdateAction); - return updateActions; - }; -``` - -### Build ProductTypeDraft (syncing from external project) - -The producttype-sync expects a list of `ProductTypeDraft`s to process. If you use java-sync-library to sync your producttypes from any external system into a commercetools platform project you have to convert your data into CTP compatible `ProductTypeDraft` type. This was done in previous version using `DraftBuilder`s. -The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: - -```java -// SDK v1: ProductTypeDraftBuilder.of takes parameters 'key', 'name', 'description' and list of 'attributes' -final ProductTypeDraft productTypeDraft = - ProductTypeDraftBuilder - .of("key", "name", "description", emptyList()) - .build(); - -// SDK v2: ProductTypeDraftBuilder without draftTemplate -final ProductTypeDraft productTypeDraft = - ProductTypeDraftBuilder.of() - .description("product-type-description") - .key("product-type-key") - .name("product-type-name") - .build(); -``` -For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). - -### Query for ProductTypes (syncing from CTP project) - -If you sync producttypes between different commercetools projects you probably use [ProductTypeTransformUtils#toProductTypeDrafts](#todo) to transform `ProductType` into `ProductTypeDraft` which can be used by the producttype-sync. -However, if you need to query `ProductTypes` from a commercetools project instead of passing `ProductTypeQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. -Here's an example: - -```java -// SDK v1: ProductTypeQuery to fetch all producttypes -final ProductTypeQuery query = ProductTypeQuery.of(); - -final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); - -// SDK v2: Create and execute query to fetch all producttypes in one line -final ProductTypePagedQueryResponse result = apiRoot.productTypes().get().executeBlocking().getBody(); -``` -[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. - -### JVM-SDK-V2 migration guide - -On any other needs to migrate your project using jvm-sdk-v2 please refer to its [Migration Guide](https://docs.commercetools.com/sdk/java-sdk-migrate). diff --git a/docs/sdk2/usage/QUICK_START.md b/docs/sdk2/usage/QUICK_START.md deleted file mode 100644 index f62fb81803..0000000000 --- a/docs/sdk2/usage/QUICK_START.md +++ /dev/null @@ -1,71 +0,0 @@ -# ⚡ Quick Start - - - - - -- [1. Installation](#1-installation) -- [2. Setup Syncing Options](#2-setup-syncing-options) -- [3. Start Syncing](#3-start-syncing) -- [4. And you're done ✨](#4-and-youre-done-) - - - -### 1. Installation -- Make sure you have `JDK 11` or higher installed. -- Add the following dependency in your application: -- For Maven users: -````xml - - - com.commercetools - commercetools-sync-java - 10.0.0 - -```` -- For Gradle users: -````groovy -// Add commercetools-sync-java dependency. -implementation 'com.commercetools:commercetools-sync-java:10.0.0' -```` - -### 2. Setup Syncing Options - - ```java - final Logger logger = LoggerFactory.getLogger(MySync.class); - final ProductSyncOptions productsyncOptions = ProductSyncOptionsBuilder - .of(projectApiRoot) - .errorCallback((syncException, draft, productProjection, updateActions) -> - logger.error(syncException.getMessage(), syncException)) - .warningCallback((exception, oldProductProjection, newResources) -> - logger.warn(exception.getMessage(), exception)) - .build(); - ``` - -### 3. Start Syncing - ````java - // Transform your product feed batch into a list of ProductDrafts using your preferred way. - final List productDraftsBatch = ... - - final ProductSync productSync = new ProductSync(productSyncOptions); - - // execute the sync on your list of products - final CompletionStage syncStatisticsStage = productSync.sync(productDraftsBatch); - ```` -### 4. And you're done ✨ - ````java - final ProductSyncStatistics stats = syncStatisticsStage.toCompletebleFuture() - .join(); - stats.getReportMessage(); - /*"Summary: 2000 product(s) were processed in total (1000 created, 995 updated, 5 failed to sync and 0 - product(s) with missing reference(s))."*/ - ```` - - -#### More Details -*[Product Sync](PRODUCT_SYNC.md), [ProductType Sync](PRODUCT_TYPE_SYNC.md), -[Category Sync](CATEGORY_SYNC.md), [Inventory Sync](INVENTORY_SYNC.md), -[Type Sync](TYPE_SYNC.md), [CartDiscount Sync](CART_DISCOUNT_SYNC.md), -[TaxCategory Sync](#todo), [State Sync](STATE_SYNC.md), -[CustomObject Sync](CUSTOM_OBJECT_SYNC.md), [Customer Sync](CUSTOMER_SYNC.md), -[ShoppingLists Sync](#todo)* diff --git a/docs/sdk2/usage/SHOPPING_LIST_SYNC.md b/docs/sdk2/usage/SHOPPING_LIST_SYNC.md deleted file mode 100644 index 584403dcd7..0000000000 --- a/docs/sdk2/usage/SHOPPING_LIST_SYNC.md +++ /dev/null @@ -1,397 +0,0 @@ -# Shopping List Sync - -The module used for importing/syncing Shopping Lists into a commercetools project. -It also provides utilities for generating update actions based on the comparison of a [ShoppingList](https://docs.commercetools.com/api/projects/shoppingLists#shoppinglist) -against a [ShoppingListDraft](https://docs.commercetools.com/api/projects/shoppingLists#shoppinglistdraft). - - - - -**Table of Contents** - -- [Usage](#usage) - - [Prerequisites](#prerequisites) - - [ProjectApiRoot](#projectapiroot) - - [Required Fields](#required-fields) - - [Reference Resolution](#reference-resolution) - - [Syncing from a commercetools project](#syncing-from-a-commercetools-project) - - [Syncing from an external resource](#syncing-from-an-external-resource) - - [SyncOptions](#syncoptions) - - [errorCallback](#errorcallback) - - [warningCallback](#warningcallback) - - [beforeUpdateCallback](#beforeupdatecallback) - - [beforeCreateCallback](#beforecreatecallback) - - [batchSize](#batchsize) - - [cacheSize](#cachesize) - - [Running the sync](#running-the-sync) - - [More examples of how to use the sync](#more-examples-of-how-to-use-the-sync) - - [Build all update actions](#build-all-update-actions) - - [Build particular update action(s)](#build-particular-update-actions) -- [Caveats](#caveats) -- [Migration Guide](#migration-guide) - - [Client configuration and creation](#client-configuration-and-creation) - - [Signature of ShoppingListSyncOptions](#signature-of-shoppinglistsyncoptions) - - [Build ShoppingListDraft (syncing from external project)](#build-shoppinglistdraft-syncing-from-external-project) - - [Query for ShoppingLists (syncing from CTP project)](#query-for-shoppinglists-syncing-from-ctp-project) - - [JVM-SDK-V2 migration guide](#jvm-sdk-v2-migration-guide) - - - - -## Usage - -### Prerequisites -#### ProjectApiRoot - -Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -To create the required `ClientCredentials` for client creation, please utilize the `ClientCredentialsBuilder` provided in the java-sdk-v2 [Client OAUTH2 package](#todo). -If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). - -````java -final ClientCredentials clientCredentials = - new ClientCredentialsBuilder() - .withClientId("client-id") - .withClientSecret("client-secret") - .withScopes("scopes") - .build(); -final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); -```` - -#### Required Fields - -The following fields are **required** to be set in, otherwise, they won't be matched by sync: - -|Draft|Required Fields|Note| -|---|---|---| -| [ShoppingListDraft](https://docs.commercetools.com/api/projects/shoppingLists#shoppinglistdraft) | `key` | Also, the shopping lists in the target project are expected to have the `key` fields set. | -| [LineItemDraft](https://docs.commercetools.com/api/projects/shoppingLists#lineitemdraft) | `sku` | Also, all the line items in the target project are expected to have the `sku` fields set. | -| [TextLineItemDraft](https://docs.commercetools.com/api/projects/shoppingLists#textlineitem) | `name` | | - -#### Reference Resolution - -In commercetools, a reference can be created by providing the key instead of the ID with the type [ResourceIdentifier](https://docs.commercetools.com/api/types#resourceidentifier). -When the reference key is provided with a `ResourceIdentifier`, the sync will resolve the resource with the given key and use the ID of the found resource to create or update a reference. -Therefore, in order to resolve the actual ids of those references in the sync process, `ResourceIdentifier`s with their `key`s have to be supplied. - -|Reference Field|Type| -|:---|:---| -| `customer` | CustomerResourceIdentifier | -| `custom.type` | TypeResourceIdentifier | -| `lineItems.custom.type` | TypeResourceIdentifier | -| `textLineItems.custom.type ` | TypeResourceIdentifier | - -> Note that a reference without the key field will be considered as an existing resource on the target commercetools project and the library will issue an update/create an API request without reference resolution. - -##### Syncing from a commercetools project - -When syncing from a source commercetools project, you can use [`toShoppingListDrafts`](#todo) - method that transforms(resolves by querying and caching key-id pairs) and maps from a `ShoppingList` to `ShoppingListDraft` using cache in order to make them ready for reference resolution by the sync, for example: - -````java -// Build a ShoppingListQuery for fetching shopping lists from a source CTP project with expansion for line items for the sync: -final ByProjectKeyShoppingListsGet byProjectKeyShoppingListsGet = client.shoppingLists().addExpand("lineItems[*].variant").get(); - -// Query all shopping lists (NOTE this is just for example, please adjust your logic) -final List states = QueryUtils.queryAll(byProjectKeyShoppingListsGet, - (shoppingLists) -> shoppingLists) - .thenApply(lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())) - .toCompletableFuture() - .join(); -```` - -In order to transform and map the `ShoppingList` to `ShoppingListDraft`, -Utils method `toShoppingListDrafts` requires `projectApiRoot`, implementation of [`ReferenceIdToKeyCache`](#todo) and `shoppingLists` as parameters. -For cache implementation, you can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](#todo). -Example as shown below: - -````java -//Implement the cache using library class. -final ReferenceIdToKeyCache referenceIdToKeyCache = new CaffeineReferenceIdToKeyCacheImpl(); - -//For every reference fetch its key using id, cache it and map from ShoppingList to ShoppingListDraft. With help of the cache same reference keys can be reused. -final CompletableFuture> shoppingListDrafts = ShoppingListTransformUtils.toShoppingListDrafts(client, referenceIdToKeyCache, shoppingLists); -```` - -##### Syncing from an external resource - -- When syncing from an external resource, `ResourceIdentifier`s with their `key`s have to be supplied as following example: - -````java -final ShoppingListDraft shoppingListDraft = - ShoppingListDraftBuilder - .of() - .name(LocalizedString.ofEnglish("name")) - .key("shopping-list-key") - .customer(CustomerResourceIdentifierBuilder.of().key("customer-key").build()) // note that customer provided with key - .custom(CustomFieldsDraftBuilder.of().type(typeResourceIdentifierBuilder -> typeResourceIdentifierBuilder.key("type-key")) - .fields(fieldContainerBuilder -> fieldContainerBuilder.values(Map.of())).build() - ) // note that custom type provided with key - .lineItems(List.of(ShoppingListLineItemDraftBuilder - .of() - .sku("SKU-1") - .quantity(1L) // note that sku field is set. - .custom(CustomFieldsDraftBuilder.of().type(typeResourceIdentifierBuilder -> typeResourceIdentifierBuilder.key("type-key")) - .fields(fieldContainerBuilder -> fieldContainerBuilder.values(Map.of())).build() - ) // note that custom type provided with key - .build()) - ) - .textLineItems(List.of( - TextLineItemDraftBuilder.of().name(ofEnglish("name")).quantity(1L) // note that name field is set for text line item. - .custom(CustomFieldsDraftBuilder.of().type(typeResourceIdentifierBuilder -> typeResourceIdentifierBuilder.key("type-key")) - .fields(fieldContainerBuilder -> fieldContainerBuilder.values(Map.of())).build() - ) // note that custom type provided with key - .build() - ) - ) - .build(); -```` - -#### SyncOptions - -After the `projectApiRoot` is set up, a `ShoppingListSyncOptions` should be built as follows: -````java -// instantiating a ShoppingListSyncOptions -final ShoppingListSyncOptions shoppingListSyncOptions = ShoppingListSyncOptionsBuilder.of(projectApiRoot).build(); -```` - -`SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. -Available configurations: - -##### errorCallback -A callback that is called whenever an error event occurs during the sync process. Each resource executes its own -error-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the error-event: - -* sync exception -* shopping list draft from the source -* shopping list of the target project (only provided if an existing shopping list could be found) -* the update-actions, which failed (only provided if an existing shopping list could be found) - -````java - final Logger logger = LoggerFactory.getLogger(ShoppingListSync.class); - final ShoppingListSyncOptions shoppingListSyncOptions = ShoppingListSyncOptionsBuilder - .of(projectApiRoot) - .errorCallback((syncException, draft, shoppingList, updateActions) -> - logger.error(new SyncException("My customized message"), syncException)).build(); -```` - -##### warningCallback -A callback is called whenever a warning event occurs during the sync process. Each resource executes its own -warning-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the warning message: - -* sync exception -* shopping list draft from the source -* shopping list of the target project (only provided if an existing shopping list could be found) - -````java - final Logger logger = LoggerFactory.getLogger(ShoppingListSync.class); - final ShoppingListSyncOptions shoppingListSyncOptions = ShoppingListSyncOptionsBuilder - .of(projectApiRoot) - .warningCallback((syncException, draft, shoppingList) -> - logger.warn(new SyncException("My customized message"), syncException)).build(); -```` - -##### beforeUpdateCallback -During the sync process, if a target customer and a customer draft are matched, this callback can be used to -intercept the **_update_** request just before it is sent to the commercetools platform. This allows the user to modify -update actions array with custom actions or discard unwanted actions. The callback provides the following information : - - * shopping list draft from the source - * shopping list from the target project - * update actions that were calculated after comparing both - -````java -final TriFunction, ShoppingListDraft, ShoppingList, - List> beforeUpdateCallback = - (updateActions, newShoppingList, oldShoppingList) -> updateActions - .stream() - .filter(updateAction -> !(updateAction instanceof ShoppingListSetSlugAction)) - .collect(Collectors.toList()); - -final ShoppingListSyncOptions shoppingListSyncOptions = ShoppingListSyncOptionsBuilder - .of(projectApiRoot) - .beforeUpdateCallback(beforeUpdateCallback) - .build(); -```` - -##### beforeCreateCallback -During the sync process, if a shopping list draft should be created, this callback can be used to intercept the **_create_** request just before it is sent to the commercetools platform. It contains the following information : - - * shopping list that should be created - - Please refer to the [example in the product sync document](#todo). - -##### batchSize -A number that could be used to set the batch size with which shopping lists are fetched and processed, -as shopping lists are obtained from the target project on the commercetools platform in batches for better performance. The algorithm accumulates up to `batchSize` resources from the input list, then fetches the corresponding shopping lists -from the target project on the commercetools platform in a single request. Playing with this option can slightly improve or reduce processing speed. If it is not set, the default batch size is 50 for shopping list sync. - -````java -final ShoppingListSyncOptions shoppingListSyncOptions = - ShoppingListSyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); -```` - -##### cacheSize -In the service classes of the commercetools-sync-java library, we have implemented an in-memory [LRU cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) to store a map used for the reference resolution of the library. -The cache reduces the reference resolution based calls to the commercetools API as the required fields of a resource will be fetched only one time. These cached fields then might be used by another resource referencing the already resolved resource instead of fetching from commercetools API. It turns out, having the in-memory LRU cache will improve the overall performance of the sync library and commercetools API. -which will improve the overall performance of the sync and commercetools API. - -Playing with this option can change the memory usage of the library. If it is not set, the default cache size is `10.000` for shopping list sync. - -````java -final ShoppingListSyncOptions shoppingListSyncOptions = - ShoppingListSyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); -```` - -### Running the sync -When all prerequisites are fulfilled, follow these steps to run the sync: - -````java -// instantiating a shopping list sync -final ShoppingListSync shoppingListSync = new ShoppingListSync(shoppingListSyncOptions); - -// execute the sync on your list of shopping lists -CompletionStage syncStatisticsStage = shoppingListSync.sync(shoppingListDrafts); -```` -The result of completing the `syncStatisticsStage` in the previous code snippet contains a `ShoppingListSyncStatistics` -which contains all the stats of the sync process; which includes a report message, the total number of updated, created, -failed, processed shopping lists, and the processing time of the last sync batch in different time units and in a -human-readable format. - -````java -final ShoppingListSyncStatistics stats = syncStatisticsStage.toCompletebleFuture().join(); -stats.getReportMessage(); -/*"Summary: 100 shopping lists were processed in total (11 created, 87 updated, 2 failed to sync)."*/ -```` - -__Note__ The statistics object contains the processing time of the last batch only. This is due to two reasons: - - 1. The sync processing time should not take into account the time between supplying batches to the sync. - 2. It is not known by the sync which batch is going to be the last one supplied. - -#### More examples of how to use the sync - - [Sync from an external source](#todo). - - *Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* - -### Build all update actions - A utility method provided by the library to compare a `ShoppingList` to a new `ShoppingListDraft`. The results are collected in a list of shopping list update actions. - ```java - List updateActions = ShoppingListSyncUtils.buildActions(shoppingList, shoppingListDraft, shoppingListSyncOptions); - ``` - -### Build particular update action(s) - The library provides utility methods to compare specific fields of a `ShoppingList` and a new `ShoppingListDraft`, and builds the update action(s) as a result. - One example is the `buildChangeNameUpdateAction` which compare shopping list names: - ````java - Optional updateAction = ShoppingListUpdateActionUtils.buildChangeNameAction(shoppingList, shoppingListDraft); - ```` - - More examples for particular update actions can be found in the test scenarios for [ShoppingListUpdateActionUtils](#todo). - - -## Caveats - -In commercetools shopping lists API, there is no update action to change the `addedAt` field of the `LineItem` and `TextLineItem`, -hereby commercetools-java-sync library will not update the `addedAt` value. -> For the new LineItem and TextLineItem the `addedAt` values will be added, if the draft has the value set. - - -## Migration Guide - -The shopping-list-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with -any HTTP client module. The default one is `commercetools-http-client`. - -```xml - - - LATEST - - - - - com.commercetools.sdk - commercetools-http-client - ${commercetools.version} - - - com.commercetools.sdk - commercetools-sdk-java-api - ${commercetools.version} - - -``` - -### Client configuration and creation - -For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). - -### Signature of ShoppingListSyncOptions - -As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `ShoppingListDraft`, `ShoppingList` and `ShoppingListUpdateAction` from `package com.commercetools.api.models.shopping_list.*` - -> Note: Type `UpdateAction` has changed to `ShoppingListUpdateAction`. Make sure you create and supply a specific ShoppingListUpdateAction in `beforeUpdateCallback`. For that you can use the [library-utilities](#todo) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): - -```java -// Example: Create a shopping-list update action to change name taking the 'newName' of the shoppingListDraft - final Function createBeforeUpdateAction = - (newName) -> ShoppingListChangeNameAction.builder().name(newName).build(); - -// Add the change name action to the list of update actions before update is executed - final TriFunction< - List, ShoppingListDraft, ShoppingList, List> - beforeUpdateShoppingListCallback = - (updateActions, newShoppingListDraft, oldShoppingList) -> { - final ShoppingListUpdateAction beforeUpdateAction = - createBeforeUpdateAction.apply(newShoppingListDraft.getName()); - updateActions.add(beforeUpdateAction); - return updateActions; - }; -``` - -### Build ShoppingListDraft (syncing from external project) - -The shopping-list-sync expects a list of `ShoppingListDraft`s to process. If you use java-sync-library to sync your shopping-lists from any external system into a commercetools platform project you have to convert your data into CTP compatible `ShoppingListDraft` type. This was done in previous version using `DraftBuilder`s. -The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: - -```java -// SDK v1: ShoppingListDraftBuilder.of takes parameters 'key', 'name' and 1 line item -final ShoppingListDraft shoppingListDraft = - ShoppingListDraftBuilder.of(LocalizedString.ofEnglish("name")) - .key("key") - .plusLineItems(LineItemDraftBuilder.ofSku("sku", Long.valueOf(1)).build()) - .build() - -// SDK v2: ShoppingListDraftBuilder without draftTemplate -final ShoppingListDraft shoppingListDraft = - ShoppingListDraftBuilder.of() - .name(LocalizedString.ofEnglish("name")) - .key("product-type-key") - .lineItems(ShoppingListLineItemDraftBuilder.of().sku("SKU-1").quantity(1L).build()) - .build(); -``` -For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). - -### Query for ShoppingLists (syncing from CTP project) - -If you sync shopping lists between different commercetools projects you probably use [ShoppingListTransformUtils#toShoppingListDrafts](#todo) to transform `ShoppingList` into `ShoppingListDraft` which can be used by the shopping-list-sync. -However, if you need to query `ShoppingLists` from a commercetools project instead of passing `ShoppingListQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. -Here's an example: - -```java -// SDK v1: ShoppingListQuery to fetch all shopping lists -final ShoppingListQuery query = ShoppingListQuery.of(); - -final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); - -// SDK v2: Create and execute query to fetch all shopping lists in one line -final ShoppingListPagedQueryResponse result = apiRoot.shoppingLists().get().executeBlocking().getBody(); -``` -[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. - -### JVM-SDK-V2 migration guide - -On any other needs to migrate your project using jvm-sdk-v2 please refer to its [Migration Guide](https://docs.commercetools.com/sdk/java-sdk-migrate). diff --git a/docs/sdk2/usage/STATE_SYNC.md b/docs/sdk2/usage/STATE_SYNC.md deleted file mode 100644 index b969342189..0000000000 --- a/docs/sdk2/usage/STATE_SYNC.md +++ /dev/null @@ -1,417 +0,0 @@ -# State Sync - -The module used for importing/syncing States into a commercetools project. -It also provides utilities for generating update actions based on the comparison a [State](https://docs.commercetools.com/api/projects/states#state) (which basically represents what commercetools already has) -against a [StateDraft](https://docs.commercetools.com/api/projects/states#statedraft) (which represents a new version of the state supplied by the user). - - - - -- [Usage](#usage) - - [Prerequisites](#prerequisites) - - [ProjectApiRoot](#projectapiroot) - - [Required Fields](#required-fields) - - [Reference Resolution](#reference-resolution) - - [Syncing from a commercetools project](#syncing-from-a-commercetools-project) - - [Syncing from an external resource](#syncing-from-an-external-resource) - - [SyncOptions](#syncoptions) - - [errorCallback](#errorcallback) - - [warningCallback](#warningcallback) - - [beforeUpdateCallback](#beforeupdatecallback) - - [beforeCreateCallback](#beforecreatecallback) - - [batchSize](#batchsize) - - [cacheSize](#cachesize) - - [Running the sync](#running-the-sync) - - [Persistence of StateDrafts with missing references](#persistence-of-statedrafts-with-missing-references) - - [More examples of how to use the sync](#more-examples-of-how-to-use-the-sync) - - [Build all update actions](#build-all-update-actions) - - [Build particular update action(s)](#build-particular-update-actions) -- [Migration Guide](#migration-guide) - - [Client configuration and creation](#client-configuration-and-creation) - - [Signature of StateSyncOptions](#signature-of-statesyncoptions) - - [Build StateDraft (syncing from external project)](#build-statedraft-syncing-from-external-project) - - [Query for states (syncing from CTP project)](#query-for-states-syncing-from-ctp-project) - - [Referencing other states in transitions](#referencing-other-states-in-transitions) - - - -## Usage - -### Prerequisites - -#### ProjectApiRoot - - -Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](#todo) -If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). - -````java -final ClientCredentials clientCredentials = - new ClientCredentialsBuilder() - .withClientId("client-id") - .withClientSecret("client-secret") - .withScopes("scopes") - .build(); -final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); -```` - -#### Required Fields - -The following fields are **required** to be set in, otherwise, they won't be matched by sync: - -|Draft|Required Fields|Note| -|---|---|---| -| [StateDraft](https://docs.commercetools.com/api/projects/states#statedraft)| `key` | Also, the states in the target project are expected to have the `key` fields set. | - -#### Reference Resolution - -`Transitions` are a way to describe possible transformations of the current state to other states of the same type (for example Initial -> Shipped). When performing a [SetTransitions](https://docs.commercetools.com/api/projects/states#set-transitions), an array of [ResourceIdentifiers](https://docs.commercetools.com/api/projects/states#ctp:api:type:StateResourceIdentifier) to State is needed. -In commercetools, a [ResourceIdentifier](https://docs.commercetools.com/api/projects/states#ctp:api:type:StateResourceIdentifier) can be created by providing either the key or the ID. -When the key to a referenced state is provided with a `ResourceIdentifier`, the sync will resolve the resource with the given key and use the ID of the found resource to create or update a reference. - -| ResourceIdentifier Field | Type | -|:-------------------------|:------------------------------------------| -| `transitions` | Array of StateResourceIdentifiers | - -##### Syncing from a commercetools project - -When syncing from a source commercetools project, you can use [`toStateDrafts`](#todo) - method that transforms(resolves by querying and caching key-id pairs) and maps from a `State` to `StateDraft` using cache in order to make them ready for reference resolution by the sync, for example: - -````java -// Build a ByProjectKeyStatesGet for fetching states from a source CTP project without any references expanded for the sync: -final ByProjectKeyStatesGet byProjectKeyStatesGet = client.states().get(); - -// Query all states (NOTE this is just for example, please adjust your logic) -final List states = QueryUtils.queryAll(byProjectKeyStatesGet, - (states) -> states) - .thenApply(lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())) - .toCompletableFuture() - .join(); -```` - -In order to transform and map the `State` to `StateDraft`, -Utils method `toStateDrafts` requires `projectApiRoot`, implementation of [`ReferenceIdToKeyCache`](#todo) and `states` as parameters. -For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](#todo). -Example as shown below: - -````java -//Implement the cache using library class. -final ReferenceIdToKeyCache referenceIdToKeyCache = new CaffeineReferenceIdToKeyCacheImpl(); - -//For every reference fetch its key using id, cache it and map from State to StateDraft. With help of the cache same reference keys can be reused. -final CompletableFuture> stateDrafts = StateTransformUtils.toStateDrafts(client, referenceIdToKeyCache, states); -```` - -##### Syncing from an external resource - -- When syncing from an external resource, `ResourceIdentifier`s with their `key`s have to be supplied as following example: - -````java -final StateDraft stateDraft = StateDraftBuilder.of() - .key("state-key") - .type(StateTypeEnum.LINE_ITEM_STATE) - .transitions(StateResourceIdentifierBuilder.of().key("another-state-key").build()) - .build(); -```` - - -#### SyncOptions - -After the `projectApiRoot` is set up, a `StateSyncOptions` should be built as follows: - -````java -// instantiating a StateSyncOptions - final StateSyncOptions stateSyncOptions = StateSyncOptionsBuilder.of(projectApiRoot).build(); -```` - -`SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. -Available configurations: - -##### errorCallback -A callback that is called whenever an error event occurs during the sync process. Each resource executes its own -error-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the error-event: - -* sync exception -* state draft from the source -* state of the target project (only provided if an existing state could be found) -* the update-actions, which failed (only provided if an existing state could be found) - -````java - final Logger logger = LoggerFactory.getLogger(StateSync.class); - final StateSyncOptions stateSyncOptions = StateSyncOptionsBuilder - .of(projectApiRoot) - .errorCallback((syncException, draft, state, updateActions) -> - logger.error(new SyncException("My customized message"), syncException)).build(); -```` - -##### warningCallback - -A callback is called whenever a warning event occurs during the sync process. Each resource executes its own -warning-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the warning message: - -* sync exception -* state draft from the source -* state of the target project (only provided if an existing state could be found) - -````java - final Logger logger = LoggerFactory.getLogger(StateSync.class); - final StateSyncOptions stateSyncOptions = StateSyncOptionsBuilder - .of(projectApiRoot) - .warningCallback((syncException, draft, state) -> - logger.warn(new SyncException("My customized message"), syncException)).build(); -```` - -##### beforeUpdateCallback -During the sync process, if a target state and a state draft are matched, this callback can be used to -intercept the **_update_** request just before it is sent to the commercetools platform. This allows the user to modify -update actions array with custom actions or discard unwanted actions. The callback provides the following information : - - * state draft from the source - * state from the target project - * update actions that were calculated after comparing both - -````java -final TriFunction< - List, StateDraft, State, List> - beforeUpdateStateCallback = - (updateActions, newStateDraft, oldState) -> updateActions.stream() - .filter(updateAction -> !(updateAction instanceof StateRemoveRolesAction)) - .collect(Collectors.toList()); - -final StateSyncOptions stateSyncOptions = - StateSyncOptionsBuilder.of(projectApiRoot).beforeUpdateCallback(beforeUpdateStateCallback).build(); -```` - -##### beforeCreateCallback -During the sync process, if a state draft should be created, this callback can be used to intercept the **_create_** request just before it is sent to the commercetools platform. It contains the following information : - - * state draft that should be created - -Please refer to [example in product sync document](PRODUCT_SYNC.md#example-set-publish-stage-if-category-references-of-given-product-draft-exists). - -##### batchSize -A number that could be used to set the batch size with which states are fetched and processed, -as states are obtained from the target project on commercetools platform in batches for better performance. The algorithm accumulates up to `batchSize` resources from the input list, then fetches the corresponding states -from the target project on the commecetools platform in a single request. Playing with this option can slightly improve or reduce processing speed. If it is not set, the default batch size is 50 for state sync. - -````java -final StateSyncOptions stateSyncOptions = - StateSyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); -```` - -##### cacheSize -In the service classes of the commercetools-sync-java library, we have implemented an in-memory [LRU cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) to store a map used for the reference resolution of the library. -The cache reduces the reference resolution based calls to the commercetools API as the required fields of a resource will be fetched only one time. These cached fields then might be used by another resource referencing the already resolved resource instead of fetching from commercetools API. It turns out, having the in-memory LRU cache will improve the overall performance of the sync library and commercetools API. -which will improve the overall performance of the sync and commercetools API. - -Playing with this option can change the memory usage of the library. If it is not set, the default cache size is `10.000` for state sync. - -````java -final StateSyncOptions stateSyncOptions = - StateSyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); -```` - - -### Running the sync -After all the aforementioned points in the previous section have been fulfilled, run the sync as follows: -````java -// instantiating a State sync - final StateSync stateSync = new StateSync(stateSyncOptions); - -// execute the sync on your list of StateDraft - final CompletionStage stateSyncStatisticsStage = stateSync.sync(stateDrafts); -```` -The result of the completing the `StateSyncStatistics` in the previous code snippet contains a `StateSyncStatistics` -which contains all the stats of the sync process; which includes a report message, the total number of updated, created, -failed, processed states, the missing parent of transitions and the processing time of the sync in different time units and in a -human-readable format. -````java -final StateSyncStatistics stats = stateSyncStatisticsStage.toCompletebleFuture().join(); -stats.getReportMessage(); -// Summary: 3 state(s) were processed in total (3 created, 0 updated, 0 failed to sync and 0 state(s) with missing transition(s). -```` - -__Note__ The statistics object contains the processing time of the last batch only. This is due to two reasons: - - 1. The sync processing time should not take into account the time between supplying batches to the sync. - 2. It is not known by the sync which batch is going to be the last one supplied. - -##### Persistence of StateDrafts with missing references - -A StateDraft (state-A) could be supplied with a transition referencing StateDraft (state-B). -It could be that (state-B) is not supplied before (state-A), which means the sync could fail to create/update (state-A). -It could also be that (state-B) is not supplied at all in this batch but at a later batch. - -The library keeps tracks of such "referencing" states like (state-A) and persists them in storage -(**commercetools `customObjects` in the target project** , in this case) -to keep them and create/update them accordingly whenever the referenced state has been provided at some point. - -The `customObject` will have a `container:` **`"commercetools-sync-java.UnresolvedTransitionsService.stateDrafts"`** -and a `key` representing a hash value of the StateDraft key that is waiting to be created/updated. - - -Here is an example of a `CustomObject` in the target project that represents a StateDraft with key `state-A`. -It being persisted as `CustomObject` means that the referenced StateDrafts with keys `state-B` do not exist yet. - -```json -{ - "container": "commercetools-sync-java.UnresolvedTransitionsService.stateDrafts", - "key": "518ea82bb78755c0cdd67909dd3206d56186f7e5", - "value": { - "missingTransitionStateKeys": [ - "state-B" - ], - "stateDraft": { - "type": "ReviewState", - "transitions": [ - { - "id": "state-B", - "typeId": "state" - } - ], - "roles": [ - "ReviewIncludedInStatistics" - ], - "key": "state-A", - "initial": true - } - } -} -``` - -As soon, as the referenced StateDrafts are supplied to the sync, the draft will be created/updated and the -`CustomObject` will be removed from the target project. - -Keeping the old custom objects around forever can negatively influence the performance of your project and the time it takes to restore it from a backup. Deleting unused data ensures the best performance for your project. Please have a look into the [Cleanup guide](CLEANUP_GUIDE.md) to cleanup old unresolved custom objects. - -#### More examples of how to use the sync - - 1. [Sync usages](#todo). - -*Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* - - -### Build all update actions - -A utility method provided by the library to compare a `State` with a new `StateDraft` and results in a list of state update actions. - update actions. -```java -List updateActions = StateSyncUtils.buildActions(state, stateDraft, stateSyncOptions); -``` - -### Build particular update action(s) - -Utility methods provided by the library to compare the specific fields of a `State` and a new `StateDraft`, and in turn builds - the update action. One example is the `buildSetNameAction` which compares names: -````java -Optional updateAction = StateUpdateActionUtils.buildSetNameAction(oldState, stateDraft); -```` -More examples of those utils for different types can be found [here](#todo). - - -## Migration Guide - -The state-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with -any HTTP client module. The default one is `commercetools-http-client`. - -```xml - - - LATEST - - - - - com.commercetools.sdk - commercetools-http-client - ${commercetools.version} - - - com.commercetools.sdk - commercetools-sdk-java-api - ${commercetools.version} - - - -``` - -### Client configuration and creation - -For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). - -### Signature of StateSyncOptions - -As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `State`, `StateDraft` and `StateUpdateAction` from `package com.commercetools.api.models.state.*` - -> Note: Type `StateUpdateAction` has changed to `StateUpdateAction`. Make sure you create and supply a specific StateUpdateAction in `beforeUpdateCallback`. For that you can use the [library-utilities](#todo) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): - -```java -// Example: Create a state update action to change name taking the 'newName' of the stateDraft - final Function createBeforeUpdateAction = - (newName) -> StateSetNameAction.builder().name(newName).build(); - -// Add the change name action to the list of update actions before update is executed - final TriFunction< - List, StateDraft, State, List> - beforeUpdateStateCallback = - (updateActions, newStateDraft, oldState) -> { - final StateUpdateAction beforeUpdateAction = - createBeforeUpdateAction.apply(newStateDraft.getName()); - updateActions.add(beforeUpdateAction); - return updateActions; - }; -``` - -### Build StateDraft (syncing from external project) - -The state-sync expects a list of `StateDraft`s to process. If you use java-sync-library to sync your states from any external system into a commercetools platform project you have to convert your data into CTP compatible `StateDraft` type. This was done in previous version using `DraftBuilder`s. -The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: - -```java -// StateDraftBuilder in v1 takes parameters 'key', 'type' -final StateDraft stateDraft = - StateDraftBuilder.of("key", StateType.LINE_ITEM_STATE) - .name(ofEnglish("state-name")) - .description(ofEnglish("state-desc")) - .roles(Collections.singleton(StateRole.RETURN)) - .initial(false) - .build(); - -// StateDraftBuilder in v2 -final StateDraft stateDraft = - StateDraftBuilder.of() - .key("key") - .type(StateTypeEnum.LINE_ITEM_STATE) - .name(ofEnglish("state-name")) - .description(ofEnglish("state-desc")) - .roles(StateRoleEnum.RETURN) - .initial(false) - .build(); -``` -For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). - -### Query for states (syncing from CTP project) - -If you sync states between different commercetools projects you probably use [StateTransformUtils#toStateDrafts](#todo) to transform `State` into `StateDraft` which can be used by the state-sync. -However, if you need to query `states` from a commercetools project instead of passing `StateQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. -Here's an example: - -```java -// SDK v1: StateQuery to fetch all states -final StateQuery query = StateQuery.of(); - -final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); - -// SDK v2: Create and execute query to fetch all states in one line -final StatePagedQueryResponse result = apiRoot.states().get().executeBlocking().getBody(); -``` -[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. - -### Referencing other states in transitions - -When you use references to other states in the field `transitions`, the state-sync needs to do the reference resolution process. In the previous java-sdk-v1 it was required to provide the `key` value on the `id` field of the reference. In the current java-sdk-v2 you must provide the `key` field in `StateResourceIdentifier`. For detailed information see the [Reference resolution section](#reference-resolution). diff --git a/docs/sdk2/usage/SYNC_OPTIONS.md b/docs/sdk2/usage/SYNC_OPTIONS.md deleted file mode 100644 index 3920c521ba..0000000000 --- a/docs/sdk2/usage/SYNC_OPTIONS.md +++ /dev/null @@ -1,84 +0,0 @@ -# Sync Options - -#### `errorCallback` -a callback that is called whenever an error event occurs during the sync process. It contains the following information -about the error-event: - -* sync exception -* the resource draft of the source project -* the resource of the target project -* the update-actions, which failed - -#### `warningCallback` -a callback that is called whenever a warning event occurs during the sync process. It contains the following information -about the warning message: - -* sync exception -* the resource draft of the source project -* the resource of the target project - -#### `beforeUpdateCallback` -during the sync process, if a target resource and a resource draft are matched, this callback can be used to intercept the **_update_** request just before it is sent to CTP. It contains information about the resource draft, the target -resource, and the update actions that were calculated after comparing both. - -#### `beforeCreateCallback` -during the sync process, if a resource draft should be created, this callback can be used to intercept the **_create_** request just before it sent to CTP. It contains information about the resource draft that should be -created. - -#### `batchSize` -a number that could be used to set the batch size with which resources are fetched and processed, -as resources are obtained from the target CTP project in batches for better performance. The algorithm accumulates up to -`batchSize` resources from the input list, then fetch the corresponding resources from the target CTP project -in a single request. Playing with this option can slightly improve or reduce processing speed. - -#### `cacheSize` -In the service classes of the commercetools-sync-java library, we have implemented an in-memory [LRU cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) to store a map used for the reference resolution of the library. -The cache reduces the reference resolution based calls to the commercetools API as the required fields of a resource will be fetched only one time. These cached fields then might be used by another resource referencing the already resolved resource instead of fetching from commercetools API. It turns out, having the in-memory LRU cache will improve the overall performance of the sync library and commercetools API. -which will improve the overall performance of the sync and commercetools API. - -Playing with this option can change the memory usage of the library. If it is not set, the default cache size is `10.000` for the sync. - - -#### `syncFilter` (Only for Product Sync Options) -represents either a blacklist or a whitelist for filtering certain update action groups. - - - __Blacklisting__ an update action group means that everything in products will be synced except for any group in the blacklist. A typical use case is to blacklist prices when syncing products. In other words, syncing everything - in products except for prices. - - - __Whitelisting__ an update action group means that the groups in this whitelist will be the *only* group synced in products. One use case could be to whitelist prices when syncing products. In other words, syncing prices only in - products and nothing else. - - - The list of action groups allowed to be blacklisted or whitelisted on products can be found [here](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/products/ActionGroup.java). - -#### `ensureChannels` (Only for Product and Inventory Sync Options) -a flag that represents a strategy to handle syncing inventory entries with missing channels. -Having an inventory entry or a product, with a missing channel reference, could be processed in either of the following ways: -- If `ensureChannels` is set to `false` this inventory entry/product won't be synced and the `errorCallback` will be triggered. -- If `ensureChannels` is set to `true` the sync will attempt to create the missing channel with the given key. -If it fails to create the supply channel, the inventory entry/product won't sync and `errorCallback` will be triggered. -- If not provided, it is set to `false` by default. - - -### Examples - -#### 1. Using `errorCallback` and `warningCallback` for logging - -````java - final Logger logger = LoggerFactory.getLogger(MySync.class); - final ProductSyncOptions productsyncOptions = ProductSyncOptionsBuilder - .of(sphereClient) - .errorCallback((syncException, draft, product, updateActions) -> - logger.error(syncException.getMessage(), syncException)) - .warningCallback((exception, oldResource, newResources) -> - logger.warn(exception.getMessage(), exception)) - .build(); -```` - -#### 2. [Using `beforeUpdateCallback` for syncing a single locale](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/externalsource/products/SyncSingleLocaleIT.java). - -#### 3. [Using `beforeUpdateCallback` for keeping other variants](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/ctpprojectsource/products/templates/beforeupdatecallback/KeepOtherVariantsSyncIT.java). - -#### 4. [Using `syncFilter` for blacklisting product categories while syncing products](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/externalsource/products/ProductSyncFilterIT.java#L142-L143). - -#### 5. [Using `syncFilter` for whitelisting product names while syncing products](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/externalsource/products/ProductSyncFilterIT.java#L173). - diff --git a/docs/sdk2/usage/TAX_CATEGORY_SYNC.md b/docs/sdk2/usage/TAX_CATEGORY_SYNC.md deleted file mode 100644 index ed2c53c1aa..0000000000 --- a/docs/sdk2/usage/TAX_CATEGORY_SYNC.md +++ /dev/null @@ -1,301 +0,0 @@ -# Tax Category Sync - -Allows importing/syncing TaxCategory into a commercetools project. -It also provides utilities for generating update actions based on the comparison of a [TaxCategory](https://docs.commercetools.com/api/projects/taxCategories#taxcategory) -against a [TaxCategoryDraft](https://docs.commercetools.com/api/projects/taxCategories#taxcategorydraft). - - - - -- [Usage](#usage) - - [Prerequisites](#prerequisites) - - [ProjectApiRoot](#projectapiroot) - - [Required Fields](#required-fields) - - [SyncOptions](#syncoptions) - - [errorCallback](#errorcallback) - - [warningCallback](#warningcallback) - - [beforeUpdateCallback](#beforeupdatecallback) - - [beforeCreateCallback](#beforecreatecallback) - - [batchSize](#batchsize) - - [cacheSize](#cachesize) - - [Running the sync](#running-the-sync) - - [More examples of how to use the sync](#more-examples-of-how-to-use-the-sync) - - [Build all update actions](#build-all-update-actions) - - [Build particular update action(s)](#build-particular-update-actions) -- [Migration Guide](#migration-guide) - - [Client configuration and creation](#client-configuration-and-creation) - - [Signature of TaxCategorySyncOptions](#signature-of-taxcategorysyncoptions) - - [Build TaxCategoryDraft (syncing from external project)](#build-taxcategorydraft-syncing-from-external-project) - - [Query for TaxCategories (syncing from CTP project)](#query-for-taxcategories-syncing-from-ctp-project) - - [JVM-SDK-V2 migration guide](#jvm-sdk-v2-migration-guide) - - - -## Usage - -### Prerequisites - -#### ProjectApiRoot - -Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](#todo) -If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). - -````java -final ClientCredentials clientCredentials = - new ClientCredentialsBuilder() - .withClientId("client-id") - .withClientSecret("client-secret") - .withScopes("scopes") - .build(); -final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); -```` - -#### Required Fields - -The following fields are **required** to be set in, otherwise, they won't be matched by sync: - -|Draft|Required Fields|Note| -|---|---|---| -| [TaxCategoryDraft](https://docs.commercetools.com/api/projects/taxCategories#taxcategorydraft) | `key` | Also, the tax categories in the target project are expected to have the `key` fields set. | - -#### SyncOptions - -After the `projectApiRoot` is set up, a `TaxCategorySyncOptions` should be built as follows: -````java -// instantiating a TaxCategorySyncOptions -final TaxCategorySyncOptions taxCategorySyncOptions = TaxCategorySyncOptionsBuilder.of(projectApiRoot).build(); -```` - -`SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. -Available configurations: - -##### errorCallback -A callback that is called whenever an error event occurs during the sync process. Each resource executes its own -error-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the error-event: - -* sync exception -* tax category draft from the source -* tax category of the target project (only provided if an existing tax category could be found) -* the update-actions, which failed (only provided if an existing tax category could be found) - -````java - final Logger logger = LoggerFactory.getLogger(TaxCategorySync.class); - final TaxCategorySyncOptions taxCategorySyncOptions = TaxCategorySyncOptionsBuilder - .of(projectApiRoot) - .errorCallback((syncException, draft, taxCategory, updateActions) -> - logger.error(new SyncException("My customized message"), syncException)).build(); -```` - -##### warningCallback -A callback is called whenever a warning event occurs during the sync process. Each resource executes its own -warning-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the warning message: - -* sync exception -* tax category draft from the source -* tax category of the target project (only provided if an existing tax category could be found) - -````java - final Logger logger = LoggerFactory.getLogger(TaxCategorySync.class); - final TaxCategorySyncOptions taxCategorySyncOptions = TaxCategorySyncOptionsBuilder - .of(projectApiRoot) - .warningCallback((syncException, draft, taxCategory) -> - logger.warn(new SyncException("My customized message"), syncException)).build(); -```` - -##### beforeUpdateCallback -During the sync process, if a target tax category and a tax category draft are matched, this callback can be used to -intercept the **_update_** request just before it is sent to the commercetools platform. This allows the user to modify -update actions array with custom actions or discard unwanted actions. The callback provides the following information : - - * tax category draft from the source - * tax category from the target project - * update actions that were calculated after comparing both - -````java -final TriFunction< - List, TaxCategoryDraft, TaxCategory, List> - beforeUpdateTaxCategoryCallback = - (updateActions, newTaxCategoryDraft, oldTaxCategory) -> updateActions.stream() - .filter(updateAction -> !(updateAction instanceof TaxCategoryRemoveTaxRateAction)) - .collect(Collectors.toList()); - -final TaxCategorySyncOptions taxCategorySyncOptions = - TaxCategorySyncOptionsBuilder.of(projectApiRoot).beforeUpdateCallback(beforeUpdateTaxCategoryCallback).build(); -```` - -##### beforeCreateCallback -During the sync process, if a tax category draft should be created, this callback can be used to intercept the **_create_** request just before it is sent to the commercetools platform. It contains the following information : - - * tax category draft that should be created - -Please refer to [example in product sync document](PRODUCT_SYNC.md#beforecreatecallback). - -##### batchSize -A number that could be used to set the batch size with which tax categories are fetched and processed, -as tax categories are obtained from the target project on the commercetools platform in batches for better performance. The algorithm accumulates up to `batchSize` resources from the input list, then fetches the corresponding tax categories from the target project on commecetools platform in a single request. Playing with this option can slightly improve or reduce processing speed. If it is not set, the default batch size is 50 for tax category sync. - -````java -final TaxCategorySyncOptions taxCategorySyncOptions = - TaxCategorySyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); -```` - -##### cacheSize -In the service classes of the commercetools-sync-java library, we have implemented an in-memory [LRU cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) to store a map used for the reference resolution of the library. -The cache reduces the reference resolution based calls to the commercetools API as the required fields of a resource will be fetched only one time. These cached fields then might be used by another resource referencing the already resolved resource instead of fetching from commercetools API. It turns out, having the in-memory LRU cache will improve the overall performance of the sync library and commercetools API. -which will improve the overall performance of the sync and commercetools API. - -Playing with this option can change the memory usage of the library. If it is not set, the default cache size is `10.000` for tax category sync. - -````java -final TaxCategorySyncOptions taxCategorySyncOptions = - TaxCategorySyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); -```` - -### Running the sync -After all the aforementioned points in the previous section have been fulfilled, to run the sync: -````java -// instantiating a TaxCategorySync -final TaxCategorySync taxCategorySync = new TaxCategorySync(taxCategorySyncOptions); - -// execute the sync on your list of tax categories -CompletionStage syncStatisticsStage = taxCategorySync.sync(taxCategoryDrafts); -```` -The result of completing the `syncStatisticsStage` in the previous code snippet contains a `TaxCategorySyncStatistics` -which contains all the stats of the sync process; which includes a report message, the total number of updated, created, -failed, processed tax categories and the processing time of the last sync batch in different time units and in a -human-readable format. - -````java -final TaxCategorySyncStatistics stats = syncStatisticsStage.toCompletebleFuture().join(); -stats.getReportMessage(); -/*"Summary: 2000 tax categories were processed in total (1000 created, 995 updated, 5 failed to sync)."*/ -```` - -__Note__ The statistics object contains the processing time of the last batch only. This is due to two reasons: - - 1. The sync processing time should not take into account the time between supplying batches to the sync. - 2. It is not known by the sync which batch is going to be the last one supplied. - -#### More examples of how to use the sync - -- [Sync from an external source](#todo). - -*Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* - -### Build all update actions - -A utility method provided by the library to compare a `TaxCategory` with a new `TaxCategoryDraft` and results in a list of tax category update actions. -```java -List updateActions = TaxCategorySyncUtils.buildActions(taxCategory, taxCategoryDraft, taxCategorySyncOptions); -``` - -### Build particular update action(s) - -Utility methods provided by the library to compare the specific fields of a `TaxCategory` and a new `TaxCategoryDraft`, and in turn builds - the update action. One example is the `buildChangeNameUpdateAction` which compares names: -````java -Optional updateAction = TaxCategoryUpdateActionUtils.buildChangeNameAction(oldTaxCategory, taxCategoryDraft); -```` -More examples of those utils for different tax categories can be found [here](#todo). - -## Migration Guide - -The tax-category-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with -any HTTP client module. The default one is `commercetools-http-client`. - -```xml - - - LATEST - - - - - com.commercetools.sdk - commercetools-http-client - ${commercetools.version} - - - com.commercetools.sdk - commercetools-sdk-java-api - ${commercetools.version} - - - -``` - -### Client configuration and creation - -For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). - -### Signature of TaxCategorySyncOptions - -As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `TaxCategoryDraft`, `TaxCategory` and `TaxCategoryUpdateAction` from `package com.commercetools.api.models.tax_category.*` - -> Note: Type `UpdateAction` has changed to `TaxCategoryUpdateAction`. Make sure you create and supply a specific TaxCategoryUpdateAction in `beforeUpdateCallback`. For that you can use the [library-utilities](#todo) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): - -```java -// Example: Create a tax-category update action to change name taking the 'newName' of the taxCategoryDraft - final Function changeNameBeforeUpdateAction = - (newName) -> TaxCategoryChangeNameAction.builder().name(newName).build(); - -// Add the change name action to the list of update actions before update is executed - final TriFunction< - List, TaxCategoryDraft, TaxCategory, List> - beforeUpdateTypeCallback = - (updateActions, newTaxCategoryDraft, oldTaxCategory) -> { - final TaxCategoryUpdateAction beforeUpdateAction = - changeNameBeforeUpdateAction.apply(newTaxCategoryDraft.getName()); - updateActions.add(beforeUpdateAction); - return updateActions; - }; -``` - -### Build TaxCategoryDraft (syncing from external project) - -The tax-category-sync expects a list of `TaxCategoryDraft`s to process. If you use java-sync-library to sync your types from any external system into a commercetools platform project you have to convert your data into CTP compatible `TaxCategoryDraft` type. This was done in previous version using `DraftBuilder`s. -The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: - -```java -// TaxCategoryDraftBuilder in v1 takes parameters 'name', 'taxRates' and 'description' -final TaxCategoryDraft taxCategoryDraft = - TaxCategoryDraftBuilder - .of("name", emptyList(), "description") - .key("key") - .build(); - -// TaxCategoryDraftBuilder in v2. -final TaxCategoryDraft taxCategoryDraft = - TaxCategoryDraftBuilder.of() - .key("key") - .name("name") - .rates(emptyList()) - .description("description") - .build(); -``` -For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). - -### Query for TaxCategories (syncing from CTP project) - -If you sync types between different commercetools projects you have to transform `TaxCategory` into `TaxCategoryDraft`. -However, if you need to query `TaxCategory` from a commercetools project instead of passing `TaxCategoryQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. -Here's an example: - -```java -// SDK v1: TaxCategoryQuery to fetch all taxCategories -final TaxCategoryQuery query = TaxCategoryQuery.of(); - -final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); - -// SDK v2: Create and execute query to fetch all tax-categories in one line -final TaxCategoryPagedQueryResponse result = apiRoot.taxCategories().get().executeBlocking().getBody(); -``` -[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. - -### JVM-SDK-V2 migration guide - -On any other needs to migrate your project using jvm-sdk-v2 please refer to it's [Migration Guide](https://docs.commercetools.com/sdk/java-sdk-migrate). diff --git a/docs/sdk2/usage/TYPE_SYNC.md b/docs/sdk2/usage/TYPE_SYNC.md deleted file mode 100644 index dddb348e1c..0000000000 --- a/docs/sdk2/usage/TYPE_SYNC.md +++ /dev/null @@ -1,304 +0,0 @@ -# Type Sync - -The module used for importing/syncing Types into a commercetools project. -It also provides utilities for generating update actions based on the comparison of a [Type](https://docs.commercetools.com/api/projects/types#type) -against a [TypeDraft](https://docs.commercetools.com/api/projects/types#typedraft). - - - - - -- [Usage](#usage) - - [Prerequisites](#prerequisites) - - [SphereClient](#sphereclient) - - [Required Fields](#required-fields) - - [SyncOptions](#syncoptions) - - [errorCallback](#errorcallback) - - [warningCallback](#warningcallback) - - [beforeUpdateCallback](#beforeupdatecallback) - - [beforeCreateCallback](#beforecreatecallback) - - [batchSize](#batchsize) - - [cacheSize](#cachesize) - - [Running the sync](#running-the-sync) - - [Important to Note](#important-to-note) - - [More examples of how to use the sync](#more-examples-of-how-to-use-the-sync) - - [Build all update actions](#build-all-update-actions) - - [Build particular update action(s)](#build-particular-update-actions) -- [Caveats](#caveats) - - - -## Usage - -### Prerequisites - -#### ProjectApiRoot - -Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](#todo) -If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). - -````java -final ClientCredentials clientCredentials = - new ClientCredentialsBuilder() - .withClientId("client-id") - .withClientSecret("client-secret") - .withScopes("scopes") - .build(); -final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); -```` - -#### Required Fields - -The following fields are **required** to be set in, otherwise, they won't be matched by sync: - -|Draft|Required Fields|Note| -|---|---|---| -| [TypeDraft](https://docs.commercetools.com/api/projects/types#typedraft) | `key` | Also, the types in the target project are expected to have the `key` fields set. | - -#### SyncOptions - -After the `projectApiRoot` is set up, a `TypeSyncOptions` should be built as follows: -````java -// instantiating a TypeSyncOptions -final TypeSyncOptions typeSyncOptions = TypeSyncOptionsBuilder.of(projectApiRoot).build(); -```` - -`SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. -Available configurations: - -##### errorCallback -A callback that is called whenever an error event occurs during the sync process. Each resource executes its own -error-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the error-event: - -* sync exception -* type draft from the source -* type of the target project (only provided if an existing type could be found) -* the update-actions, which failed (only provided if an existing type could be found) - -````java - final Logger logger = LoggerFactory.getLogger(TypeSync.class); - final TypeSyncOptions typeSyncOptions = TypeSyncOptionsBuilder - .of(projectApiRoot) - .errorCallback((syncException, draft, type, updateActions) -> - logger.error(new SyncException("My customized message"), syncException)).build(); -```` - -##### warningCallback -A callback is called whenever a warning event occurs during the sync process. Each resource executes its own -warning-callback. When the sync process of a particular resource runs successfully, it is not triggered. It contains the -following context about the warning message: - -* sync exception -* type draft from the source -* type of the target project (only provided if an existing type could be found) - -````java - final Logger logger = LoggerFactory.getLogger(TypeSync.class); - final TypeSyncOptions typeSyncOptions = TypeSyncOptionsBuilder - .of(projectApiRoot) - .warningCallback((syncException, draft, type) -> - logger.warn(new SyncException("My customized message"), syncException)).build(); -```` - -##### beforeUpdateCallback -During the sync process, if a target type and a type draft are matched, this callback can be used to -intercept the **_update_** request just before it is sent to the commercetools platform. This allows the user to modify -update actions array with custom actions or discard unwanted actions. The callback provides the following information : - - * type draft from the source - * type from the target project - * update actions that were calculated after comparing both - -````java -// Example: Ignore update actions that remove field definition -final TriFunction< - List, TypeDraft, Type, List> - beforeUpdateTypeCallback = - (updateActions, newTypeDraft, oldType) -> updateActions.stream() - .filter(updateAction -> !(updateAction instanceof TypeRemoveFieldDefinitionAction)) - .collect(Collectors.toList()); - -final TypeSyncOptions typeSyncOptions = - TypeSyncOptionsBuilder.of(projectApiRoot).beforeUpdateCallback(beforeUpdateTypeCallback).build(); -```` - -##### beforeCreateCallback -During the sync process, if a type draft should be created, this callback can be used to intercept the **_create_** request just before it is sent to the commercetools platform. It contains the following information : - - * type draft that should be created - -Please refer to [example in product sync document](PRODUCT_SYNC.md#beforecreatecallback). - -##### batchSize -A number that could be used to set the batch size with which types are fetched and processed, -as types are obtained from the target project on commercetools platform in batches for better performance. The algorithm accumulates up to `batchSize` resources from the input list, then fetches the corresponding types from the target project on the commecetools platform in a single request. Playing with this option can slightly improve or reduce processing speed. If it is not set, the default batch size is 50 for type sync. - -````java -final TypeSyncOptions typeSyncOptions = - TypeSyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); -```` - -##### cacheSize -In the service classes of the commercetools-sync-java library, we have implemented an in-memory [LRU cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) to store a map used for the reference resolution of the library. -The cache reduces the reference resolution based calls to the commercetools API as the required fields of a resource will be fetched only one time. These cached fields then might be used by another resource referencing the already resolved resource instead of fetching from commercetools API. It turns out, having the in-memory LRU cache will improve the overall performance of the sync library and commercetools API. -which will improve the overall performance of the sync and commercetools API. - -Playing with this option can change the memory usage of the library. If it is not set, the default cache size is `10.000` for type sync. - -````java -final TypeSyncOptions typeSyncOptions = - TypeSyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); -```` - - -### Running the sync -After all the aforementioned points in the previous section have been fulfilled, to run the sync: -````java -// instantiating a type sync -final TypeSync typeSync = new TypeSync(typeSyncOptions); - -// execute the sync on your list of types -CompletionStage syncStatisticsStage = typeSync.sync(typeDrafts); -```` -The result of completing the `syncStatisticsStage` in the previous code snippet contains a `TypeSyncStatistics` -which contains all the stats of the sync process; which includes a report message, the total number of updated, created, -failed, processed types and the processing time of the last sync batch in different time units and in a -human-readable format. - -````java -final TypeSyncStatistics stats = syncStatisticsStage.toCompletebleFuture().join(); -stats.getReportMessage(); -/*"Summary: 2000 types were processed in total (1000 created, 995 updated, 5 failed to sync)."*/ -```` - -__Note__ The statistics object contains the processing time of the last batch only. This is due to two reasons: - - 1. The sync processing time should not take into account the time between supplying batches to the sync. - 2. It is not known by the sync which batch is going to be the last one supplied. - -#### Important to Note -1. If two matching `fieldDefinition`s (old and new) on the matching `type`s (old and new) have a different `FieldType`, the sync will -**remove** the existing `fieldDefinition` and then **add** a new `fieldDefinition` with the new `FieldType`. - -2. The `fieldDefinition` with missing `fieldType` (is `null`) will not be synced. - -#### More examples of how to use the sync - - 1. [Sync from another CTP project as a source](#todo). - 2. [Sync from an external source](#todo). - -*Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* - -### Build all update actions - -A utility method provided by the library to compare a `Type` with a new `TypeDraft` and results in a list of type update actions. -```java -List updateActions = TypeSyncUtils.buildActions(type, typeDraft, typeSyncOptions); -``` - -### Build particular update action(s) - -Utility methods provided by the library to compare the specific fields of a `Type` and a new `TypeDraft`, and in turn builds - the update action. One example is the `buildChangeNameUpdateAction` which compares names: -````java -Optional updateAction = TypeUpdateActionUtils.buildChangeNameUpdateAction(oldType, typeDraft); -```` -More examples of those utils for different types can be found [here](#todo). - -## Migration Guide - -The type-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with -any HTTP client module. The default one is `commercetools-http-client`. - -```xml - - - LATEST - - - - - com.commercetools.sdk - commercetools-http-client - ${commercetools.version} - - - com.commercetools.sdk - commercetools-sdk-java-api - ${commercetools.version} - - - -``` - -### Client configuration and creation - -For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. -If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). - -### Signature of TypeSyncOptions - -As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `TypeDraft`, `Type` and `TypeUpdateAction` from `package com.commercetools.api.models.type.*` - -> Note: Type `UpdateAction` has changed to `TypeUpdateAction`. Make sure you create and supply a specific TypeUpdateAction in `beforeUpdateCallback`. For that you can use the [library-utilities](#todo) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): - -```java -// Example: Create a type update action to change name taking the 'newName' of the typeDraft - final Function changeNameBeforeUpdateAction = - (newName) -> TypeChangeNameAction.builder().name(newName).build(); - -// Add the change name action to the list of update actions before update is executed - final TriFunction< - List, TypeDraft, Type, List> - beforeUpdateTypeCallback = - (updateActions, newTypeDraft, oldType) -> { - final TypeUpdateAction beforeUpdateAction = - changeNameBeforeUpdateAction.apply(newTypeDraft.getName()); - updateActions.add(beforeUpdateAction); - return updateActions; - }; -``` - -### Build TypeDraft (syncing from external project) - -The type-sync expects a list of `TypeDraft`s to process. If you use java-sync-library to sync your types from any external system into a commercetools platform project you have to convert your data into CTP compatible `TypeDraft` type. This was done in previous version using `DraftBuilder`s. -The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: - -```java -// TypeDraftBuilder in v1 takes parameters 'key', 'name' and a set of 'resourceTypeIds' -final TypeDraft typeDraft = - TypeDraftBuilder - .of("type-key", ofEnglish("name"), ResourceTypeIdsSetBuilder.of().addCategories().build()) - .build(); - -// TypeDraftBuilder in v2. 'resourceTypeIds' is a list - TypeDraftBuilder.of() - .key("type-key") - .name(LocalizedString.ofEnglish("name")) - .resourceTypeIds(ResourceTypeId.CATEGORY) - .build(); -``` -For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). - -### Query for Types (syncing from CTP project) - -If you sync types between different commercetools projects you have to transform `Type` into `TypeDraft`. -However, if you need to query `Types` from a commercetools project instead of passing `TypeQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. -Here's an example: - -```java -// SDK v1: TypeQuery to fetch all types -final TypeQuery query = TypeQuery.of(); - -final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); - -// SDK v2: Create and execute query to fetch all types in one line -final TypePagedQueryResponse result = apiRoot.types().get().executeBlocking().getBody(); -``` -[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. - -### JVM-SDK-V2 migration guide - -On any other needs to migrate your project using jvm-sdk-v2 please refer to it's [Migration Guide](https://docs.commercetools.com/sdk/java-sdk-migrate). diff --git a/docs/usage/CART_DISCOUNT_SYNC.md b/docs/usage/CART_DISCOUNT_SYNC.md index 6b0d1e538e..a24cb85dab 100644 --- a/docs/usage/CART_DISCOUNT_SYNC.md +++ b/docs/usage/CART_DISCOUNT_SYNC.md @@ -1,16 +1,15 @@ # CartDiscount Sync The module used for importing/syncing CartDiscounts into a commercetools project. -It also provides utilities for generating update actions based on the comparison of a [CartDiscount](https://docs.commercetools.com/http-api-projects-cartDiscounts#cartdiscount) -against a [CartDiscountDraft](https://docs.commercetools.com/http-api-projects-cartDiscounts#cartdiscountdraft). +It also provides utilities for generating update actions based on the comparison of a [CartDiscount](https://docs.commercetools.com/api/projects/cartDiscounts#cartdiscount) +against a [CartDiscountDraft](https://docs.commercetools.com/api/projects/cartDiscounts#cartdiscountdraft). - - [Usage](#usage) - [Prerequisites](#prerequisites) - - [SphereClient](#sphereclient) + - [ProjectApiRoot](#projectapiroot) - [Required Fields](#required-fields) - [Reference Resolution](#reference-resolution) - [Syncing from a commercetools project](#syncing-from-a-commercetools-project) @@ -26,6 +25,11 @@ against a [CartDiscountDraft](https://docs.commercetools.com/http-api-projects-c - [More examples of how to use the sync](#more-examples-of-how-to-use-the-sync) - [Build all update actions](#build-all-update-actions) - [Build particular update action(s)](#build-particular-update-actions) +- [Migration Guide](#migration-guide) + - [Client configuration and creation](#client-configuration-and-creation) + - [Signature of CartDiscountSyncOptions](#signature-of-cartdiscountsyncoptions) + - [Build CartDiscountDraft (syncing from external project)](#build-cartdiscountdraft-syncing-from-external-project) + - [Query for Cart Discounts (syncing from CTP project)](#query-for-cart-discounts-syncing-from-ctp-project) - [Caveats](#caveats) @@ -34,15 +38,20 @@ against a [CartDiscountDraft](https://docs.commercetools.com/http-api-projects-c ### Prerequisites -#### SphereClient +#### ProjectApiRoot -Use the [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/9.2.3/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L45) which apply the best practices for `SphereClient` creation. -If you have custom requirements for the sphere client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). +Use the [ClientConfigurationUtils](/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java) which apply the best practices for `ProjectApiRoot` creation. +To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](https://github.com/commercetools/commercetools-sdk-java-v2/blob/main/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/oauth2/ClientCredentialsBuilder.java) +If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). ````java -final SphereClientConfig clientConfig = SphereClientConfig.of("project-key", "client-id", "client-secret"); - -final SphereClient sphereClient = ClientConfigurationUtils.createClient(clientConfig); +final ClientCredentials clientCredentials = + new ClientCredentialsBuilder() + .withClientId("client-id") + .withClientSecret("client-secret") + .withScopes("scopes") + .build(); +final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); ```` #### Required Fields @@ -51,7 +60,7 @@ The following fields are **required** to be set in, otherwise, they won't be mat |Draft|Required Fields|Note| |---|---|---| -| [CartDiscountDraft](https://docs.commercetools.com/http-api-projects-cartDiscounts#cartdiscountdraft). | `key` | Also, the cart discounts in the target project are expected to have the `key` fields set. | +| [CartDiscountDraft](https://docs.commercetools.com/api/projects/cartDiscounts#cartdiscountdraft) | `key` | Also, the cart discounts in the target project are expected to have the `key` fields set. | #### Reference Resolution @@ -67,28 +76,24 @@ Therefore, in order to resolve the actual ids of those references in the sync pr ##### Syncing from a commercetools project -When syncing from a source commercetools project, you can use [`toCartDiscountDrafts`](https://commercetools.github.io/commercetools-sync-java/v/9.2.3/com/commercetools/sync/cartdiscounts/utils/CartDiscountTransformUtils.html#toCartDiscountDrafts-java.util.List-) +When syncing from a source commercetools project, you can use [`toCartDiscountDrafts`](#todo) method that transforms(resolves by querying and caching key-id pairs) and maps from a `CartDiscount` to `CartDiscountDraft` using cache in order to make them ready for reference resolution by the sync, for example: ````java -// Build a CartDiscountQuery for fetching cart discounts from a source CTP project without any references expanded for the sync: -final CartDiscountQuery cartDiscountQuery = CartDiscountQuery.of(); +// Build a ByProjectKeyCartDiscountsGet for fetching cart discounts from a source CTP project without any references expanded for the sync: +final ByProjectKeyCartDiscountsGet byProjectKeyCartDiscountsGet = client.cartDiscounts().get(); // Query all cart discounts (NOTE this is just for example, please adjust your logic) -final List cartDiscounts = - CtpQueryUtils - .queryAll(sphereClient, cartDiscountQuery, Function.identity()) - .thenApply(fetchedResources -> fetchedResources - .stream() - .flatMap(List::stream) - .collect(Collectors.toList())) +final List cartDiscounts = QueryUtils.queryAll(byProjectKeyCartDiscountsGet, + (cartDiscounts) -> cartDiscounts) + .thenApply(lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())) .toCompletableFuture() .join(); ```` In order to transform and map the `CartDiscount` to `CartDiscountDraft`, -Utils method `toCartDiscountDrafts` requires `sphereClient`, implementation of [`ReferenceIdToKeyCache`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ReferenceIdToKeyCache.java) and `cartDiscounts` as parameters. -For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/CaffeineReferenceIdToKeyCacheImpl.java). +Utils method `toCartDiscountDrafts` requires `projectApiRoot`, implementation of [`ReferenceIdToKeyCache`](#todo) and `cartDiscounts` as parameters. +For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](#todo). Example as shown below: ````java @@ -104,25 +109,31 @@ CompletableFuture> cartDiscountDrafts = CartDiscountTran - When syncing from an external resource, `ResourceIdentifier`s with their `key`s have to be supplied as following example: ```` java -final CartDiscountDraft cartDiscountDraft = CartDiscountDraftBuilder - .of("cartPredicate", - LocalizedString.ofEnglish("foo"), - true, - "0.1", - ShippingCostTarget.of(), - CartDiscountValue.ofAbsolute(MoneyImpl.of(10, DefaultCurrencyUnits.EUR))) - .key("cart-discount-key") - .custom(CustomFieldsDraft.ofTypeKeyAndJson("type-key", emptyMap())) // note that custom type provided with key - .build(); +final CartDiscountDraft cartDiscountDraft = CartDiscountDraftBuilder.of() + .cartPredicate("cartPredicate") + .name(LocalizedString.ofEnglish("foo")) + .requiresDiscountCode(true) + .sortOrder("0.1") + .target(CartDiscountTargetBuilder::shippingBuilder) + .value(CartDiscountValueAbsoluteDraftBuilder.of() + .money( + MoneyBuilder.of() + .centAmount(10L) + .currencyCode(DefaultCurrencyUnits.EUR.getCurrencyCode()) + .build()) + .build()) + .key("cart-discount-key") + .custom(CustomFieldsDraftBuilder.of().type(typeResourceIdentifierBuilder -> typeResourceIdentifierBuilder.key("type-key")).fields(fieldContainerBuilder -> fieldContainerBuilder.values(emptyMap())).build()) // note that custom type provided with key + .build(); ```` #### SyncOptions -After the `sphereClient` is set up, a `CartDiscountSyncOptions` should be built as follows: +After the `ProjectApiRoot` is set up, a `CartDiscountSyncOptions` should be built as follows: ````java // instantiating a CartDiscountSyncOptions -final CartDiscountSyncOptions cartDiscountSyncOptions = CartDiscountSyncOptionsBuilder.of(sphereClient).build(); +final CartDiscountSyncOptions cartDiscountSyncOptions = CartDiscountSyncOptionsBuilder.of(projectApiRoot).build(); ```` `SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. @@ -158,7 +169,7 @@ following context about the warning message: ````java final Logger logger = LoggerFactory.getLogger(CartDiscountSync.class); final CartDiscountSyncOptions cartDiscountSyncOptions = CartDiscountSyncOptionsBuilder - .of(sphereClient) + .of(projectApiRoot) .warningCallback((syncException, draft, cartDiscount, updateActions) -> logger.warn(new SyncException("My customized message"), syncException)).build(); ```` @@ -174,14 +185,14 @@ update actions array with custom actions or discard unwanted actions. The callba ````java final TriFunction< - List>, CartDiscountDraft, CartDiscount, List>> + List, CartDiscountDraft, CartDiscount, List> beforeUpdateCartDiscountCallback = (updateActions, newCartDiscountDraft, oldCartDiscount) -> updateActions.stream() - .filter(updateAction -> !(updateAction instanceof ChangeCartPredicate)) + .filter(updateAction -> !(updateAction instanceof CartDiscountChangeCartPredicateAction)) .collect(Collectors.toList()); final CartDiscountSyncOptions cartDiscountSyncOptions = - CartDiscountSyncOptionsBuilder.of(sphereClient).beforeUpdateCallback(beforeUpdateCartDiscountCallback).build(); + CartDiscountSyncOptionsBuilder.of(projectApiRoot).beforeUpdateCallback(beforeUpdateCartDiscountCallback).build(); ```` ##### beforeCreateCallback @@ -189,7 +200,7 @@ During the sync process, if a cart discount draft should be created, this callba * cart discount draft that should be created -Please refer to [example in product sync document](PRODUCT_SYNC.md#example-set-publish-stage-if-category-references-of-given-product-draft-exists). +Please refer to [example in product sync document](PRODUCT_SYNC.md#beforeCreateCallback). ##### batchSize A number that could be used to set the batch size with which cart discounts are fetched and processed, @@ -197,7 +208,7 @@ as cart discounts are obtained from the target project on the commercetools plat ````java final CartDiscountSyncOptions cartDiscountSyncOptions = - CartDiscountSyncOptionsBuilder.of(sphereClient).batchSize(30).build(); + CartDiscountSyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); ```` ##### cacheSize @@ -208,7 +219,7 @@ which will improve the overall performance of the sync and commercetools API. Playing with this option can change the memory usage of the library. If it is not set, the default cache size is `10.000` for cart discount sync. ````java final CartDiscountSyncOptions cartDiscountSyncOptions = - CartDiscountSyncOptionsBuilder.of(sphereClient).cacheSize(5000).build(); + CartDiscountSyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); ```` ### Running the sync @@ -239,8 +250,8 @@ __Note__ The statistics object contains the processing time of the last batch on #### More examples of how to use the sync - 1. [Sync from another CTP project as a source](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/ctpprojectsource/cartDiscounts/CartDiscountSyncIT.java). - 2. [Sync from an external source](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/externalsource/cartDiscounts/CartDiscountSyncIT.java). + 1. [Sync from another CTP project as a source](#todo). + 2. [Sync from an external source](#todo). *Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* @@ -248,7 +259,7 @@ __Note__ The statistics object contains the processing time of the last batch on A utility method provided by the library to compare a `CartDiscount` with a new `CartDiscountDraft` and results in a list of cart discount update actions. ```java -List> updateActions = CartDiscountSyncUtils.buildActions(cartDiscount, cartDiscountDraft, cartDiscountSyncOptions); +List updateActions = CartDiscountSyncUtils.buildActions(cartDiscount, cartDiscountDraft, cartDiscountSyncOptions); ``` ### Build particular update action(s) @@ -256,9 +267,124 @@ List> updateActions = CartDiscountSyncUtils.buildActi Utility methods provided by the library to compare the specific fields of a `CartDiscount` and a new `CartDiscountDraft`, and in turn builds the update action. One example is the `buildChangeNameUpdateAction` which compares names: ````java -Optional> updateAction = CartDiscountUpdateActionUtils.buildChangeNameAction(oldCartDiscount, cartDiscountDraft); +Optional updateAction = CartDiscountUpdateActionUtils.buildChangeNameAction(oldCartDiscount, cartDiscountDraft); ```` -More examples of those utils for different cart discounts can be found [here](https://github.com/commercetools/commercetools-sync-java/tree/master/src/test/java/com/commercetools/sync/cartdiscounts/utils/CartDiscountUpdateActionUtilsTest.java). +More examples of those utils for different cart discounts can be found [here](#todo). + +## Migration Guide + +The cart-discount-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with +any HTTP client module. The default one is `commercetools-http-client`. + +```xml + + + LATEST + + + + + com.commercetools.sdk + commercetools-http-client + ${commercetools.version} + + + com.commercetools.sdk + commercetools-sdk-java-api + ${commercetools.version} + + + +``` + +### Client configuration and creation + +For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). + +### Signature of CartDiscountSyncOptions + +As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `CartDiscount`, `CartDiscountDraft` and `CartDiscountUpdateAction` from `package com.commercetools.api.models.cart_discount.*` + +> Note: Type `UpdateAction` has changed to `CartDiscountUpdateAction`. Make sure you create and supply a specific CartDiscountUpdateAction in `beforeUpdateCallback`. For that you can use the [library-utilities](#todo) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): + +```java +// Example: Create a cart discount update action to change name taking the 'newName' of the cartDiscountDraft + final Function createBeforeUpdateAction = + (newName) -> CartDiscountChangeNameAction.builder().name(newName).build(); + +// Add the change name action to the list of update actions before update is executed + final TriFunction< + List, CartDiscountDraft, CartDiscount, List> + beforeUpdateCartDiscountCallback = + (updateActions, newCartDiscountDraft, oldCartDiscount) -> { + final CartDiscountUpdateAction beforeUpdateAction = + createBeforeUpdateAction.apply(newCartDiscountDraft.getName()); + updateActions.add(beforeUpdateAction); + return updateActions; + }; +``` + +### Build CartDiscountDraft (syncing from external project) + +The cartDiscount-sync expects a list of `CartDiscountDraft`s to process. If you use java-sync-library to sync your cart discounts from any external system into a commercetools platform project you have to convert your data into CTP compatible `CartDiscountDraft` type. This was done in previous version using `DraftBuilder`s. +The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: + +```java +// CartDiscountDraftBuilder in v1 takes parameters 'name', 'cartPredicate', 'value', 'target', 'sortOrder', 'requiresDiscountCode' +final CartDiscountDraft cartDiscountDraft = + CartDiscountDraftBuilder.of( + ofEnglish("name"), + "1 = 1", + CartDiscountValue.ofAbsolute(MoneyImpl.of(20, EUR)), + "sku = \"0123456789\" or sku = \"0246891213\"", + "0.2", + false) + .key("key") + .active(false) + .build() + +// CartDiscountDraftBuilder in v2 +final CartDiscountDraft cartDiscountDraft = + CartDiscountDraftBuilder.of() + .name(ofEnglish("name")) + .cartPredicate("1 = 1") + .value( + CartDiscountValueAbsoluteDraftBuilder.of() + .money( + CentPrecisionMoneyBuilder.of() + .centAmount(20L) + .fractionDigits(0) + .currencyCode(DefaultCurrencyUnits.EUR.getCurrencyCode()) + .build() + ) + .build() + ) + .target("sku = \"0123456789\" or sku = \"0246891213\"") + .sortOrder("0.2") + .requiresDiscountCode(false) + .key("key") + .isActive(false) + .build(); +``` +For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). + +### Query for Cart Discounts (syncing from CTP project) + +If you sync cart discounts between different commercetools projects you probably use [CartDiscountTransformUtils#toCartDiscountDrafts](#todo) to transform `CartDiscount` into `CartDiscountDraft` which can be used by the cartDiscount-sync. +However, if you need to query `Cart Discounts` from a commercetools project instead of passing `CartDiscountQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. +Here's an example: + +```java +// SDK v1: CartDiscountQuery to fetch all cart discounts +final CartDiscountQuery query = CartDiscountQuery.of(); + +final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); + +// SDK v2: Create and execute query to fetch all cart discounts in one line +final CartDiscountPagedQueryResponse result = apiRoot.cart discounts().get().executeBlocking().getBody(); +``` +[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. ## Caveats 1. Syncing cart discounts with a `CartDiscountValue` of type `giftLineItem` is not supported yet. [#411](https://github.com/commercetools/commercetools-sync-java/issues/411). diff --git a/docs/usage/CATEGORY_SYNC.md b/docs/usage/CATEGORY_SYNC.md index 8cda45ee80..8c5a80d802 100644 --- a/docs/usage/CATEGORY_SYNC.md +++ b/docs/usage/CATEGORY_SYNC.md @@ -1,18 +1,18 @@ # Category Sync Module used for importing/syncing Categories into a commercetools project. -It also provides utilities for generating update actions based on the comparison of a [Category](https://docs.commercetools.com/http-api-projects-categories.html#category) -against a [CategoryDraft](https://docs.commercetools.com/http-api-projects-categories.html#categorydraft). +It also provides utilities for generating update actions based on the comparison of a [Category](https://docs.commercetools.com/api/projects/categories#category) +against a [CategoryDraft](https://docs.commercetools.com/api/projects/categories#categorydraft). - [Usage](#usage) - [Prerequisites](#prerequisites) - - [SphereClient](#sphereclient) + - [ProjectApiRoot](#projectapiroot) - [Required Fields](#required-fields) - [Reference Resolution](#reference-resolution) - - [Persistence of category Drafts with irresolvable parent](#persistence-of-category-drafts-with-irresolvable-parent) + - [Persistence of Category Drafts with irresolvable parent](#persistence-of-category-drafts-with-irresolvable-parent) - [Syncing from a commercetools project](#syncing-from-a-commercetools-project) - [Syncing from an external resource](#syncing-from-an-external-resource) - [SyncOptions](#syncoptions) @@ -26,7 +26,12 @@ against a [CategoryDraft](https://docs.commercetools.com/http-api-projects-categ - [More examples of how to use the sync](#more-examples-of-how-to-use-the-sync) - [Build all update actions](#build-all-update-actions) - [Build particular update action(s)](#build-particular-update-actions) -- [Caveats](#caveats) +- [Migration Guide](#migration-guide) + - [Client configuration and creation](#client-configuration-and-creation) + - [Signature of CategorySyncOptions](#signature-of-categorysyncoptions) + - [Build CategoryDraft (syncing from external project)](#build-categorydraft-syncing-from-external-project) + - [Query for Categories (syncing from CTP project)](#query-for-categories-syncing-from-ctp-project) + - [JVM-SDK-V2 migration guide](#jvm-sdk-v2-migration-guide) @@ -34,15 +39,20 @@ against a [CategoryDraft](https://docs.commercetools.com/http-api-projects-categ ### Prerequisites -#### SphereClient +#### ProjectApiRoot -Use the [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/9.2.3/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L45) which apply the best practices for `SphereClient` creation. -If you have custom requirements for the sphere client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). +Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](#todo) +If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). ````java -final SphereClientConfig clientConfig = SphereClientConfig.of("project-key", "client-id", "client-secret"); - -final SphereClient sphereClient = ClientConfigurationUtils.createClient(clientConfig); +final ClientCredentials clientCredentials = + new ClientCredentialsBuilder() + .withClientId("client-id") + .withClientSecret("client-secret") + .withScopes("scopes") + .build(); +final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); ```` #### Required Fields @@ -51,7 +61,7 @@ The following fields are **required** to be set in, otherwise they won't be matc |Draft|Required Fields|Note| |---|---|---| -| [CategoryDraft](https://docs.commercetools.com/http-api-projects-categories.html#categorydraft) | `key` | Also, the categories in the target project are expected to have the `key` fields set. | +| [CategoryDraft](https://docs.commercetools.com/api/projects/categories#categorydraft) | `key` | Also, the categories in the target project are expected to have the `key` fields set. | #### Reference Resolution @@ -59,20 +69,20 @@ In commercetools, a reference can be created by providing the key instead of the When the reference key is provided with a `ResourceIdentifier`, the sync will resolve the resource with the given key and use the ID of the found resource to create or update a reference. Therefore, in order to resolve the actual ids of those references in sync process, `ResourceIdentifier`s with their `key`s have to be supplied. -|Reference Field|Type| -|:---|:---| -| `parent` | ResourceIdentifier to a Category | -| `custom.type` | ResourceIdentifier to a Type | -| `assets.custom.type` | ResourceIdentifier to a Type | +|Reference Field| Type | +|:---|:---------------------------------| +| `parent` | CategoryResourceIdentifier | +| `custom.type` | TypeResourceIdentifier | +| `assets.custom.type` | TypeResourceIdentifier | > Note that a reference without the key field will be considered as existing resource on the target commercetools project and the library will issue an update/create an API request without reference resolution. -##### Persistence of category Drafts with irresolvable parent +##### Persistence of Category Drafts with irresolvable parent -A categorydraft X could have a parent Category Y. But It could be that the parent Category Y is not supplied before X, +A CategoryDraft X could have a parent Category Y. But It could be that the parent Category Y is not supplied before X, which means the sync could fail to create/updating X. It could also be that Y is not supplied at all in this batch but at a later batch. -The library keeps track of such "referencing" category Drafts like X and persists them in storage +The library keeps track of such "referencing" Category Drafts like X and persists them in storage (**Commercetools platform `customObjects` in the target project** , in this case) to keep them and create/update them accordingly whenever the referenced drafts exist in the target project. @@ -130,33 +140,29 @@ Being persisted as `CustomObject` means that the referenced parent Category with } ``` -As soon, as the referenced parent Category draft is supplied to the sync, the draft will be created/updated and the +As soon, as the referenced parent Category Draft is supplied to the sync, the Category will be created/updated and the `CustomObject` will be removed from the target project. ##### Syncing from a commercetools project -When syncing from a source commercetools project, you can use [`toCategoryDrafts`](https://commercetools.github.io/commercetools-sync-java/v/9.2.3/com/commercetools/sync/categories/utils/CategoryTransformUtils.html#toCategoryDrafts-java.util.List-) +When syncing from a source commercetools project, you can use [`toCategoryDrafts`](#todo) method that transforms(resolves by querying and caching key-id pairs) and maps from a `Category` to `CategoryDraft` using cache in order to make them ready for reference resolution by the sync, for example: ````java -// Build a CategoryQuery for fetching categories from a source CTP project without any references expanded for the sync: -final CategoryQuery categoryQuery = CategoryQuery.of(); +// Build ByProjectKeyCategoriesGet for fetching categories from a source CTP project without any references expanded for the sync: +final ByProjectKeyCategoriesGet byProjectKeyCategoriesGet = client.categories().get(); // Query all categories (NOTE this is just for example, please adjust your logic) -final List categories = - CtpQueryUtils - .queryAll(sphereClient, categoryQuery, Function.identity()) - .thenApply(fetchedResources -> fetchedResources - .stream() - .flatMap(List::stream) - .collect(Collectors.toList())) - .toCompletableFuture() - .join(); +final List categories = QueryUtils.queryAll(byProjectKeyCategoriesGet, + (categories) -> categories) + .thenApply(lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())) + .toCompletableFuture() + .join(); ```` In order to transform and map the `Category` to `CategoryDraft`, -Utils method `toCategoryDrafts` requires `sphereClient`, implementation of [`ReferenceIdToKeyCache`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ReferenceIdToKeyCache.java) and `categories` as parameters. -For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/CaffeineReferenceIdToKeyCacheImpl.java). +Utils method `toCategoryDrafts` requires `projectApiRoot`, implementation of [`ReferenceIdToKeyCache`](#todo) and `categories` as parameters. +For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](#todo). Example as shown below: ````java @@ -164,7 +170,7 @@ Example as shown below: final ReferenceIdToKeyCache referenceIdToKeyCache = new CaffeineReferenceIdToKeyCacheImpl(); //For every reference fetch its key using id, cache it and map from Category to CategoryDraft. With help of the cache same reference keys can be reused. -CompletableFuture> categoryDrafts = CategoryTransformUtils.toCategoryDrafts(client, referenceIdToKeyCache, categories); +final CompletableFuture> categoryDrafts = CategoryTransformUtils.toCategoryDrafts(client, referenceIdToKeyCache, categories); ```` ##### Syncing from an external resource @@ -185,12 +191,38 @@ final CategoryDraft categoryDraft = .build(); ```` + +````java +final CustomFieldsDraft customFields = CustomFieldsDraftBuilder.of() + .type(TypeResourceIdentifierBuilder.of().key("type-key").build()) // note that custom type provided with key + .fields(FieldContainerBuilder.of().values(Collections.emptyMap()).build()) + .build(); + +final CategoryResourceIdentifier categoryResourceIdentifier = CategoryResourceIdentifierBuilder.of() + .key("category-key") + .build(); + +final CategoryDraft categoryDraft = CategoryDraftBuilder.of() + .key("category-key") + .slug(LocalizedString.of(Locale.ENGLISH, "category-slug")) + .name(LocalizedString.of(Locale.ENGLISH, "category-name")) + .description(LocalizedString.of(Locale.ENGLISH, "category-description")) + .externalId("external-id") + .metaDescription(LocalizedString.of(Locale.ENGLISH, "meta-description")) + .metaKeywords(LocalizedString.of(Locale.ENGLISH, "meta-keywords")) + .metaTitle(LocalizedString.of(Locale.ENGLISH, "meta-title")) + .orderHint("order-hint") + .custom(customFields) + .parent(categoryResourceIdentifier) + .build() +```` + #### SyncOptions -After the `sphereClient` is set up, a `CategorySyncOptions` should be built as follows: +After the `ProjectApiRoot` is set up, a `CategorySyncOptions` should be built as follows: ````java // instantiating a CategorySyncOptions -final CategorySyncOptions categorySyncOptions = CategorySyncOptionsBuilder.of(sphereClient).build(); +final CategorySyncOptions categorySyncOptions = CategorySyncOptionsBuilder.of(projectApiRoot).build(); ```` `SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. @@ -209,7 +241,7 @@ following context about the error-event: ````java final Logger logger = LoggerFactory.getLogger(CategorySync.class); final CategorySyncOptions categorySyncOptions = CategorySyncOptionsBuilder - .of(sphereClient) + .of(projectApiRoot) .errorCallback((syncException, draft, category, updateActions) -> logger.error(new SyncException("My customized message"), syncException)).build(); ```` @@ -226,7 +258,7 @@ following context about the warning message: ````java final Logger logger = LoggerFactory.getLogger(CategorySync.class); final CategorySyncOptions categorySyncOptions = CategorySyncOptionsBuilder - .of(sphereClient) + .of(projectApiRoot) .warningCallback((syncException, draft, category, updateActions) -> logger.warn(new SyncException("My customized message"), syncException)).build(); ```` @@ -241,15 +273,16 @@ update actions array with custom actions or discard unwanted actions. The callba * update actions that were calculated after comparing both ````java +// Example: Ignore update actions that change category name final TriFunction< - List>, CategoryDraft, Category, List>> + List, CategoryDraft, Category, List> beforeUpdateCategoryCallback = (updateActions, newCategoryDraft, oldCategory) -> updateActions.stream() - .filter(updateAction -> !(updateAction instanceof RemoveAsset)) + .filter(updateAction -> !(updateAction instanceof CategoryChangeNameAction)) .collect(Collectors.toList()); final CategorySyncOptions categorySyncOptions = - CategorySyncOptionsBuilder.of(sphereClient).beforeUpdateCallback(beforeUpdateCategoryCallback).build(); + CategorySyncOptionsBuilder.of(projectApiRoot).beforeUpdateCallback(beforeUpdateCategoryCallback).build(); ```` ##### beforeCreateCallback @@ -258,18 +291,18 @@ the **_create_** request just before it is sent to commercetools platform. It c * category draft that should be created -Please refer to [example in product sync document](PRODUCT_SYNC.md#example-set-publish-stage-if-category-references-of-given-product-draft-exists). +Please refer to [example in product sync document](PRODUCT_SYNC.md#beforeCreateCallback). ##### batchSize A number that could be used to set the batch size with which categories are fetched and processed, as categories are obtained from the target project on commercetools platform in batches for better performance. The algorithm accumulates up to `batchSize` resources from the input list, then fetches the corresponding categories from the target project on commecetools platform in a single request. Playing with this option can slightly improve or -reduce processing speed. If it is not set, the default batch size is 50 for category sync. +reduce processing speed. If it is not set, the default batch size is **50** for category sync. ````java final CategorySyncOptions categorySyncOptions = - CategorySyncOptionsBuilder.of(sphereClient).batchSize(30).build(); + CategorySyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); ```` ##### cacheSize @@ -280,7 +313,7 @@ which will improve the overall performance of the sync and commercetools API. Playing with this option can change the memory usage of the library. If it is not set, the default cache size is `10.000` for category sync. ````java final CategorySyncOptions categorySyncOptions = - CategorySyncOptionsBuilder.of(sphereClient).cacheSize(5000).build(); + CategorySyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); ```` ### Running the sync @@ -310,8 +343,8 @@ __Note__ The statistics object contains the processing time of the last batch on ##### More examples of how to use the sync -1. [Sync from another CTP project as a source](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/ctpprojectsource/categories/CategorySyncIT.java). -2. [Sync from an external source](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/externalsource/categories/CategorySyncIT.java). +1. [Sync from another CTP project as a source](#todo). +2. [Sync from an external source](#todo). *Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* @@ -319,11 +352,11 @@ __Note__ The statistics object contains the processing time of the last batch on A utility method provided by the library to compare a Category with a new CategoryDraft and results in a list of category update actions. ```java -List> updateActions = CategorySyncUtils.buildActions(category, categoryDraft, categorySyncOptions); +final List updateActions = CategorySyncUtils.buildActions(category, categoryDraft, categorySyncOptions); ``` Examples of its usage can be found in the tests -[here](https://github.com/commercetools/commercetools-sync-java/tree/master/src/test/java/com/commercetools/sync/categories/utils/CategorySyncUtilsTest.java). +[here](#todo). ### Build particular update action(s) @@ -331,10 +364,105 @@ Examples of its usage can be found in the tests Utility methods provided by the library to compare the specific fields of a Category and a new CategoryDraft, and in turn, build the update action. One example is the `buildChangeNameUpdateAction` which compares names: ````java -Optional> updateAction = buildChangeNameUpdateAction(oldCategory, categoryDraft); +final Optional updateAction = buildChangeNameUpdateAction(oldCategory, categoryDraft); ```` -More examples of those utils for different fields can be found [here](https://github.com/commercetools/commercetools-sync-java/blob/master/src/test/java/com/commercetools/sync/categories/utils/CategoryUpdateActionUtilsTest.java). +More examples of those utils for different fields can be found [here](#todo). + +## Migration Guide + +The category-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with +any HTTP client module. The default one is `commercetools-http-client`. + +```xml + + + LATEST + + + + + com.commercetools.sdk + commercetools-http-client + ${commercetools.version} + + + com.commercetools.sdk + commercetools-sdk-java-api + ${commercetools.version} + + + +``` + +### Client configuration and creation + +For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). + +### Signature of CategorySyncOptions + +As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `CategoryDraft`, `Category` and `CategoryUpdateAction` from `package com.commercetools.api.models.category.*` + +> Note: Type `UpdateAction` has changed to `CategoryUpdateAction`. Make sure you create and supply a specific CategoryUpdateAction in `beforeUpdateCallback`. For that you can use the [library-utilities](#todo) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): + +```java +// Example: Create a category update action to change name taking the 'newName' of the categoryDraft + final Function createBeforeUpdateAction = + (newName) -> CategoryChangeNameAction.builder().name(newName).build(); + +// Add the change name action to the list of update actions before update is executed + final TriFunction< + List, CategoryDraft, Category, List> + beforeUpdateCategoryCallback = + (updateActions, newCategoryDraft, oldCategory) -> { + final CategoryUpdateAction beforeUpdateAction = + createBeforeUpdateAction.apply(newCategoryDraft.getName()); + updateActions.add(beforeUpdateAction); + return updateActions; + }; +``` + +### Build CategoryDraft (syncing from external project) + +The category-sync expects a list of `CategoryDraft`s to process. If you use java-sync-library to sync your categories from any external system into a commercetools platform project you have to convert your data into CTP compatible `CategoryDraft` type. This was done in previous version using `DraftBuilder`s. +The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: + +```java +// CategoryDraftBuilder in v1 takes parameters 'name' and 'slug' +final CategoryDraft categoryDraft = + CategoryDraftBuilder + .of(ofEnglish("name"), ofEnglish("slug")) + .key("category-key") + .build(); + +// CategoryDraftBuilder in v2 +final CategoryDraft categoryDraft = + CategoryDraftBuilder + .of() + .name(LocalizedString.ofEnglish("name")) + .slug(LocalizedString.ofEnglish("slug")) + .key("category-key") + .build(); +``` +For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). + +### Query for Categories (syncing from CTP project) + +If you sync categories between different commercetools projects you probably use [CategoryTransformUtils#toCategoryDrafts](#todo) to transform `Category` into `CategoryDraft` which can be used by the category-sync. +However, if you need to query `Categories` from a commercetools project instead of passing `CategoryQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. +Here's an example: + +```java +// SDK v1: CategoryQuery to fetch all categories +final CategoryQuery query = CategoryQuery.of(); + +final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); + +// SDK v2: Create and execute query to fetch all categories in one line +final CategoryPagedQueryResponse result = apiRoot.categories().get().executeBlocking().getBody(); +``` +[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. +### JVM-SDK-V2 migration guide -## Caveats -1. The library will sync all field types of custom fields, except `ReferenceType`. [#87](https://github.com/commercetools/commercetools-sync-java/issues/87). +On any other needs to migrate your project using jvm-sdk-v2 please refer to it's [Migration Guide](https://docs.commercetools.com/sdk/java-sdk-migrate). diff --git a/docs/usage/CLEANUP_GUIDE.md b/docs/usage/CLEANUP_GUIDE.md index e81f147a58..eeba9d3bbf 100644 --- a/docs/usage/CLEANUP_GUIDE.md +++ b/docs/usage/CLEANUP_GUIDE.md @@ -1,30 +1,3 @@ # Cleanup of old unresolved reference custom objects -For some references such as state transitions,product references and category references, the library keeps tracks -of unresolved drafts and persists them in commercetools custom objects and create/update them accordingly whenever -the referenced drafts exist in the target project. - -It also means that created data might be never resolved. In this case keeping the old custom objects around forever - can negatively influence the performance of your project and the time it takes to restore it from a backup. So deleting unused data ensures the best performance for your project. - -For the cleanup, commercetools-sync-java library exposes a ready to use method so that all custom objects created by the library can be cleaned up on demand. - -The cleanup can be defined with the parameter `deleteDaysAfterLastModification` (in days) of object creation. For - example, if you configure the `deleteDaysAfterLastModification` parameter to 30 days, cleanup method will delete the custom objects which haven't been modified in the last 30 days. -Additionally, an error callback could be configured to consume the error, that is called `errorCallback` whenever an error event occurs during the sync process. - -````java -final CleanupUnresolvedReferenceCustomObjects.Statistics statistics = - CleanupUnresolvedReferenceCustomObjects.of(sphereClient) - .errorCallback(throwable -> logger.error("Unexcepted error.", throwable)) - .cleanup(30) - .join(); -```` - -The result of the previous code snippet is a `Statistics` object that contains all the statistics of the cleanup process. That includes a report message, the total number of deleted and failed custom objects. - -````java -statistics.getReportMessage(); // Summary: 100 custom objects were deleted in total (1 failed to delete). -statistics.getTotalDeleted(); // Returns 100 -statistics.getTotalFailed(); // Returns 1 -```` +TODO diff --git a/docs/usage/CUSTOMER_SYNC.md b/docs/usage/CUSTOMER_SYNC.md index 04bba47b32..0d4845fedf 100644 --- a/docs/usage/CUSTOMER_SYNC.md +++ b/docs/usage/CUSTOMER_SYNC.md @@ -7,10 +7,9 @@ against a [CustomerDraft](https://docs.commercetools.com/api/projects/customers# - - [Usage](#usage) - [Prerequisites](#prerequisites) - - [SphereClient](#sphereclient) + - [ProjectApiRoot](#projectapiroot) - [Required Fields](#required-fields) - [Reference Resolution](#reference-resolution) - [Syncing from a commercetools project](#syncing-from-a-commercetools-project) @@ -33,15 +32,20 @@ against a [CustomerDraft](https://docs.commercetools.com/api/projects/customers# ## Usage ### Prerequisites -#### SphereClient +#### ProjectApiRoot -Use the [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/9.2.3/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L45) which apply the best practices for `SphereClient` creation. -If you have custom requirements for the sphere client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). +Use the [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/java-sdk-v2-product-sync-migration/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java) which apply the best practices for `ProjectApiRoot` creation. +To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](https://github.com/commercetools/commercetools-sdk-java-v2/blob/main/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/oauth2/ClientCredentialsBuilder.java) +If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). ````java -final SphereClientConfig clientConfig = SphereClientConfig.of("project-key", "client-id", "client-secret"); - -final SphereClient sphereClient = ClientConfigurationUtils.createClient(clientConfig); +final ClientCredentials clientCredentials = + new ClientCredentialsBuilder() + .withClientId("client-id") + .withClientSecret("client-secret") + .withScopes("scopes") + .build(); +final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); ```` #### Required Fields @@ -51,7 +55,7 @@ The following fields are **required** to be set in, otherwise, they won't be mat |Draft|Required Fields|Note| |---|---|---| | [CustomerDraft](https://docs.commercetools.com/api/projects/customers#customerdraft) | `key` | Also, the customers in the target project are expected to have the `key` fields set. | -| [CustomerDraft](https://docs.commercetools.com/api/projects/customers#customerdraft) | `address.key` | Every customer [Address](https://docs.commercetools.com/api/types#address) needs a unique key to match the existing `Address` with the new Address. | +| [CustomerDraft](https://docs.commercetools.com/api/projects/customers#customerdraft) | `address.key` | Every customer [BaseAddress](https://docs.commercetools.com/api/types#ctp:api:type:BaseAddress) needs a unique key to match the existing `Address` with the new `AddressDraft`. | #### Reference Resolution @@ -61,35 +65,31 @@ Therefore, in order to resolve the actual ids of those references in the sync pr |Reference Field|Type| |:---|:---| -| `customerGroup` | ResourceIdentifier to a CustomerGroup | -| `stores` | Set of ResourceIdentifier to a Store | -| `custom.type` | ResourceIdentifier to a Type | +| `customerGroup` | CustomerGroupResourceIdentifier | +| `stores` | List of StoreResourceIdentifier | +| `custom.type` | TypeResourceIdentifier | > Note that a reference without the key field will be considered as an existing resource on the target commercetools project and the library will issue an update/create an API request without reference resolution. ##### Syncing from a commercetools project -When syncing from a source commercetools project, you can use [`toCustomerDrafts`](https://commercetools.github.io/commercetools-sync-java/v/9.2.3/com/commercetools/sync/customers/utils/CustomerTransformUtils.html#toCustomerDrafts-java.util.List-) +When syncing from a source commercetools project, you can use [`toCustomerDrafts`](https://github.com/commercetools/commercetools-sync-java/blob/java-sdk-v2-product-sync-migration/src/main/java/com/commercetools/sync/customers/utils/CustomerTransformUtils.java#L42) method that transforms(resolves by querying and caching key-id pairs) and maps from a `Customer` to `CustomerDraft` using cache in order to make them ready for reference resolution by the sync, for example: ````java -// Build a CustomerQuery for fetching customers from a source CTP project without any references expanded for the sync: -final CustomerQuery customerQuery = CustomerQuery.of(); +// Build ByProjectKeyCustomersGet for fetching customers from a source CTP project without any references expanded for the sync: +final ByProjectKeyCustomersGet byProjectKeyCustomersGet = client.customers().get(); // Query all customers (NOTE this is just for example, please adjust your logic) -final List customers = - CtpQueryUtils - .queryAll(sphereClient, customerQuery, Function.identity()) - .thenApply(fetchedResources -> fetchedResources - .stream() - .flatMap(List::stream) - .collect(Collectors.toList())) - .toCompletableFuture() - .join(); +final List customers = QueryUtils.queryAll(byProjectKeyCustomersGet, + (customers) -> customers) + .thenApply(lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())) + .toCompletableFuture() + .join(); ```` In order to transform and map the `Customer` to `CustomerDraft`, -Utils method `toCustomerDrafts` requires `sphereClient`, implementation of [`ReferenceIdToKeyCache`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ReferenceIdToKeyCache.java) and `customers` as parameters. +Utils method `toCustomerDrafts` requires `projectApiRoot`, implementation of [`ReferenceIdToKeyCache`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ReferenceIdToKeyCache.java) and `customers` as parameters. For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/CaffeineReferenceIdToKeyCacheImpl.java). Example as shown below: @@ -106,22 +106,31 @@ CompletableFuture> customerDrafts = CustomerTransformUtils.t - When syncing from an external resource, `ResourceIdentifier`s with their `key`s have to be supplied as following example: ````java -final CustomerDraftBuilder customerDraftBuilder = CustomerDraftBuilder - .of("email@example.com", "password") - .customerGroup(ResourceIdentifier.ofKey("customer-group-key")) // note that customer group reference provided with key - .stores(asList(ResourceIdentifier.ofKey("store-key1"), - ResourceIdentifier.ofKey("store-key2"))) // note that store references provided with key - .custom(CustomFieldsDraft.ofTypeKeyAndJson("type-key", emptyMap())) // note that custom type provided with key - .addresses(singletonList(Address.of(CountryCode.DE).withKey("address-key-1"))) // note that addresses has to be provided with their keys - .key("customer-key"); +final CustomFieldsDraft customFields = CustomFieldsDraftBuilder.of() + .type(TypeResourceIdentifierBuilder.of().key("type-key").build()) // note that custom type provided with key + .fields(FieldContainerBuilder.of().values(Collections.emptyMap()).build()) + .build(); +final AddressDraft address = AddressDraftBuilder.of() + .key("address-key-1") // note that addresses has to be provided with their keys + .country("DE") + .build(); +final CustomerDraft customerDraft = CustomerDraftBuilder.of() + .email("email@example.com") + .password("password") + .key("customer-key") + .customerGroup(CustomerGroupRescourceIdentifierBuilder.of().key("customer-group-key").build()) // note that customergroup reference provided with key + .addresses(address) + .custom(customFields) + .stores(StoresResourceIdentifierBuilder.of().key("store-key1").build(), StoresResourceIdentifierBuilder.of().key("store-key2").build()) // note that store reference provided with key + .build(); ```` #### SyncOptions -After the `sphereClient` is set up, a `CustomerSyncOptions` should be built as follows: +After the `ProjectApiRoot` is set up, a `CustomerSyncOptions` should be built as follows: ````java // instantiating a CustomerSyncOptions -final CustomerSyncOptions customerSyncOptions = CustomerSyncOptionsBuilder.of(sphereClient).build(); +final CustomerSyncOptions customerSyncOptions = CustomerSyncOptionsBuilder.of(projectApiRoot).build(); ```` `SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. @@ -140,7 +149,7 @@ following context about the error-event: ````java final Logger logger = LoggerFactory.getLogger(CustomerSync.class); final CustomerSyncOptions customerSyncOptions = CustomerSyncOptionsBuilder - .of(sphereClient) + .of(projectApiRoot) .errorCallback((syncException, draft, customer, updateActions) -> logger.error(new SyncException("My customized message"), syncException)).build(); ```` @@ -157,8 +166,8 @@ following context about the warning message: ````java final Logger logger = LoggerFactory.getLogger(CustomerSync.class); final CustomerSyncOptions customerSyncOptions = CustomerSyncOptionsBuilder - .of(sphereClient) - .warningCallback((syncException, draft, customer, updateActions) -> + .of(projectApiRoot) + .warningCallback((syncException, draft, customer) -> logger.warn(new SyncException("My customized message"), syncException)).build(); ```` @@ -172,15 +181,16 @@ update actions array with custom actions or discard unwanted actions. The callba * update actions that were calculated after comparing both ````java -final TriFunction>, CustomerDraft, Customer, - List>> beforeUpdateCallback, = +// Example: Ignore update actions which contain setting of lastName action +final TriFunction, CustomerDraft, Customer, + List> beforeUpdateCallback, = (updateActions, newCustomerDraft, oldCustomer) -> updateActions .stream() - .filter(updateAction -> !(updateAction instanceof SetLastName)) + .filter(updateAction -> !(updateAction instanceof CustomerSetLastNameActionImpl)) .collect(Collectors.toList()); final CustomerSyncOptions customerSyncOptions = CustomerSyncOptionsBuilder - .of(CTP_CLIENT) + .of(projectApiRoot) .beforeUpdateCallback(beforeUpdateCallback) .build(); ```` @@ -199,7 +209,7 @@ from the target project on the commercetools platform in a single request. Playi ````java final CustomerSyncOptions customerSyncOptions = - CustomerSyncOptionsBuilder.of(sphereClient).batchSize(30).build(); + CustomerSyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); ```` ##### cacheSize @@ -211,7 +221,7 @@ Playing with this option can change the memory usage of the library. If it is no ````java final CustomerSyncOptions customerSyncOptions = - CustomerSyncOptionsBuilder.of(sphereClient).cacheSize(5000).build(); + CustomerSyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); ```` ### Running the sync @@ -249,14 +259,14 @@ __Note__ The statistics object contains the processing time of the last batch on ### Build all update actions A utility method provided by the library to compare a `Customer` to a new `CustomerDraft`. The results are collected in a list of customer update actions. ```java -List> updateActions = CustomerSyncUtils.buildActions(customer, customerDraft, customerSyncOptions); +List updateActions = CustomerSyncUtils.buildActions(customer, customerDraft, customerSyncOptions); ``` ### Build particular update action(s) The library provides utility methods to compare specific fields of a `Customer` and a new `CustomerDraft`, and builds the update action(s) as a result. One example is the `buildChangeEmailUpdateAction` which compare email addresses: ````java -Optional> updateAction = CustomerUpdateActionUtils.buildChangeEmailAction(oldCustomer, customerDraft); +Optional updateAction = CustomerUpdateActionUtils.buildChangeEmailUpdateAction(oldCustomer, customerDraft); ```` More examples for particular update actions can be found in the test scenarios for [CustomerUpdateActionUtils](https://github.com/commercetools/commercetools-sync-java/tree/master/src/test/java/com/commercetools/sync/customers/utils/CustomerUpdateActionUtilsTest.java) diff --git a/docs/usage/CUSTOM_OBJECT_SYNC.md b/docs/usage/CUSTOM_OBJECT_SYNC.md index 51ea152565..23aebe18fe 100644 --- a/docs/usage/CUSTOM_OBJECT_SYNC.md +++ b/docs/usage/CUSTOM_OBJECT_SYNC.md @@ -2,16 +2,15 @@ Module used for importing/syncing CustomObject into a commercetools project. It also provides utilities for correlating a custom object to a given custom object draft based on the -comparison of a [CustomObject](https://docs.commercetools.com/http-api-projects-custom-objects#customobject) -against a [CustomObjectDraft](https://docs.commercetools.com/http-api-projects-custom-objects#customobjectdraft). +comparison of a [CustomObject](https://docs.commercetools.com/api/projects/custom-objects#customobject) +against a [CustomObjectDraft](https://docs.commercetools.com/api/projects/custom-objects#customobjectdraft). - - [Usage](#usage) - [Prerequisites](#prerequisites) - - [SphereClient](#sphereclient) + - [ProjectApiRoot](#projectapiroot) - [Required Fields](#required-fields) - [SyncOptions](#syncoptions) - [errorCallback](#errorcallback) @@ -22,6 +21,12 @@ against a [CustomObjectDraft](https://docs.commercetools.com/http-api-projects-c - [cacheSize](#cachesize) - [Running the sync](#running-the-sync) - [More examples of how to use the sync](#more-examples-of-how-to-use-the-sync) +- [Migration Guide](#migration-guide) + - [Client configuration and creation](#client-configuration-and-creation) + - [Signature of CustomObjectSyncOptions](#signature-of-customobjectsyncoptions) + - [Build CustomObjectDraft (syncing from external project)](#build-customobjectdraft-syncing-from-external-project) + - [Query for CustomObjects](#query-for-customobjects) + - [JVM-SDK-V2 migration guide](#jvm-sdk-v2-migration-guide) @@ -29,15 +34,20 @@ against a [CustomObjectDraft](https://docs.commercetools.com/http-api-projects-c ### Prerequisites -#### SphereClient +#### ProjectApiRoot -Use the [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/9.2.3/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L45) which apply the best practices for `SphereClient` creation. -If you have custom requirements for the sphere client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). +Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](#todo) +If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). ````java -final SphereClientConfig clientConfig = SphereClientConfig.of("project-key", "client-id", "client-secret"); - -final SphereClient sphereClient = ClientConfigurationUtils.createClient(clientConfig); +final ClientCredentials clientCredentials = + new ClientCredentialsBuilder() + .withClientId("client-id") + .withClientSecret("client-secret") + .withScopes("scopes") + .build(); +final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); ```` #### Required Fields @@ -46,15 +56,15 @@ The following fields are **required** to be set in, otherwise, they won't be mat |Draft|Required Fields|Note| |---|---|---| -| [CustomObjectDraft](https://docs.commercetools.com/http-api-projects-custom-objects#customobjectdraft) | `key` | Also, the custom objects in the target project are expected to have the `key` fields set. | -| [CustomObjectDraft](https://docs.commercetools.com/http-api-projects-custom-objects#customobjectdraft) | `container` | Also, the custom objects in the target project are expected to have the `container` fields set. | +| [CustomObjectDraft](https://docs.commercetools.com/api/projects/custom-objects#customobjectdraft) | `key` | Also, the custom objects in the target project are expected to have the `key` fields set. | +| [CustomObjectDraft](https://docs.commercetools.com/api/projects/custom-objects#customobjectdraft) | `container` | Also, the custom objects in the target project are expected to have the `container` fields set. | #### SyncOptions -After the `sphereClient` is set up, a `CustomObjectSyncOptions` should be built as follows: +After the `projectApiRoot` is set up, a `CustomObjectSyncOptions` should be built as follows: ````java // instantiating a CustomObjectSyncOptions -final CustomObjectSyncOptions customObjectSyncOptions = CustomObjectSyncOptionsBuilder.of(sphereClient).build(); +final CustomObjectSyncOptions customObjectSyncOptions = CustomObjectSyncOptionsBuilder.of(projectApiRoot).build(); ```` `SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. @@ -68,12 +78,12 @@ following context about the error-event: * sync exception * custom object draft from the source * custom object of the target project (only provided if an existing custom object could be found) -* the update-actions, which failed (only provided if an existing custom object could be found) +* a fake list of update actions, as custom objects API does not provide update actions. [NoopResourceUpdateAction.java](#todo) ````java final Logger logger = LoggerFactory.getLogger(CustomObjectSync.class); final CustomObjectSyncOptions customObjectSyncOptions = CustomObjectSyncOptionsBuilder - .of(sphereClient) + .of(projectApiRoot) .errorCallback((syncException, draft, customObject, updateActions) -> logger.error(new SyncException("My customized message"), syncException)).build(); ```` @@ -90,8 +100,8 @@ following context about the warning message: ````java final Logger logger = LoggerFactory.getLogger(CustomObjectSync.class); final CustomObjectSyncOptions customObjectSyncOptions = CustomObjectSyncOptionsBuilder - .of(sphereClient) - .warningCallback((syncException, draft, customObject, updateActions) -> + .of(projectApiRoot) + .warningCallback((syncException, draft, customObject) -> logger.warn(new SyncException("My customized message"), syncException)).build(); ```` @@ -99,16 +109,16 @@ following context about the warning message: In theory, `CustomObjectSyncOptions` provides callback before update operation. User can customize their own callback and inject into sync options. However, in the actual case, `beforeUpdateCallback`is not triggered in the custom object sync process. When the new custom object draft has the same key and container as an existing custom object but different in custom object values, -the sync process automatically performs the update operation. The value of a corresponding custom object in the target project is overwritten. This approach is different from other resources and no update action is involved. +the sync process automatically performs the create/update operation. The value of a corresponding custom object in the target project is overwritten. This approach is different from other resources and no update action is involved. -No example is applicable. +Also see the API documentation of [Create-or-update-customobject](https://docs.commercetools.com/api/projects/custom-objects#create-or-update-customobject) ##### beforeCreateCallback During the sync process, if a custom object draft should be created, this callback can be used to intercept the **_create_** request just before it is sent to the commercetools platform. It contains the following information : * custom object draft that should be created -Please refer to [example in product sync document](PRODUCT_SYNC.md#example-set-publish-stage-if-category-references-of-given-product-draft-exists). +Please refer to [example in product sync document](PRODUCT_SYNC.md#beforecreatecallback). ##### batchSize A number that could be used to set the batch size with which custom objects are fetched and processed, @@ -116,7 +126,7 @@ as custom objects are obtained from the target project on the commercetools plat ````java final CustomObjectSyncOptions customObjectSyncOptions = - CustomObjectSyncOptionsBuilder.of(sphereClient).batchSize(30).build(); + CustomObjectSyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); ```` ##### cacheSize @@ -128,7 +138,7 @@ Playing with this option can change the memory usage of the library. If it is no ````java final CustomObjectSyncOptions customObjectSyncOptions = - CustomObjectSyncOptionsBuilder.of(sphereClient).cacheSize(5000).build(); + CustomObjectSyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); ```` ### Running the sync @@ -158,8 +168,91 @@ __Note__ The statistics object contains the processing time of the last batch on #### More examples of how to use the sync -- [Sync from an external source](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/externalsource/customobjects/CustomObjectSyncIT.java). +- [Sync from an external source](#todo). *Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* -More examples of those utils for different custom objects can be found [here](https://github.com/commercetools/commercetools-sync-java/tree/master/src/test/java/com/commercetools/sync/customobjects/utils/CustomObjectSyncUtilsTest.java). +More examples of those utils for different custom objects can be found [here](#todo). + +## Migration Guide + +The custom-object-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with +any HTTP client module. The default one is `commercetools-http-client`. + +```maven + // Sample maven pom.xml + + LATEST + + + + + com.commercetools.sdk + commercetools-http-client + ${commercetools.version} + + + com.commercetools.sdk + commercetools-sdk-java-api + ${commercetools.version} + + + +``` + +### Client configuration and creation + +For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). + +### Signature of CustomObjectSyncOptions + +As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `CustomObjectDraft`, `CustomObject` (without type parameter as in v1) from `package com.commercetools.api.models.custom_object.*` and `NoopResourceUpdateAction` which is a fake class representing resource without update actions like custom-object. + +> Note: Make sure `beforeUpdateCallback` isn't used as the sync will **not** trigger it in the process. +> Note: Further make sure on `errorCallback` to not operate on`NoopResourceUpdateAction`'s actions field as it is null. + +### Build CustomObjectDraft (syncing from external project) + +The custom-object-sync expects a list of `CustomObjectDraft`s to process. To sync your categories from anywhere (including other CTP project) into a commercetools platform project you have to convert your data into CTP compatible `CategoryDraft` type. This was done in previous version using `DraftBuilder`s. +The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: + +> Note: In v1 the value in CustomObjectDraft is of generic type and custom-object-sync was expecting `JsonNode` as value. This changed in V2 SDK and the sync-library, and value field is of type `Object` now. +```java +// CategoryDraft builder in v1 takes parameters 'container', 'key' and 'value' +final CustomObjectDraft cutomObjectDraft = + CustomObjectDraft.ofUnversionedUpsert( + "someContainer", + "someKey", + JsonNodeFactory.instance.objectNode().put("json-field", "json-value")); + +// CustomObjectDraftBuilder in v2 +final CustomObjectDraft newCustomObjectDraft = + CustomObjectDraftBuilder.of() + .container("someContainer") + .key("someKey") + .value("someValue") + .build(); +``` +For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). + +### Query for CustomObjects + +If you need to query `CustomObjects` from a commercetools project instead of passing `CustomObjectQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. +Here's an example: + +```java +// SDK v1: CategoryQuery to fetch all categories +final CustomObjectQuery query = CustomObjectQuery.ofJsonNode(); + +final PagedQueryResult> pagedQueryResult = sphereClient.executeBlocking(query); + +// SDK v2: Create and execute query to fetch all custom objects in one line +final CustomObjectPagedQueryResponse result = apiRoot.customObjects().get().executeBlocking().getBody(); +``` +[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. + +### JVM-SDK-V2 migration guide + +On any other needs to migrate your project using jvm-sdk-v2 please refer to it's [Migration Guide](https://docs.commercetools.com/sdk/java-sdk-migrate). + diff --git a/docs/usage/IMPORTANT_USAGE_TIPS.md b/docs/usage/IMPORTANT_USAGE_TIPS.md index 99ce4a4b9a..80a07f5763 100644 --- a/docs/usage/IMPORTANT_USAGE_TIPS.md +++ b/docs/usage/IMPORTANT_USAGE_TIPS.md @@ -1,25 +1,25 @@ # Important Usage Tips -#### Customized `SphereClient` Creation -When creating a customized `SphereClient` the following remarks should be considered: + + +- [Customized `ProjectApiRoot` Creation](#customized-projectapiroot-creation) +- [Tuning the Sync Process](#tuning-the-sync-process) -- Limit the number of concurrent requests done to CTP. This can be done by decorating the `sphereClient` with [QueueSphereClientDecorator](http://commercetools.github.io/commercetools-jvm-sdk/apidocs/io/sphere/sdk/client/QueueSphereClientDecorator.html) + + +#### Customized `ProjectApiRoot` Creation +When creating a customized `ProjectApiRoot` the following remarks should be considered: + +- Limit the number of concurrent requests done to CTP. This can be done by adding a QueueMiddleware to the ApiRootBuilder [QueueMiddleware](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/com/commercetools/docs/meta/ClientTuning.html#limit-requests) -- Retry on 5xx errors with a retry strategy. This can be achieved by decorating the `sphereClient` with the [RetrySphereClientDecorator](http://commercetools.github.io/commercetools-jvm-sdk/apidocs/io/sphere/sdk/client/RetrySphereClientDecorator.html) +- Retry on 5xx errors with a retry strategy. This can be achieved by adding a RetryRequestMiddleware to the ApiRootBuilder [RetryRequestMiddleware](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/com/commercetools/docs/meta/ClientTuning.html#retry-middleware) -If you have no special requirements on the sphere client creation, then you can use the `ClientConfigurationUtils#createClient` -util which applies the best practices for `SphereClient` creation. - -As [next generation of JVM-SDK](http://commercetools.github.io/commercetools-sdk-java-v2) has been released, now we provide an overloading method for `ClientConfigurationUtils#createClient` -which makes use of JVM-SDK-V2 to apply the best practices for `SphereClient` creation. Meanwhile the original `ClientConfigurationUtils#createClient` is supporting the last generation of JVM-SDK to avoid breaking change. -``` -public static SphereClient createClient( - @Nonnull final String projectKey, - @Nonnull final ClientCredentials clientCredentials, - @Nonnull final ServiceRegion serviceRegion) { -``` +If you have no special requirements on the client creation, then you can use the `ClientConfigurationUtils#createClient` +util which applies the best practices for `ProjectApiRoot` creation. To understand how to initialize those method arguments, please refer to the [unit test](https://github.com/commercetools/commercetools-sync-java/blob/master/src/test/java/com/commercetools/sync/commons/utils/ClientV2ConfigurationUtilsTest.java#L20) +To tune / customize your client please refer to [Client Tuning](https://commercetools.github.io/commercetools-sdk-java-v2/javadoc/com/commercetools/docs/meta/ClientTuning.html) + #### Tuning the Sync Process The sync library is not meant to be executed in a parallel fashion. For example: ````java @@ -39,10 +39,10 @@ productSync.sync(batch1) ```` By design, scaling the sync process should **not** be done by executing the batches themselves in parallel. However, it can be done either by: - - Changing the number of [max parallel requests](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L116) within the `sphereClient` configuration. It defines how many requests the client can execute in parallel. - - or changing the draft [batch size](https://commercetools.github.io/commercetools-sync-java/v/9.2.3/com/commercetools/sync/commons/BaseSyncOptionsBuilder.html#batchSize-int-). It defines how many drafts can one batch contains. + - Changing the number of [max parallel requests](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L116) within the `projectApiRoot` configuration. It defines how many requests the client can execute in parallel. + - or changing the draft [batch size](https://commercetools.github.io/commercetools-sync-java/v/9.2.1/com/commercetools/sync/commons/BaseSyncOptionsBuilder.html#batchSize-int-). It defines how many drafts can one batch contains. -The current overridable default [configuration](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L45) of the `sphereClient` +The current overridable default [configuration](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L45) of the `projectApiRoot` is the recommended good balance for stability and performance for the sync process. In order to exploit the number of `max parallel requests`, the `batch size` should have a value set that is equal or higher. diff --git a/docs/usage/INVENTORY_SYNC.md b/docs/usage/INVENTORY_SYNC.md index 00cc1be6ec..f2fa705cd5 100644 --- a/docs/usage/INVENTORY_SYNC.md +++ b/docs/usage/INVENTORY_SYNC.md @@ -1,16 +1,15 @@ # InventoryEntry Sync The module used for importing/syncing InventoryEntries into a commercetools project. -It also provides utilities for generating update actions based on the comparison of a [InventoryEntry](https://docs.commercetools.com/http-api-projects-inventory.html#inventoryentry) -against a [InventoryEntryDraft](https://docs.commercetools.com/http-api-projects-inventory.html#inventoryentrydraft). +It also provides utilities for generating update actions based on the comparison of a [InventoryEntry](https://docs.commercetools.com/api/projects/inventory#inventoryentry) +against a [InventoryEntryDraft](https://docs.commercetools.com/api/projects/inventory#inventoryentrydraft). - - [Usage](#usage) - [Prerequisites](#prerequisites) - - [SphereClient](#sphereclient) + - [ProjectApiRoot](#projectapiroot) - [Required Fields](#required-fields) - [Reference Resolution](#reference-resolution) - [Syncing from a commercetools project](#syncing-from-a-commercetools-project) @@ -26,7 +25,12 @@ against a [InventoryEntryDraft](https://docs.commercetools.com/http-api-projects - [Running the sync](#running-the-sync) - [Build all update actions](#build-all-update-actions) - [Build particular update action(s)](#build-particular-update-actions) -- [Caveats](#caveats) +- [Migration Guide](#migration-guide) + - [Client configuration and creation](#client-configuration-and-creation) + - [Signature of InventorySyncOptions](#signature-of-inventorysyncoptions) + - [Build InventoryEntryDraft (syncing from external project)](#build-inventoryentrydraft-syncing-from-external-project) + - [Query for Inventories (syncing from CTP project)](#query-for-inventories-syncing-from-ctp-project) + - [JVM-SDK-V2 migration guide](#jvm-sdk-v2-migration-guide) @@ -34,15 +38,20 @@ against a [InventoryEntryDraft](https://docs.commercetools.com/http-api-projects ### Prerequisites -#### SphereClient +#### ProjectApiRoot -Use the [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/9.2.3/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L45) which apply the best practices for `SphereClient` creation. -If you have custom requirements for the sphere client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). +Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](#todo) +If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). ````java -final SphereClientConfig clientConfig = SphereClientConfig.of("project-key", "client-id", "client-secret"); - -final SphereClient sphereClient = ClientConfigurationUtils.createClient(clientConfig); +final ClientCredentials clientCredentials = + new ClientCredentialsBuilder() + .withClientId("client-id") + .withClientSecret("client-secret") + .withScopes("scopes") + .build(); +final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); ```` #### Required Fields @@ -51,45 +60,41 @@ The following fields are **required** to be set in, otherwise, they won't be mat |Draft|Required Fields|Note| |---|---|---| -| [InventoryEntryDraft](https://docs.commercetools.com/http-api-projects-inventory.html#inventoryentrydraft) | `sku` | Also, the inventory entries in the target project are expected to have the `sku` fields set. | +| [InventoryEntryDraft](https://docs.commercetools.com/api/projects/inventory#inventoryentrydraft) | `sku` | Also, the inventory entries in the target project are expected to have the `sku` fields set. | #### Reference Resolution -In commercetools, a reference can be created by providing the key instead of the ID with the type [ResourceIdentifier](https://docs.commercetools.com/api/types#resourceidentifier). +In commercetools, a reference can be created by providing the key instead of the ID with the type [ResourceIdentifier](https://docs.commercetools.com/api/types#ctp:api:type:ResourceIdentifier). When the reference key is provided with a `ResourceIdentifier`, the sync will resolve the resource with the given key and use the ID of the found resource to create or update a reference. Therefore, in order to resolve the actual ids of those references in the sync process, `ResourceIdentifier`s with their `key`s have to be supplied. |Reference Field|Type| |:---|:---| -| `supplyChannel` | ResourceIdentifier to a Channel | -| `custom.type` | ResourceIdentifier to a Type | +| `supplyChannel` | [ChannelResourceIdentifier](https://docs.commercetools.com/api/projects/channels#ctp:api:type:ChannelResourceIdentifier)| +| `custom.type` | [TypeResourceIdentifier](https://docs.commercetools.com/api/projects/types#ctp:api:type:TypeResourceIdentifier) | > Note that a reference without the key field will be considered as an existing resource on the target commercetools project and the library will issue an update/create an API request without reference resolution. ##### Syncing from a commercetools project -When syncing from a source commercetools project, you can use [`toInventoryEntryDrafts`](https://commercetools.github.io/commercetools-sync-java/v/9.2.3/com/commercetools/sync/inventories/utils/InventoryTransformUtils.html#toInventoryEntryDrafts-java.util.List-) +When syncing from a source commercetools project, you can use [`toInventoryEntryDrafts`](#todo) method that transforms(resolves by querying and caching key-id pairs) and maps from a `InventoryEntry` to `InventoryEntryDraft` using cache in order to make them ready for reference resolution by the sync, for example: ````java -// Build an InventoryEntryQuery for fetching inventories from a source CTP project without any references expanded for the sync: -final InventoryEntryQuery inventoryEntryQuery = InventoryEntryQuery.of(); +// Build an ByProjectKeyInventoryGet for fetching inventories from a source CTP project without any references expanded for the sync: +final ByProjectKeyInventoryEntriesGet inventoryEntryQuery = client.inventory().get(); // Query all inventories (NOTE this is just for example, please adjust your logic) -final List inventoryEntries = - CtpQueryUtils - .queryAll(sphereClient, inventoryEntryQuery, Function.identity()) - .thenApply(fetchedResources -> fetchedResources - .stream() - .flatMap(List::stream) - .collect(Collectors.toList())) - .toCompletableFuture() - .join(); +final List categories = QueryUtils.queryAll(inventoryEntryQuery, + (inventories) -> inventories) + .thenApply(lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())) + .toCompletableFuture() + .join(); ```` In order to transform and map the `InventoryEntry` to `InventoryEntryDraft`, -Utils method `toInventoryEntryDrafts` requires `sphereClient`, implementation of [`ReferenceIdToKeyCache`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ReferenceIdToKeyCache.java) and `inventoryEntries` as parameters. -For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/CaffeineReferenceIdToKeyCacheImpl.java). +Utils method `toInventoryEntryDrafts` requires `projectApiRoot`, implementation of [`ReferenceIdToKeyCache`](#todo) and `inventoryEntries` as parameters. +For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](#todo). Example as shown below: ````java @@ -106,17 +111,19 @@ CompletableFuture> inventoryEntryDrafts = InventoryTra ````java final InventoryEntryDraft inventoryEntryDraft = InventoryEntryDraftBuilder - .of("sku-1", 2L) - .custom(CustomFieldsDraft.ofTypeKeyAndJson("type-key", emptyMap())) // note that custom type provided with key - .supplyChannel(ResourceIdentifier.ofKey("channel-key")) // note that channel reference provided with key + .of() + .sku("sku1") + .quantityOnStock(1L) + .custom(CustomFieldsDraftBuilder.of().type(typeResourceIdentifierBuilder -> typeResourceIdentifierBuilder.key("type-key")).fields(fieldContainerBuilder -> fieldContainerBuilder.values(emptyMap())).build())) // note that custom type provided with key + .supplyChannel(ChannelResourceIdentifierBuilder.of().key("channel-key").build()) // note that channel reference provided with key .build(); ```` #### SyncOptions -After the `sphereClient` is set up, an `InventorySyncOptions` should be built as follows: +After the `projectApiRoot` is set up, an `InventorySyncOptions` should be built as follows: ````java // instantiating a InventorySyncOptions -final InventorySyncOptions inventorySyncOptions = InventorySyncOptionsBuilder.of(sphereClient).build(); +final InventorySyncOptions inventorySyncOptions = InventorySyncOptionsBuilder.of(projectApiRoot).build(); ```` `SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. @@ -135,7 +142,7 @@ following context about the error-event: ````java final Logger logger = LoggerFactory.getLogger(InventorySync.class); final InventorySyncOptions inventorySyncOptions = InventorySyncOptionsBuilder - .of(sphereClient) + .of(projectApiRoot) .errorCallback((syncException, draft, inventoryEntry, updateActions) -> logger.error(new SyncException("My customized message"), syncException)).build(); ```` @@ -152,8 +159,8 @@ following context about the warning message: ````java final Logger logger = LoggerFactory.getLogger(InventorySync.class); final InventorySyncOptions inventorySyncOptions = InventorySyncOptionsBuilder - .of(sphereClient) - .warningCallback((syncException, draft, inventoryEntry, updateActions) -> + .of(projectApiRoot) + .warningCallback((syncException, draft, inventoryEntry) -> logger.warn(new SyncException("My customized message"), syncException)).build(); ```` @@ -168,16 +175,16 @@ update actions array with custom actions or discard unwanted actions. The callba ````java final TriFunction< - List>, + List, InventoryEntryDraft, InventoryEntry, - List>> beforeUpdateInventoryCallback = + List> beforeUpdateInventoryCallback = (updateActions, newInventoryEntryDraft, oldInventoryEntry) -> updateActions.stream() - .filter(updateAction -> !(updateAction instanceof RemoveQuantity)) + .filter(updateAction -> !(updateAction instanceof InventoryEntryRemoveQuantityAction)) .collect(Collectors.toList()); final InventorySyncOptions inventorySyncOptions = - InventorySyncOptionsBuilder.of(sphereClient).beforeUpdateCallback(beforeUpdateInventoryCallback).build(); + InventorySyncOptionsBuilder.of(projectApiRoot).beforeUpdateCallback(beforeUpdateInventoryCallback).build(); ```` ##### beforeCreateCallback @@ -193,7 +200,7 @@ as inventories are obtained from the target project on the commercetools platfor ````java final InventorySyncOptions inventorySyncOptions = - InventorySyncOptionsBuilder.of(sphereClient).batchSize(100).build(); + InventorySyncOptionsBuilder.of(projectApiRoot).batchSize(100).build(); ```` ##### cacheSize @@ -205,7 +212,7 @@ Playing with this option can change the memory usage of the library. If it is no ````java final InventorySyncOptions inventorySyncOptions = - InventorySyncOptionsBuilder.of(sphereClient).cacheSize(5000).build(); + InventorySyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); ```` @@ -219,7 +226,7 @@ If it fails to create the supply channel, the inventory won't sync and `errorCal ````java final InventorySyncOptions inventorySyncOptions = - InventorySyncOptionsBuilder.of(sphereClient).ensureChannels(true).build(); + InventorySyncOptionsBuilder.of(projectApiRoot).ensureChannels(true).build(); ```` ### Running the sync @@ -247,7 +254,7 @@ __Note__ The statistics object contains the processing time of the last batch on 2. It is not known by the sync which batch is going to be the last one supplied. -More examples of how to use the sync [here](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/inventories/InventorySyncIT.java). +More examples of how to use the sync [here](#todo). *Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* @@ -257,7 +264,7 @@ More examples of how to use the sync [here](https://github.com/commercetools/com A utility method provided by the library to compare an InventoryEntry with a new InventoryEntryDraft and results in a list of InventoryEntry update actions. ```java -List> updateActions = InventorySyncUtils.buildActions(oldEntry, newEntry, inventorySyncOptions); +List updateActions = InventorySyncUtils.buildActions(oldEntry, newEntry, inventorySyncOptions); ``` Examples of its usage can be found in the tests @@ -269,8 +276,107 @@ Utility methods provided by the library to compare the specific fields of an Inv the update action. One example is the `buildChangeQuantityAction` which compares quantities: ````java -Optional> updateAction = buildChangeQuantityAction(oldEntry, newEntry); +Optional updateAction = buildChangeQuantityAction(oldEntry, newEntry); ```` -## Caveats -1. The library will sync all field types of custom fields, except `ReferenceType`. [#87](https://github.com/commercetools/commercetools-sync-java/issues/87). +## Migration Guide + +The inventory-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with +any HTTP client module. The default one is `commercetools-http-client`. + +```xml + + + LATEST + + + + + com.commercetools.sdk + commercetools-http-client + ${commercetools.version} + + + com.commercetools.sdk + commercetools-sdk-java-api + ${commercetools.version} + + + +``` + +### Client configuration and creation + +For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). + +### Signature of InventorySyncOptions + +As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `InventoryEntryDraft`, `InventoryEntry` and `InventoryEntryUpdateAction` from `package com.commercetools.api.models.inventory.*` + +> Note: Type `UpdateAction` has changed to `InventoryEntryUpdateAction`. Make sure you create and supply a specific InventoryEntryUpdateAction in `beforeUpdateCallback`. For that you can use the [library-utilities](#todo) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): + +```java +// Example: Create a inventory update action to change quantity taking the 'newQuantity' of the InventoryEntryDraft + final Function createBeforeUpdateAction = + (newQuantity) -> InventoryEntryChangeQuantityAction.builder().quantity(newQuantity).build(); + +// Add the change quantity action to the list of update actions before update is executed + final TriFunction< + List, InventoryEntryDraft, InventoryEntry, List> + beforeUpdateInventoryCallback = + (updateActions, newInventoryEntryDraft, oldInventoryEntry) -> { + final InventoryEntryUpdateAction beforeUpdateAction = + createBeforeUpdateAction.apply(newInventoryDraft.getQuantity()); + updateActions.add(beforeUpdateAction); + return updateActions; + }; +``` + +### Build InventoryEntryDraft (syncing from external project) + +The inventory-sync expects a list of `InventoryEntryDraft`s to process. If you use java-sync-library to sync your inventories from any external system into a commercetools platform project you have to convert your data into CTP compatible `InventoryEntryDraft` type. This was done in previous version using `DraftBuilder`s. +The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: + +```java +// InventoryEntryDraftBuilder in v1 takes parameters 'sku' and 'quantityOnStock' +final InventoryEntryDraft inventoryEntryDraft = + InventoryEntryDraftBuilder + .of("sku", 10L) + .restockableInDays(10) //Note: Field 'restockableInDays' is of type Integer + .build(); + +// InventoryEntryDraftBuilder in v2 +final InventoryEntryDraft inventoryEntryDraft = + InventoryEntryDraftBuilder + .of() + .sku("sku") + .quantityOnStock(10L) + .restockableInDays(10L) //Note: Field 'restockableInDays' is of type Long + .build(); +``` +For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). + +### Query for Inventories (syncing from CTP project) + +If you sync inventories between different commercetools projects you probably use [InventoryTransformUtils#toInventoryEntryDrafts](#todo) to transform `InventoryEntry` into `InventoryEntryDraft` which can be used by the inventory-sync. +However, if you need to query `Inventories` from a commercetools project instead of passing `InventoryEntryQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. +Here's an example: + +```java +// SDK v1: InventoryEntryQuery to fetch all inventories +final InventoryEntryQuery query = InventoryEntryQuery.of(); + +final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); + +// SDK v2: Create and execute query to fetch all inventories in one line +final InventoryEntryPagedQueryResponse result = apiRoot.inventory().get().executeBlocking().getBody(); +``` +[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. + +> Note: If you use predicates to query resources please keep in mind the URI length is limited to ~8kB. Therefore, consider limiting the query-predicates (max. 10.000 characters), because above this size it could return - Error 414 (Request-URI Too Large). + +### JVM-SDK-V2 migration guide + +On any other needs to migrate your project using jvm-sdk-v2 please refer to it's [Migration Guide](https://docs.commercetools.com/sdk/java-sdk-migrate). + diff --git a/docs/usage/PRODUCT_SYNC.md b/docs/usage/PRODUCT_SYNC.md index 24021289b0..a7daeaf8ca 100644 --- a/docs/usage/PRODUCT_SYNC.md +++ b/docs/usage/PRODUCT_SYNC.md @@ -2,15 +2,14 @@ The module used for importing/syncing Products into a commercetools project. It also provides utilities for generating update actions based on the comparison of a [ProductProjection](https://docs.commercetools.com/api/projects/productProjections#productprojection) -against a [ProductDraft](https://docs.commercetools.com/http-api-projects-products.html#productdraft). +against a [ProductDraft](https://docs.commercetools.com/api/projects/products#productdraft). - - [Usage](#usage) - [Prerequisites](#prerequisites) - - [SphereClient](#sphereclient) + - [ProjectApiRoot](#projectapiroot) - [Required Fields](#required-fields) - [Reference Resolution](#reference-resolution) - [Syncing from a commercetools project](#syncing-from-a-commercetools-project) @@ -30,6 +29,12 @@ against a [ProductDraft](https://docs.commercetools.com/http-api-projects-produc - [Build all update actions](#build-all-update-actions) - [Build particular update action(s)](#build-particular-update-actions) - [Caveats](#caveats) +- [Migration Guide](#migration-guide) + - [Client configuration and creation](#client-configuration-and-creation) + - [Signature of ProductSyncOptions](#signature-of-productsyncoptions) + - [Build ProductDraft (syncing from external project)](#build-productdraft-syncing-from-external-project) + - [Query for Products (syncing from CTP project)](#query-for-products-syncing-from-ctp-project) + - [JVM-SDK-V2 migration guide](#jvm-sdk-v2-migration-guide) @@ -37,15 +42,20 @@ against a [ProductDraft](https://docs.commercetools.com/http-api-projects-produc ### Prerequisites -#### SphereClient - -Use the [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/9.2.3/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L45) which apply the best practices for `SphereClient` creation. -If you have custom requirements for the sphere client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). +#### ProjectApiRoot + +Use the [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/java-sdk-v2-product-sync-migration/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java) which apply the best practices for `ProjectApiRoot` creation. +To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](https://github.com/commercetools/commercetools-sdk-java-v2/blob/main/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/oauth2/ClientCredentialsBuilder.java) +If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). ````java -final SphereClientConfig clientConfig = SphereClientConfig.of("project-key", "client-id", "client-secret"); - -final SphereClient sphereClient = ClientConfigurationUtils.createClient(clientConfig); +final ClientCredentials clientCredentials = + new ClientCredentialsBuilder() + .withClientId("client-id") + .withClientSecret("client-secret") + .withScopes("scopes") + .build(); +final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); ```` #### Required Fields @@ -63,44 +73,40 @@ In commercetools, a reference can be created by providing the key instead of the When the reference key is provided with a `ResourceIdentifier`, the sync will resolve the resource with the given key and use the ID of the found resource to create or update a reference. Therefore, in order to resolve the actual ids of those references in the sync process, `ResourceIdentifier`s with their `key`s have to be supplied. -|Reference Field|Type| -|:---|:---| -| `productType` - **Required** | ResourceIdentifier to a ProductType | -| `categories` | Set of ResourceIdentifier for a Category | -| `taxCategory` | ResourceIdentifier to a TaxCategory | -| `state` | ResourceIdentifier for a State | Optional | -| `variants.prices.channel` | ResourceIdentifier to a Channel | -| `variants.prices.customerGroup` | ResourceIdentifier to a CustomerGroup | -| `variants.prices.custom.type` | ResourceIdentifier to a Type | -| `variants.assets.custom.type` | ResourceIdentifier to a Type | -| `variants.attributes` * | Only the attributes with type [ReferenceType](https://docs.commercetools.com/api/projects/productTypes#referencetype), [SetType](https://docs.commercetools.com/api/projects/productTypes#settype) with `elementType` as [ReferenceType](https://docs.commercetools.com/api/projects/productTypes#referencetype) and [NestedType](https://docs.commercetools.com/api/projects/productTypes#nestedtype) requires `key` on the `id` field of the `ReferenceType`. | +|Reference Field|Type|Necessity| +|:---|:---|:---| +| `productType` | ProductTypeResourceIdentifier | **Required** | +| `categories` | List of CategoryResourceIdentifier | Optional | +| `taxCategory` | TaxCategoryResourceIdentifier | Optional | +| `state` | StateResourceIdentifier | Optional | +| `variants.prices.channel` | ChannelResourceIdentifier | Optional | +| `variants.prices.customerGroup` | CustomerGroupResourceIdentifier | Optional | +| `variants.prices.custom.type` | TypeResourceIdentifier | **Required** for `custom` (CustomFieldsDraft) | +| `variants.assets.custom.type` | TypeResourceIdentifier | **Required** for `custom` (CustomFieldsDraft) | +| `variants.attributes` | Only the attributes with type [ReferenceType](https://docs.commercetools.com/api/projects/productTypes#referencetype), [SetType](https://docs.commercetools.com/api/projects/productTypes#settype) with `elementType` as [ReferenceType](https://docs.commercetools.com/api/projects/productTypes#referencetype) and [NestedType](https://docs.commercetools.com/api/projects/productTypes#nestedtype) requires `key` on the `id` field of the `ReferenceType`. | Optional | > Note that a reference without the key field will be considered as existing resource on the target commercetools project and the library will issue an update/create an API request without reference resolution. ##### Syncing from a commercetools project -When syncing from a source commercetools project, you can use [`toProductDrafts`](https://commercetools.github.io/commercetools-sync-java/v/9.2.3/com/commercetools/sync/products/utils/ProductTransformUtils.html#toProductDrafts-java.util.List-) - method that transforms(resolves by querying and caching key-id pairs) and maps from a `Product` to `ProductDraft` using cache in order to make them ready for reference resolution by the sync, for example: +When syncing from a source commercetools project, you can use [`toProductDrafts`](https://github.com/commercetools/commercetools-sync-java/blob/java-sdk-v2-product-sync-migration/src/main/java/com/commercetools/sync/products/utils/ProductTransformUtils.java#L59) + method that transforms(resolves by querying and caching key-id pairs) and maps from a `ProductProjection` to `ProductDraft` using cache in order to make them ready for reference resolution by the sync, for example: ````java // Build a ProductQuery for fetching products from a source CTP project without any references expanded for the sync: -final ProductProjectionQuery productProjectionQuery = ProductProjectionQuery.ofStaged(); +final ByProjectKeyProductProjectionsGet byProjectKeyProductsGet = getCtpClient().productProjections().get().addStaged(true); // Query all product projections (NOTE this is only for example, please adjust your logic) -final List productProjections = - CtpQueryUtils - .queryAll(sphereClient, productProjectionQuery, Function.identity()) - .thenApply(fetchedResources -> fetchedResources - .stream() - .flatMap(List::stream) - .collect(Collectors.toList())) - .toCompletableFuture() - .join(); +final List products = QueryUtils.queryAll(byProjectKeyProductsGet, + (productProjections) -> productProjections) + .thenApply(lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())) + .toCompletableFuture() + .join(); ```` -In order to transform and map the `Product` to `ProductDraft`, -Utils method `toProductDrafts` requires 'sphereClient', implementation of [`ReferenceIdToKeyCache`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ReferenceIdToKeyCache.java) and `products` as parameters. +In order to transform and map the `ProductProjections` to `ProductDraft`, +Utils method `toProductDrafts` requires `ProjectApiRoot`, implementation of [`ReferenceIdToKeyCache`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ReferenceIdToKeyCache.java) and list of `ProductProjection` as parameters. For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/CaffeineReferenceIdToKeyCacheImpl.java). Example as shown below: @@ -108,7 +114,7 @@ Example as shown below: //Implement the cache using library class. final ReferenceIdToKeyCache referenceIdToKeyCache = new CaffeineReferenceIdToKeyCacheImpl(); -//For every reference fetch its key using id, cache it and map from Product to ProductDraft. With help of the cache same reference keys can be reused. +//For every reference fetch its key using id, cache it and map from ProductProjection to ProductDraft. With help of the cache same reference keys can be reused. CompletableFuture> productDrafts = ProductTransformUtils.toProductDrafts(client, referenceIdToKeyCache, products); ```` ##### Syncing from an external resource @@ -117,56 +123,62 @@ CompletableFuture> productDrafts = ProductTransformUtils.toPr ```` java final ProductDraft productDraft = - ProductDraftBuilder - .of(ResourceIdentifier.ofKey("product-type-key"), ofEnglish("name"), ofEnglish("slug"), - singletonList(masterVariant)) - .key("product-key") - .categories(asSet(ResourceIdentifier.ofKey("category1-key"), ResourceIdentifier.ofKey("category2-key"))) - .taxCategory(ResourceIdentifier.ofKey("tax-category-key")) - .state(ResourceIdentifier.ofKey("tax-category-key")) - .build(); + ProductDraftBuilder + .of() + .productType(ProductTypeResourceIdentifierBuilder.of().key("product-type-key").build()) + .name(LocalizedString.ofEnglish("name")) + .slug(LocalizedString.ofEnglish("slug")) + .masterVariant(masterVariant) + .key("product-key") + .categories(CategoryResourceIdentifierBuilder.of().key("category1-key").build(), + CategoryResourceIdentifierBuilder.of().key("category2-key").build()) + .taxCategory(TaxCategoryResourceIdentifierBuilder.of().key("tax-category-key").build()) + .state(StateResourceIdentifierBuilder.of().key("tax-category-key").build()) + .build(); ```` ````java - final PriceDraft priceDraft = PriceDraftBuilder - of(MoneyImpl.of("20", "EUR")) - .channel(ResourceIdentifier.ofKey("channel-key")) - .customerGroup(ResourceIdentifier.ofKey("customer-group-key")) - .custom(CustomFieldsDraft.ofTypeKeyAndJson("type-key", emptyMap())) - .build(); +final PriceDraft priceDraft = + PriceDraftBuilder.of() + .value(MoneyBuilder.of().centAmount(20L).currencyCode("EUR").build()) + .channel(ChannelResourceIdentifierBuilder.of().key("channel-key").build()) + .customerGroup( + CustomerGroupResourceIdentifierBuilder.of().key("customer-group-key").build()) + .custom( + CustomFieldsDraftBuilder.of() + .type(TypeResourceIdentifierBuilder.of().key("type-key").build()) + .fields(FieldContainerBuilder.of().values(Collections.emptyMap()).build()).build()) + .build(); ```` - The product projection variant attributes with a type `ReferenceType` do not support the `ResourceIdentifier` yet, for those references you have to provide the `key` value on the `id` field of the reference. This means that calling `getId()` on the reference should return its `key`. ````java -final ObjectNode productReference = JsonNodeFactory.instance.objectNode(); -productReference.put("typeId", Product.referenceTypeId()); -productReference.put("id", "product-key"); // note that reference key provided in the id field +final ProductReference productReference = ProductReferenceBuilder.of().id("product-key").build(); +final Attribute attr = AttributeBuilder.of().name("attribute-name").value(productReference).build(); -final AttributeDraft productAttributeDraft = AttributeDraft.of("productAttrName", productReference); ```` -- For resolving `key-value-document` (custom object) references on attributes of type `Reference`, `Set` of `Reference`, `NestedType` or `Set` of `NestedType`, The `id` field of the reference in the attribute draft should be defined in the correct format. +- For resolving `key-value-document` (custom object) references on attributes of type `Reference`, `Set` of `Reference`, `NestedType` or `Set` of `NestedType`, The `id` field of the reference in the attribute should be defined in the correct format. The correct format must have a vertical bar `|` character between the values of the container and key. -For example, if the custom object has a container value `container` and key value `key`, the `id` field should be `container|key"`, -also, the key and container value should match the pattern `[-_~.a-zA-Z0-9]+`. +For example, if the custom object has a container value `container` and key value `key`, the `id` field should be `container|key`, +also, the key and container value should match the pattern `[-_~.a-zA-Z0-9]+`. Please also keep in mind that length of the key is limited to 256 characters max: [CustomObject](https://docs.commercetools.com/api/projects/custom-objects#customobject) ````java -final ObjectNode customObjectReference = JsonNodeFactory.instance.objectNode(); -productReference.put("typeId", CustomObject.referenceTypeId()); -productReference.put("id", "co-container|co-key"); - -final AttributeDraft customObjectAttributeDraft = AttributeDraft.of("customObjectAttrName", productReference); +final CustomObjectReference coReference = + CustomObjectReferenceBuilder.of().id("co-container|co-key").build(); +final Attribute attr = + AttributeBuilder.of().name("attribute-name").value(coReference).build(); ```` #### SyncOptions -After the `sphereClient` is set up, a `ProductSyncOptions` should be built as follows: +After the `ProjectApiRoot` is set up, a `ProductSyncOptions` should be built as follows: ````java // instantiating a ProductSyncOptions -final ProductSyncOptions productSyncOptions = ProductSyncOptionsBuilder.of(sphereClient).build(); +final ProductSyncOptions productSyncOptions = ProductSyncOptionsBuilder.of(projectApiRoot).build(); ```` `SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. @@ -185,7 +197,7 @@ following context about the error-event: ````java final Logger logger = LoggerFactory.getLogger(ProductSync.class); final ProductSyncOptions productSyncOptions = ProductSyncOptionsBuilder - .of(sphereClient) + .of(projectApiRoot) .errorCallback((syncException, draft, productProjection, updateActions) -> logger.error(new SyncException("My customized message"), syncException)).build(); ```` @@ -202,8 +214,8 @@ following context about the warning message: ````java final Logger logger = LoggerFactory.getLogger(ProductSync.class); final ProductSyncOptions productSyncOptions = ProductSyncOptionsBuilder - .of(sphereClient) - .warningCallback((syncException, draft, productProjection, updateActions) -> + .of(projectApiRoot) + .warningCallback((syncException, draft, productProjection) -> logger.warn(new SyncException("My customized message"), syncException)).build(); ```` @@ -217,15 +229,16 @@ actions array with custom actions or discard unwanted actions. The callback prov * update actions that were calculated after comparing both ````java +// Example: Ignore update actions which contain deletion of variants final TriFunction< - List>, ProductDraft, ProductProjection, List>> beforeUpdateProductCallback = + List, ProductDraft, ProductProjection, List> beforeUpdateProductCallback = (updateActions, newProductDraft, oldProduct) -> updateActions.stream() - .filter(updateAction -> !(updateAction instanceof RemoveVariant)) + .filter(updateAction -> !(updateAction instanceof ProductRemoveVariantActionImpl)) .collect(Collectors.toList()); final ProductSyncOptions productSyncOptions = - ProductSyncOptionsBuilder.of(sphereClient).beforeUpdateCallback(beforeUpdateProductCallback).build(); + ProductSyncOptionsBuilder.of(projectApiRoot).beforeUpdateCallback(beforeUpdateProductCallback).build(); ```` ##### beforeCreateCallback @@ -234,31 +247,30 @@ During the sync process, if a product draft should be created, this callback can * product draft that should be created ````java -// Example (Set publish stage if category references of given product draft exist) - +// Example: Set publish stage if category references of given product draft exist final Function beforeCreateProductCallback = (callbackDraft) -> { - Set> categoryResourceIdentifier = callbackDraft.getCategories(); + List categoryResourceIdentifier = callbackDraft.getCategories(); if (categoryResourceIdentifier!=null && !categoryResourceIdentifier.isEmpty()) { - return ProductDraftBuilder.of(callbackDraft).isPublish(true).build(); + return ProductDraftBuilder.of(callbackDraft).publish(true).build(); } return callbackDraft; }; final ProductSyncOptions productSyncOptions = - ProductSyncOptionsBuilder.of(sphereClient).beforeCreateCallback(beforeCreateProductCallback).build(); + ProductSyncOptionsBuilder.of(projectApiRoot).beforeCreateCallback(beforeCreateProductCallback).build(); ```` ##### batchSize A number that could be used to set the batch size with which product projections are fetched and processed, as product projections are obtained from the target project on commercetools platform in batches for better performance. The algorithm accumulates up to `batchSize` resources from the input list, then fetches the corresponding product -projections from the target project on the commecetools platform in a single request. Playing with this option can +projections from the target project on the commercetools platform in a single request. Playing with this option can slightly improve or reduce processing speed. If it is not set, the default batch size is 30 for product sync. ````java final ProductSyncOptions productSyncOptions = - ProductSyncOptionsBuilder.of(sphereClient).batchSize(50).build(); + ProductSyncOptionsBuilder.of(projectApiRoot).batchSize(50).build(); ```` ##### cacheSize @@ -270,7 +282,7 @@ Playing with this option can change the memory usage of the library. If it is no ````java final ProductSyncOptions productSyncOptions = - ProductSyncOptionsBuilder.of(sphereClient).cacheSize(5000).build(); + ProductSyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); ```` ##### syncFilter @@ -303,7 +315,7 @@ If it fails to create the price channel, the products won't sync and `errorCallb ````java final ProductSyncOptions productSyncOptions = - ProductSyncOptionsBuilder.of(sphereClient).ensureChannels(true).build(); + ProductSyncOptionsBuilder.of(projectApiRoot).ensureChannels(true).build(); ```` ### Running the sync @@ -320,7 +332,7 @@ which contains all the stats of the sync process; which includes a report messag failed, processed products and the processing time of the sync in different time units and in a human-readable format. ````java -final ProductSyncStatistics stats = syncStatisticsStage.toCompletebleFuture().join(); +final ProductSyncStatistics stats = syncStatisticsStage.toCompletableFuture().join(); stats.getReportMessage(); /*Summary: 2000 product(s) were processed in total (1000 created, 995 updated, 5 failed to sync and 0 product(s) with missing reference(s)).*/ ```` @@ -333,10 +345,10 @@ __Note__ The statistics object contains the processing time of the last batch on ##### Persistence of ProductDrafts with Irresolvable References A productDraft X could be supplied in with an attribute referencing productDraft Y. -It could be that Y is not supplied before X, which means the sync could fail to create/updating X. +It could be that Y is not supplied before X, which means the sync could fail to create/update X. It could also be that Y is not supplied at all in this batch but at a later batch. -The library keeps tracks of such "referencing" drafts like X and persists them in storage +The library keeps track of such "referencing" drafts like X and persists them in storage (**Commercetools platform `customObjects` in the target project** , in this case) to keep them and create/update them accordingly whenever the referenced drafts exist in the target project. @@ -417,16 +429,13 @@ Keeping the old custom objects around forever can negatively influence the perfo ### Build all update actions A utility method provided by the library to compare a ProductProjection with a new ProductDraft and results in a - list of -t - update actions. + list of update actions. ```java -List> updateActions = ProductSyncUtils.buildActions(productProjection, productDraft -, productSyncOptions, attributesMetaData); +List updateActions = ProductSyncUtils.buildActions(productProjection, productDraft, productSyncOptions, attributesMetaData); ``` Examples of its usage can be found in the tests -[here](https://github.com/commercetools/commercetools-sync-java/tree/master/src/test/java/com/commercetools/sync/products/utils/ProductSyncUtilsTest.java). +[here](https://github.com/commercetools/commercetools-sync-java/blob/java-sdk-v2-product-sync-migration/src/test/java/com/commercetools/sync/products/utils/ProductSyncUtilsTest.java). ### Build particular update action(s) @@ -434,7 +443,7 @@ Utility methods provided by the library to compare the specific fields of a Prod build the update action. One example is the `buildChangeNameUpdateAction` which compares names: ````java -Optional> updateAction = buildChangeNameUpdateAction(oldProductProjection, productDraft); +Optional updateAction = buildChangeNameUpdateAction(oldProductProjection, productDraft); ```` More examples of those utils for different fields can be found [here](https://github.com/commercetools/commercetools-sync-java/tree/master/src/test/java/com/commercetools/sync/products/utils). @@ -443,8 +452,8 @@ More examples of those utils for different fields can be found [here](https://gi The commercetools-java-sync library has some exceptions to the data it can sync, particularly around product variant attributes. -1. List of supported variant attributes, with a `AttributeType`: `ReferenceType`, - that can be synced (See more: [#87](https://github.com/commercetools/commercetools-sync-java/issues/87)): +1. List of supported variant attributes, with an `AttributeType`: `ReferenceType`, + that can be synced: | `referenceTypeId` | supported | |---|---| @@ -466,3 +475,104 @@ attributes. 3. Support for syncing variant attributes with an `AttributeType` of `NestedType` which has an attribute inside of it of `ReferenceType` with any of the aforementioned `referenceTypeId`, accordingly applies. 4. Syncing products with cyclic dependencies are not supported yet. An example of a cyclic dependency is a product `a` which references a product `b` and at the same time product `b` references product `a`. Cycles can contain more than 2 products. For example: `a` -> `b` -> `c` -> `a`. If there are such cycles, the sync will consider all the products in the cycle as products with missing parents. They will be persisted as custom objects in the target project. + +## Migration Guide + +The product-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with +any HTTP client module. The default one is `commercetools-http-client`. + +```xml + + + LATEST + + + + + com.commercetools.sdk + commercetools-http-client + ${commercetools.version} + + + com.commercetools.sdk + commercetools-sdk-java-api + ${commercetools.version} + + + +``` + +### Client configuration and creation + +For client creation use [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/java-sdk-v2-product-sync-migration/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java) which apply the best practices for `ProjectApiRoot` creation. +If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). + +### Signature of ProductSyncOptions + +As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `ProductDraft`, `ProductProjection` and `ProductUpdateAction` from `package com.commercetools.api.models.product.*` + +> Note: Type `UpdateAction` has changed to `ProductUpdateAction`. Make sure you create and supply a specific ProductUpdateAction in `beforeUpdateCallback`. Therefore you can use the [library-utilities](https://github.com/commercetools/commercetools-sync-java/blob/java-sdk-v2-product-sync-migration/src/main/java/com/commercetools/sync/products/utils/ProductUpdateActionUtils.java) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): + +```java +// Example: Create a product update action to change name taking the 'newName' of the productDraft + final Function createBeforeUpdateAction = + (newName) -> ProductChangeNameAction.builder().name(newName).staged(true).build(); + +// Add the change name action to the list of update actions before update is executed + final TriFunction< + List, ProductDraft, ProductProjection, List> + beforeUpdateProductCallback = + (updateActions, newProductDraft, oldProduct) -> { + final ProductUpdateAction beforeUpdateAction = + createBeforeUpdateAction.apply(newProductDraft.getName()); + updateActions.add(beforeUpdateAction); + return updateActions; + }; +``` + +### Build ProductDraft (syncing from external project) + +The product-sync expects a list of `ProductDraft`s to process. If you use java-sync-library to sync your products from any external system into a commercetools platform project you have to convert your data into CTP compatible `ProductDraft` type. This was done in previous version using `DraftBuilder`s. +The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: + +```java +// ProductDraftBuilder in v1 takes parameters 'productType', 'name', 'slug' and optional 'masterVariant' +final ProductDraft productDraft = + ProductDraftBuilder + .of(mock(ProductType.class), ofEnglish("name"), ofEnglish("slug"), emptyList()) + .key("product-key") + .build(); + +// ProductDraftBuilder in v2 +final ProductDraft productDraft = + ProductDraftBuilder + .of() + .productType(ProductTypeResourceIdentifierBuilder.of().key("product-type-key").build()) + .name(LocalizedString.ofEnglish("name")) + .slug(LocalizedString.ofEnglish("slug")) + .masterVariant(masterVariant) + .key("product-key") + .build(); +``` +For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). + +### Query for Products (syncing from CTP project) + +If you sync products between different commercetools projects you probably use [ProductTransformUtils#toProductDrafts](https://github.com/commercetools/commercetools-sync-java/blob/java-sdk-v2-product-sync-migration/src/main/java/com/commercetools/sync/products/utils/ProductTransformUtils.java#L59) to transform `ProductProjection` into `ProductDraft` which can be used by the product-sync. +However, if you need to query `Products` / `ProductProjections` from a commercetools project instead of passing `ProductQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. +Here's an example: + +```java +// SDK v1: ProductProjectionQuery to fetch all staged product projections +final ProductProjectionQuery query = ProductProjectionQuery.ofStaged(); + +final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); + +// SDK v2: Create and execute query to fetch all staged product projections in one line +final ProductProjectionPagedQueryResponse result = apiRoot.productProjections().get().addStaged(true).executeBlocking().getBody(); +``` +[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. + +### JVM-SDK-V2 migration guide + +On any other needs to migrate your project using jvm-sdk-v2 please refer to it's [Migration Guide](https://docs.commercetools.com/sdk/java-sdk-migrate). diff --git a/docs/usage/PRODUCT_TYPE_SYNC.md b/docs/usage/PRODUCT_TYPE_SYNC.md index eed5ce1cf2..ca132b6873 100644 --- a/docs/usage/PRODUCT_TYPE_SYNC.md +++ b/docs/usage/PRODUCT_TYPE_SYNC.md @@ -1,16 +1,15 @@ # ProductType Sync The module used for importing/syncing ProductTypes into a commercetools project. -It also provides utilities for generating update actions based on the comparison of a [ProductType](https://docs.commercetools.com/http-api-projects-productTypes.html#producttype) -against a [ProductTypeDraft](https://docs.commercetools.com/http-api-projects-productTypes.html#producttypedraft). +It also provides utilities for generating update actions based on the comparison of a [ProductType](https://docs.commercetools.com/api/projects/productTypes#producttype) +against a [ProductTypeDraft](https://docs.commercetools.com/api/projects/productTypes#ctp:api:type:ProductTypeDraft). - - [Usage](#usage) - [Prerequisites](#prerequisites) - - [SphereClient](#sphereclient) + - [ProjectApiRoot](#projectapiroot) - [Required Fields](#required-fields) - [Reference Resolution](#reference-resolution) - [Syncing from a commercetools project](#syncing-from-a-commercetools-project) @@ -28,21 +27,32 @@ against a [ProductTypeDraft](https://docs.commercetools.com/http-api-projects-pr - [Build all update actions](#build-all-update-actions) - [Build particular update action(s)](#build-particular-update-actions) - [Caveats](#caveats) +- [Migration Guide](#migration-guide) + - [Client configuration and creation](#client-configuration-and-creation) + - [Signature of ProductTypeSyncOptions](#signature-of-producttypesyncoptions) + - [Build ProductTypeDraft (syncing from external project)](#build-producttypedraft-syncing-from-external-project) + - [Query for ProductTypes (syncing from CTP project)](#query-for-producttypes-syncing-from-ctp-project) + - [JVM-SDK-V2 migration guide](#jvm-sdk-v2-migration-guide) ## Usage ### Prerequisites -#### SphereClient +#### ProjectApiRoot -Use the [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/9.2.3/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L45) which apply the best practices for `SphereClient` creation. -If you have custom requirements for the sphere client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). +Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +To create the required `ClientCredentials` for client creation, please utilize the `ClientCredentialsBuilder` provided in the java-sdk-v2 [Client OAUTH2 package](#todo). +If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). ````java -final SphereClientConfig clientConfig = SphereClientConfig.of("project-key", "client-id", "client-secret"); - -final SphereClient sphereClient = ClientConfigurationUtils.createClient(clientConfig); +final ClientCredentials clientCredentials = + new ClientCredentialsBuilder() + .withClientId("client-id") + .withClientSecret("client-secret") + .withScopes("scopes") + .build(); +final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); ```` #### Required Fields @@ -50,7 +60,7 @@ The following fields are **required** to be set in, otherwise, they won't be mat |Draft|Required Fields|Note| |---|---|---| -| [ProductTypeDraft](https://docs.commercetools.com/http-api-projects-productTypes.html#producttypedraft) | `key` | Also, the product types in the target project are expected to have the `key` fields set. | +| [ProductTypeDraft](https://docs.commercetools.com/api/projects/productTypes#ctp:api:type:ProductTypeDraft) | `key` | Also, the product types in the target project are expected to have the `key` fields set. | #### Reference Resolution @@ -60,35 +70,30 @@ Therefore, in order to resolve the actual ids of those references in the sync pr |Reference Field|Type| |:---|:---| -| `attributes` | Only the attributes with type [NestedType](https://docs.commercetools.com/api/projects/productTypes#nestedtype) and [SetType](https://docs.commercetools.com/api/projects/productTypes#settype) with `elementType` as [NestedType](https://docs.commercetools.com/api/projects/productTypes#nestedtype) requires `key` on the `id` field of the `ReferenceType`. | +| `attributes` | Only the attributes with type [AttributeNestedType](https://docs.commercetools.com/api/projects/productTypes#attributenestedtype) and [AttributeSetType](https://docs.commercetools.com/api/projects/productTypes#attributesettype) with `elementType` as `AttributeNestedType` requires `key` on the `id` field of the [ProductTypeReference](https://docs.commercetools.com/api/projects/productTypes#ctp:api:type:ProductTypeReference). | > Note that a reference without the key field will be considered as an existing resource on the target commercetools project and the library will issue an update/create an API request without reference resolution. ##### Syncing from a commercetools project -When syncing from a source commercetools project, you can use [`toProductTypeDrafts`](https://commercetools.github.io/commercetools-sync-java/v/9.2.3/com/commercetools/sync/producttypes/utils/ProductTypeTransformUtils.html#toProductTypeDrafts-java.util.List-) +When syncing from a source commercetools project, you can use [`toProductTypeDrafts`](#todo) method that transforms(resolves by querying and caching key-id pairs) and maps from a `ProductType` to `ProductTypeDraft`. It can be configured to use a cache that will speed up the reference resolution performed during the sync, for example: ````java -// Build a ProductTypeQuery for fetching product types from a source CTP project without any references expanded for the sync. -final ProductTypeQuery productTypeQuery = ProductTypeQuery.of(); - -// Query all productTypes (NOTE this is just for example, please adjust your logic) -final List productTypes = - CtpQueryUtils - .queryAll(sphereClient, productTypeQuery, Function.identity()) - .thenApply(fetchedResources -> fetchedResources - .stream() - .flatMap(List::stream) - .collect(Collectors.toList())) - .toCompletableFuture() - .join(); +// Build ByProjectKeyProductTypesGet for fetching product-types from a source CTP project without any references expanded for the sync: +final ByProjectKeyProductTypesGet byProjectKeyProductTypesGet = client.productTypes().get(); + +// Query all product-types (NOTE this is just for example, please adjust your logic) +final List productTypes = QueryUtils.queryAll(byProjectKeyProductTypesGet, + (productTypes) -> productTypes) + .thenApply(lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())) + .toCompletableFuture() + .join(); ```` In order to transform and map the `ProductType` to `ProductTypeDraft`, -Utils method `toProductTypeDrafts` requires `sphereClient`, implementation of [`ReferenceIdToKeyCache`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ReferenceIdToKeyCache.java) and `productTypes` as parameters. -For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/CaffeineReferenceIdToKeyCacheImpl.java). -Example as shown below: +Utils method `toProductTypeDrafts` requires `projectApiRoot`, implementation of [`ReferenceIdToKeyCache`](#todo) and a list of `productTypes` as parameters. +For cache implementation, you have two options: you can either use your own cache implementation or utilize the class [`CaffeineReferenceIdToKeyCacheImpl`](#todo) provided in the library. This class implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy.Example as shown below: ````java //Implement the cache using library class. @@ -100,37 +105,46 @@ CompletableFuture> productTypeDrafts = ProductTransformUt ##### Syncing from an external resource -- Variant attributes with type `NestedType` do not support the `ResourceIdentifier` yet, +- Attributes with type `AttributeNestedType` do not support the `ResourceIdentifier` yet, for those references you have to provide the `key` value on the `id` field of the reference. This means that calling `getId()` on the reference should return its `key`. ````java -final AttributeDefinitionDraft nestedTypeAttr = AttributeDefinitionDraftBuilder - .of(AttributeDefinitionBuilder - .of("nestedattr", ofEnglish("nestedattr"), - NestedAttributeType.of(ProductType.referenceOfId("product-type-key"))) // note that key is provided in the id field of reference - .build()) - .build(); - -final AttributeDefinitionDraft setOfNestedTypeAttr = AttributeDefinitionDraftBuilder - .of(AttributeDefinitionBuilder - .of("setofNestedAttr", ofEnglish("setofNestedAttr"), - SetAttributeType.of(NestedAttributeType.of(ProductType.referenceOfId("product-type-key")))) - .build()) - .searchable(false) - .build(); +final AttributeDefinitionDraft nestedTypeAttr = AttributeDefinitionDraftBuilder.of() + .type(AttributeNestedTypeBuilder.of() + .typeReference(ProductTypeReferenceBuilder.of().id("product-type-key").build()) // note that key is provided in the id field of reference + .build()) + .name("attrNestedType") + .label(LocalizedString.ofEnglish("attrNestedType")) + .isRequired(true) + .build(); + +final AttributeDefinitionDraft setOfNestedTypeAttr = AttributeDefinitionDraftBuilder.of() + .type(AttributeSetTypeBuilder.of() + .elementType(AttributeNestedTypeBuilder.of() + .typeReference(ProductTypeReferenceBuilder.of() + .id("product-type-key").build()) + .build()) + .build()) + .name("attrNestedType") + .label(LocalizedString.ofEnglish("attrNestedType")) + .isRequired(true) + .build(); final ProductTypeDraft productTypeDraft = - ProductTypeDraftBuilder.of("key", "foo", "description", - Arrays.asList(nestedTypeAttr, setOfNestedTypeAttr)) - .build(); + ProductTypeDraftBuilder.of() + .name("foo") + .description("description") + .key("key") + .attributes(nestedTypeAttr, setOfNestedTypeAttr) + .build(); ```` #### SyncOptions -After the `sphereClient` is setup, a `ProductTypeSyncOptions` should be built as follows: +After the `projectApiRoot` is setup, a `ProductTypeSyncOptions` should be built as follows: ````java // instantiating a ProductTypeSyncOptions -final ProductTypeSyncOptions productTypeSyncOptions = ProductTypeSyncOptionsBuilder.of(sphereClient).build(); +final ProductTypeSyncOptions productTypeSyncOptions = ProductTypeSyncOptionsBuilder.of(projectApiRoot).build(); ```` `SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. @@ -149,7 +163,7 @@ following context about the error-event: ````java final Logger logger = LoggerFactory.getLogger(ProductTypeSync.class); final ProductTypeSyncOptions productTypeSyncOptions = ProductTypeSyncOptionsBuilder - .of(sphereClient) + .of(projectApiRoot) .errorCallback((syncException, draft, productType, updateActions) -> logger.error(new SyncException("My customized message"), syncException)).build(); ```` @@ -166,8 +180,8 @@ following context about the warning message: ````java final Logger logger = LoggerFactory.getLogger(ProductTypeSync.class); final ProductTypeSyncOptions productTypeSyncOptions = ProductTypeSyncOptionsBuilder - .of(sphereClient) - .warningCallback((syncException, draft, productType, updateActions) -> + .of(projectApiRoot) + .warningCallback((syncException, draft, productType) -> logger.warn(new SyncException("My customized message"), syncException)).build(); ```` @@ -182,14 +196,14 @@ update actions array with custom actions or discard unwanted actions. The callba ````java final TriFunction< - List>, ProductTypeDraft, ProductType, List>> + List, ProductTypeDraft, ProductType, List> beforeUpdateProductTypeCallback = (updateActions, newProductTypeDraft, oldProductType) -> updateActions.stream() - .filter(updateAction -> !(updateAction instanceof RemoveAttributeDefinition)) + .filter(updateAction -> !(updateAction instanceof ProductTypeRemoveAttributeDefinitionAction)) .collect(Collectors.toList()); final ProductTypeSyncOptions productTypeSyncOptions = - ProductTypeSyncOptionsBuilder.of(sphereClient).beforeUpdateCallback(beforeUpdateProductTypeCallback).build(); + ProductTypeSyncOptionsBuilder.of(projectApiRoot).beforeUpdateCallback(beforeUpdateProductTypeCallback).build(); ```` ##### beforeCreateCallback @@ -197,19 +211,19 @@ During the sync process, if a product type draft should be created, this callbac * product type draft that should be created -Please refer to [example in product sync document](PRODUCT_SYNC.md#example-set-publish-stage-if-category-references-of-given-product-draft-exists). +Please refer to [example in product sync document](PRODUCT_SYNC.md#beforeCreateCallback). ##### batchSize A number that could be used to set the batch size with which product types are fetched and processed, -as product types are obtained from the target project on the commercetools platform in batches for better performance. The algorithm accumulates up to `batchSize` resources from the input list, then fetches the corresponding product types from the target project on the commecetools platform in a single request. Playing with this option can slightly improve or reduce processing speed. If it is not set, the default batch size is 50 for product type sync. +as product types are obtained from the target project on the commercetools platform in batches for better performance. The algorithm accumulates up to `batchSize` resources from the input list, then fetches the corresponding product types from the target project on the commecetools platform in a single request. Playing with this option can slightly improve or reduce processing speed. If it is not set, the default batch size is `50` for product type sync. ````java final ProductTypeSyncOptions productTypeSyncOptions = - ProductTypeSyncOptionsBuilder.of(sphereClient).batchSize(30).build(); + ProductTypeSyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); ```` ##### cacheSize -In the service classes of the commercetools-sync-java library, we have implemented an in-memory [LRU cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) to store a map used for the reference resolution of the library. +In the service classes of the commercetools-sync-java library, we have implemented an in-memory [LRU cache](#todo) to store a map used for the reference resolution of the library. The cache reduces the reference resolution based calls to the commercetools API as the required fields of a resource will be fetched only one time. These cached fields then might be used by another resource referencing the already resolved resource instead of fetching from commercetools API. It turns out, having the in-memory LRU cache will improve the overall performance of the sync library and commercetools API. which will improve the overall performance of the sync and commercetools API. @@ -217,7 +231,7 @@ Playing with this option can change the memory usage of the library. If it is no ````java final ProductTypeSyncOptions productTypeSyncOptions = - ProductTypeSyncOptionsBuilder.of(sphereClient).cacheSize(5000).build(); + ProductTypeSyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); ```` ### Running the sync @@ -254,8 +268,8 @@ __Note__ The statistics object contains the processing time of the last batch on #### More examples of how to use the sync - 1. [Sync from another CTP project as a source](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/ctpprojectsource/producttypes/ProductTypeSyncIT.java). - 2. [Sync from an external source](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/externalsource/producttypes/ProductTypeSyncIT.java). + 1. [Sync from another CTP project as a source](#todo). + 2. [Sync from an external source](#todo). *Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* @@ -263,7 +277,7 @@ __Note__ The statistics object contains the processing time of the last batch on A utility method provided by the library to compare a ProductType with a new ProductTypeDraft and results in a list of product type update actions. ```java -List> updateActions = ProductTypeSyncUtils.buildActions(productType, productTypeDraft, productTypeSyncOptions); +List updateActions = ProductTypeSyncUtils.buildActions(productType, productTypeDraft, productTypeSyncOptions); ``` ### Build particular update action(s) @@ -271,11 +285,108 @@ List> updateActions = ProductTypeSyncUtils.buildAction Utility methods provided by the library to compare the specific fields of a ProductType and a new ProductTypeDraft, and in turn, build the update action. One example is the `buildChangeNameUpdateAction` which compares names: ````java -Optional> updateAction = ProductTypeUpdateActionUtils.buildChangeNameAction(oldProductType, productTypeDraft); +Optional updateAction = ProductTypeUpdateActionUtils.buildChangeNameAction(oldProductType, productTypeDraft); ```` -More examples of those utils for different fields can be found [here](https://github.com/commercetools/commercetools-sync-java/tree/master/src/test/java/com/commercetools/sync/producttypes/utils/ProductTypeUpdateActionUtilsTest.java). +More examples of those utils for different fields can be found [here](#todo). ## Caveats 1. The order of attribute definitions in the synced product types is not guaranteed. -2. Changing the attribute definition type is not supported. Instead, remove and re-add it with a new type manually, either over API or merchant center. For more information please [check](https://github.com/commercetools/commercetools-sync-java/blob/master/docs/adr/0003-syncing-attribute-type-changes.md). +2. Changing the attribute definition type is not supported. Instead, remove and re-add it with a new type manually, either over API or merchant center. For more information please [check](#todo). + + +## Migration Guide + +The producttype-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with +any HTTP client module. The default one is `commercetools-http-client`. + +```xml + + + LATEST + + + + + com.commercetools.sdk + commercetools-http-client + ${commercetools.version} + + + com.commercetools.sdk + commercetools-sdk-java-api + ${commercetools.version} + + +``` + +### Client configuration and creation + +For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). + +### Signature of ProductTypeSyncOptions + +As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `ProductTypeDraft`, `ProductType` and `ProductTypeUpdateAction` from `package com.commercetools.api.models.product_type.*` + +> Note: Type `UpdateAction` has changed to `ProductTypeUpdateAction`. Make sure you create and supply a specific ProductTypeUpdateAction in `beforeUpdateCallback`. For that you can use the [library-utilities](#todo) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): + +```java +// Example: Create a producttype update action to change name taking the 'newName' of the productTypeDraft + final Function createBeforeUpdateAction = + (newName) -> ProductTypeChangeNameAction.builder().name(newName).build(); + +// Add the change name action to the list of update actions before update is executed + final TriFunction< + List, ProductTypeDraft, ProductType, List> + beforeUpdateProductTypeCallback = + (updateActions, newProductTypeDraft, oldProductType) -> { + final ProductTypeUpdateAction beforeUpdateAction = + createBeforeUpdateAction.apply(newProductTypeDraft.getName()); + updateActions.add(beforeUpdateAction); + return updateActions; + }; +``` + +### Build ProductTypeDraft (syncing from external project) + +The producttype-sync expects a list of `ProductTypeDraft`s to process. If you use java-sync-library to sync your producttypes from any external system into a commercetools platform project you have to convert your data into CTP compatible `ProductTypeDraft` type. This was done in previous version using `DraftBuilder`s. +The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: + +```java +// SDK v1: ProductTypeDraftBuilder.of takes parameters 'key', 'name', 'description' and list of 'attributes' +final ProductTypeDraft productTypeDraft = + ProductTypeDraftBuilder + .of("key", "name", "description", emptyList()) + .build(); + +// SDK v2: ProductTypeDraftBuilder without draftTemplate +final ProductTypeDraft productTypeDraft = + ProductTypeDraftBuilder.of() + .description("product-type-description") + .key("product-type-key") + .name("product-type-name") + .build(); +``` +For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). + +### Query for ProductTypes (syncing from CTP project) + +If you sync producttypes between different commercetools projects you probably use [ProductTypeTransformUtils#toProductTypeDrafts](#todo) to transform `ProductType` into `ProductTypeDraft` which can be used by the producttype-sync. +However, if you need to query `ProductTypes` from a commercetools project instead of passing `ProductTypeQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. +Here's an example: + +```java +// SDK v1: ProductTypeQuery to fetch all producttypes +final ProductTypeQuery query = ProductTypeQuery.of(); + +final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); + +// SDK v2: Create and execute query to fetch all producttypes in one line +final ProductTypePagedQueryResponse result = apiRoot.productTypes().get().executeBlocking().getBody(); +``` +[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. + +### JVM-SDK-V2 migration guide + +On any other needs to migrate your project using jvm-sdk-v2 please refer to its [Migration Guide](https://docs.commercetools.com/sdk/java-sdk-migrate). diff --git a/docs/usage/QUICK_START.md b/docs/usage/QUICK_START.md index ae88df9795..f62fb81803 100644 --- a/docs/usage/QUICK_START.md +++ b/docs/usage/QUICK_START.md @@ -12,7 +12,7 @@ ### 1. Installation -- Make sure you have `JDK 11` installed. +- Make sure you have `JDK 11` or higher installed. - Add the following dependency in your application: - For Maven users: ````xml @@ -20,13 +20,13 @@ com.commercetools commercetools-sync-java - 9.2.3 + 10.0.0 ```` - For Gradle users: ````groovy // Add commercetools-sync-java dependency. -implementation 'com.commercetools:commercetools-sync-java:9.2.3' +implementation 'com.commercetools:commercetools-sync-java:10.0.0' ```` ### 2. Setup Syncing Options @@ -34,7 +34,7 @@ implementation 'com.commercetools:commercetools-sync-java:9.2.3' ```java final Logger logger = LoggerFactory.getLogger(MySync.class); final ProductSyncOptions productsyncOptions = ProductSyncOptionsBuilder - .of(sphereClient) + .of(projectApiRoot) .errorCallback((syncException, draft, productProjection, updateActions) -> logger.error(syncException.getMessage(), syncException)) .warningCallback((exception, oldProductProjection, newResources) -> @@ -66,6 +66,6 @@ implementation 'com.commercetools:commercetools-sync-java:9.2.3' *[Product Sync](PRODUCT_SYNC.md), [ProductType Sync](PRODUCT_TYPE_SYNC.md), [Category Sync](CATEGORY_SYNC.md), [Inventory Sync](INVENTORY_SYNC.md), [Type Sync](TYPE_SYNC.md), [CartDiscount Sync](CART_DISCOUNT_SYNC.md), -[TaxCategory Sync](TAX_CATEGORY_SYNC.md), [State Sync](STATE_SYNC.md), +[TaxCategory Sync](#todo), [State Sync](STATE_SYNC.md), [CustomObject Sync](CUSTOM_OBJECT_SYNC.md), [Customer Sync](CUSTOMER_SYNC.md), -[ShoppingLists Sync](SHOPPING_LIST_SYNC.md)* +[ShoppingLists Sync](#todo)* diff --git a/docs/usage/SHOPPING_LIST_SYNC.md b/docs/usage/SHOPPING_LIST_SYNC.md index 49c402af41..584403dcd7 100644 --- a/docs/usage/SHOPPING_LIST_SYNC.md +++ b/docs/usage/SHOPPING_LIST_SYNC.md @@ -11,7 +11,7 @@ against a [ShoppingListDraft](https://docs.commercetools.com/api/projects/shoppi - [Usage](#usage) - [Prerequisites](#prerequisites) - - [SphereClient](#sphereclient) + - [ProjectApiRoot](#projectapiroot) - [Required Fields](#required-fields) - [Reference Resolution](#reference-resolution) - [Syncing from a commercetools project](#syncing-from-a-commercetools-project) @@ -28,6 +28,12 @@ against a [ShoppingListDraft](https://docs.commercetools.com/api/projects/shoppi - [Build all update actions](#build-all-update-actions) - [Build particular update action(s)](#build-particular-update-actions) - [Caveats](#caveats) +- [Migration Guide](#migration-guide) + - [Client configuration and creation](#client-configuration-and-creation) + - [Signature of ShoppingListSyncOptions](#signature-of-shoppinglistsyncoptions) + - [Build ShoppingListDraft (syncing from external project)](#build-shoppinglistdraft-syncing-from-external-project) + - [Query for ShoppingLists (syncing from CTP project)](#query-for-shoppinglists-syncing-from-ctp-project) + - [JVM-SDK-V2 migration guide](#jvm-sdk-v2-migration-guide) @@ -35,15 +41,20 @@ against a [ShoppingListDraft](https://docs.commercetools.com/api/projects/shoppi ## Usage ### Prerequisites -#### SphereClient +#### ProjectApiRoot -Use the [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/9.2.3/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L45) which apply the best practices for `SphereClient` creation. -If you have custom requirements for the sphere client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). +Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +To create the required `ClientCredentials` for client creation, please utilize the `ClientCredentialsBuilder` provided in the java-sdk-v2 [Client OAUTH2 package](#todo). +If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). ````java -final SphereClientConfig clientConfig = SphereClientConfig.of("project-key", "client-id", "client-secret"); - -final SphereClient sphereClient = ClientConfigurationUtils.createClient(clientConfig); +final ClientCredentials clientCredentials = + new ClientCredentialsBuilder() + .withClientId("client-id") + .withClientSecret("client-secret") + .withScopes("scopes") + .build(); +final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); ```` #### Required Fields @@ -64,37 +75,33 @@ Therefore, in order to resolve the actual ids of those references in the sync pr |Reference Field|Type| |:---|:---| -| `customer` | ResourceIdentifier to a Customer | -| `custom.type` | ResourceIdentifier to a Type | -| `lineItems.custom.type` | ResourceIdentifier to a Type | -| `textLineItems.custom.type ` | ResourceIdentifier to a Type | +| `customer` | CustomerResourceIdentifier | +| `custom.type` | TypeResourceIdentifier | +| `lineItems.custom.type` | TypeResourceIdentifier | +| `textLineItems.custom.type ` | TypeResourceIdentifier | > Note that a reference without the key field will be considered as an existing resource on the target commercetools project and the library will issue an update/create an API request without reference resolution. ##### Syncing from a commercetools project -When syncing from a source commercetools project, you can use [`toShoppingListDrafts`](https://commercetools.github.io/commercetools-sync-java/v/9.2.3/com/commercetools/sync/shoppinglists/utils/ShoppingListTransformUtils.html#toShoppingListDrafts-java.util.List-) +When syncing from a source commercetools project, you can use [`toShoppingListDrafts`](#todo) method that transforms(resolves by querying and caching key-id pairs) and maps from a `ShoppingList` to `ShoppingListDraft` using cache in order to make them ready for reference resolution by the sync, for example: ````java -// Build a ShoppingListQuery for fetching shopping lists from a source CTP project without any references expanded for the sync: -final ShoppingListQuery shoppingListQuery = ShoppingListReferenceResolutionUtils.buildShoppingListQuery(); +// Build a ShoppingListQuery for fetching shopping lists from a source CTP project with expansion for line items for the sync: +final ByProjectKeyShoppingListsGet byProjectKeyShoppingListsGet = client.shoppingLists().addExpand("lineItems[*].variant").get(); // Query all shopping lists (NOTE this is just for example, please adjust your logic) -final List shoppingLists = - CtpQueryUtils - .queryAll(sphereClient, shoppingListQuery, Function.identity()) - .thenApply(fetchedResources -> fetchedResources - .stream() - .flatMap(List::stream) - .collect(Collectors.toList())) +final List states = QueryUtils.queryAll(byProjectKeyShoppingListsGet, + (shoppingLists) -> shoppingLists) + .thenApply(lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())) .toCompletableFuture() .join(); ```` In order to transform and map the `ShoppingList` to `ShoppingListDraft`, -Utils method `toShoppingListDrafts` requires `sphereClient`, implementation of [`ReferenceIdToKeyCache`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ReferenceIdToKeyCache.java) and `shoppingLists` as parameters. -For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/CaffeineReferenceIdToKeyCacheImpl.java). +Utils method `toShoppingListDrafts` requires `projectApiRoot`, implementation of [`ReferenceIdToKeyCache`](#todo) and `shoppingLists` as parameters. +For cache implementation, you can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](#todo). Example as shown below: ````java @@ -102,7 +109,7 @@ Example as shown below: final ReferenceIdToKeyCache referenceIdToKeyCache = new CaffeineReferenceIdToKeyCacheImpl(); //For every reference fetch its key using id, cache it and map from ShoppingList to ShoppingListDraft. With help of the cache same reference keys can be reused. -CompletableFuture> shoppingListDrafts = ShoppingListTransformUtils.toShoppingListDrafts(client, referenceIdToKeyCache, shoppingLists); +final CompletableFuture> shoppingListDrafts = ShoppingListTransformUtils.toShoppingListDrafts(client, referenceIdToKeyCache, shoppingLists); ```` ##### Syncing from an external resource @@ -112,27 +119,39 @@ CompletableFuture> shoppingListDrafts = ShoppingListTran ````java final ShoppingListDraft shoppingListDraft = ShoppingListDraftBuilder - .of(LocalizedString.ofEnglish("name")) + .of() + .name(LocalizedString.ofEnglish("name")) .key("shopping-list-key") - .customer(ResourceIdentifier.ofKey("customer-key")) // note that customer provided with key - .custom(CustomFieldsDraft.ofTypeKeyAndJson("type-key", emptyMap())) // note that custom type provided with key - .lineItems(singletonList(LineItemDraftBuilder - .ofSku("SKU-1", 1L) // note that sku field is set. - .custom(CustomFieldsDraft.ofTypeKeyAndJson("type-key", emptyMap())) // note that custom type provided with key - .build())) - .textLineItems(singletonList( - TextLineItemDraftBuilder.of(LocalizedString.ofEnglish("name"), 1L) // note that name field is set for text line item. - .custom(CustomFieldsDraft.ofTypeKeyAndJson("type-key", emptyMap())) // note that custom type provided with key - .build())) + .customer(CustomerResourceIdentifierBuilder.of().key("customer-key").build()) // note that customer provided with key + .custom(CustomFieldsDraftBuilder.of().type(typeResourceIdentifierBuilder -> typeResourceIdentifierBuilder.key("type-key")) + .fields(fieldContainerBuilder -> fieldContainerBuilder.values(Map.of())).build() + ) // note that custom type provided with key + .lineItems(List.of(ShoppingListLineItemDraftBuilder + .of() + .sku("SKU-1") + .quantity(1L) // note that sku field is set. + .custom(CustomFieldsDraftBuilder.of().type(typeResourceIdentifierBuilder -> typeResourceIdentifierBuilder.key("type-key")) + .fields(fieldContainerBuilder -> fieldContainerBuilder.values(Map.of())).build() + ) // note that custom type provided with key + .build()) + ) + .textLineItems(List.of( + TextLineItemDraftBuilder.of().name(ofEnglish("name")).quantity(1L) // note that name field is set for text line item. + .custom(CustomFieldsDraftBuilder.of().type(typeResourceIdentifierBuilder -> typeResourceIdentifierBuilder.key("type-key")) + .fields(fieldContainerBuilder -> fieldContainerBuilder.values(Map.of())).build() + ) // note that custom type provided with key + .build() + ) + ) .build(); ```` #### SyncOptions -After the `sphereClient` is set up, a `ShoppingListSyncOptions` should be built as follows: +After the `projectApiRoot` is set up, a `ShoppingListSyncOptions` should be built as follows: ````java // instantiating a ShoppingListSyncOptions -final ShoppingListSyncOptions shoppingListSyncOptions = ShoppingListSyncOptionsBuilder.of(sphereClient).build(); +final ShoppingListSyncOptions shoppingListSyncOptions = ShoppingListSyncOptionsBuilder.of(projectApiRoot).build(); ```` `SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. @@ -151,7 +170,7 @@ following context about the error-event: ````java final Logger logger = LoggerFactory.getLogger(ShoppingListSync.class); final ShoppingListSyncOptions shoppingListSyncOptions = ShoppingListSyncOptionsBuilder - .of(sphereClient) + .of(projectApiRoot) .errorCallback((syncException, draft, shoppingList, updateActions) -> logger.error(new SyncException("My customized message"), syncException)).build(); ```` @@ -168,8 +187,8 @@ following context about the warning message: ````java final Logger logger = LoggerFactory.getLogger(ShoppingListSync.class); final ShoppingListSyncOptions shoppingListSyncOptions = ShoppingListSyncOptionsBuilder - .of(sphereClient) - .warningCallback((syncException, draft, shoppingList, updateActions) -> + .of(projectApiRoot) + .warningCallback((syncException, draft, shoppingList) -> logger.warn(new SyncException("My customized message"), syncException)).build(); ```` @@ -183,15 +202,15 @@ update actions array with custom actions or discard unwanted actions. The callba * update actions that were calculated after comparing both ````java -final TriFunction>, ShoppingListDraft, ShoppingList, - List>> beforeUpdateCallback = +final TriFunction, ShoppingListDraft, ShoppingList, + List> beforeUpdateCallback = (updateActions, newShoppingList, oldShoppingList) -> updateActions .stream() - .filter(updateAction -> !(updateAction instanceof SetSlug)) + .filter(updateAction -> !(updateAction instanceof ShoppingListSetSlugAction)) .collect(Collectors.toList()); final ShoppingListSyncOptions shoppingListSyncOptions = ShoppingListSyncOptionsBuilder - .of(CTP_CLIENT) + .of(projectApiRoot) .beforeUpdateCallback(beforeUpdateCallback) .build(); ```` @@ -201,7 +220,7 @@ During the sync process, if a shopping list draft should be created, this callba * shopping list that should be created - Please refer to the [example in the product sync document](https://github.com/commercetools/commercetools-sync-java/blob/master/docs/usage/PRODUCT_SYNC.md#example-set-publish-stage-if-category-references-of-given-product-draft-exists). + Please refer to the [example in the product sync document](#todo). ##### batchSize A number that could be used to set the batch size with which shopping lists are fetched and processed, @@ -210,7 +229,7 @@ from the target project on the commercetools platform in a single request. Playi ````java final ShoppingListSyncOptions shoppingListSyncOptions = - ShoppingListSyncOptionsBuilder.of(sphereClient).batchSize(30).build(); + ShoppingListSyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); ```` ##### cacheSize @@ -222,7 +241,7 @@ Playing with this option can change the memory usage of the library. If it is no ````java final ShoppingListSyncOptions shoppingListSyncOptions = - ShoppingListSyncOptionsBuilder.of(sphereClient).cacheSize(5000).build(); + ShoppingListSyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); ```` ### Running the sync @@ -253,24 +272,24 @@ __Note__ The statistics object contains the processing time of the last batch on #### More examples of how to use the sync - [Sync from an external source](https://github.com/commercetools/commercetools-sync-java/blob/master/src/integration-test/java/com/commercetools/sync/integration/externalsource/shoppinglists/ShoppingListSyncIT.java). + [Sync from an external source](#todo). *Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* ### Build all update actions A utility method provided by the library to compare a `ShoppingList` to a new `ShoppingListDraft`. The results are collected in a list of shopping list update actions. ```java - List> updateActions = ShoppingListSyncUtils.buildActions(shoppingList, shoppingListDraft, shoppingListSyncOptions); + List updateActions = ShoppingListSyncUtils.buildActions(shoppingList, shoppingListDraft, shoppingListSyncOptions); ``` ### Build particular update action(s) The library provides utility methods to compare specific fields of a `ShoppingList` and a new `ShoppingListDraft`, and builds the update action(s) as a result. One example is the `buildChangeNameUpdateAction` which compare shopping list names: ````java - Optional> updateAction = ShoppingListUpdateActionUtils.buildChangeNameAction(shoppingList, shoppingListDraft); + Optional updateAction = ShoppingListUpdateActionUtils.buildChangeNameAction(shoppingList, shoppingListDraft); ```` - More examples for particular update actions can be found in the test scenarios for [ShoppingListUpdateActionUtils](https://github.com/commercetools/commercetools-sync-java/blob/master/src/main/java/com/commercetools/sync/shoppinglists/utils/ShoppingListUpdateActionUtils.java). + More examples for particular update actions can be found in the test scenarios for [ShoppingListUpdateActionUtils](#todo). ## Caveats @@ -278,3 +297,101 @@ __Note__ The statistics object contains the processing time of the last batch on In commercetools shopping lists API, there is no update action to change the `addedAt` field of the `LineItem` and `TextLineItem`, hereby commercetools-java-sync library will not update the `addedAt` value. > For the new LineItem and TextLineItem the `addedAt` values will be added, if the draft has the value set. + + +## Migration Guide + +The shopping-list-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with +any HTTP client module. The default one is `commercetools-http-client`. + +```xml + + + LATEST + + + + + com.commercetools.sdk + commercetools-http-client + ${commercetools.version} + + + com.commercetools.sdk + commercetools-sdk-java-api + ${commercetools.version} + + +``` + +### Client configuration and creation + +For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). + +### Signature of ShoppingListSyncOptions + +As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `ShoppingListDraft`, `ShoppingList` and `ShoppingListUpdateAction` from `package com.commercetools.api.models.shopping_list.*` + +> Note: Type `UpdateAction` has changed to `ShoppingListUpdateAction`. Make sure you create and supply a specific ShoppingListUpdateAction in `beforeUpdateCallback`. For that you can use the [library-utilities](#todo) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): + +```java +// Example: Create a shopping-list update action to change name taking the 'newName' of the shoppingListDraft + final Function createBeforeUpdateAction = + (newName) -> ShoppingListChangeNameAction.builder().name(newName).build(); + +// Add the change name action to the list of update actions before update is executed + final TriFunction< + List, ShoppingListDraft, ShoppingList, List> + beforeUpdateShoppingListCallback = + (updateActions, newShoppingListDraft, oldShoppingList) -> { + final ShoppingListUpdateAction beforeUpdateAction = + createBeforeUpdateAction.apply(newShoppingListDraft.getName()); + updateActions.add(beforeUpdateAction); + return updateActions; + }; +``` + +### Build ShoppingListDraft (syncing from external project) + +The shopping-list-sync expects a list of `ShoppingListDraft`s to process. If you use java-sync-library to sync your shopping-lists from any external system into a commercetools platform project you have to convert your data into CTP compatible `ShoppingListDraft` type. This was done in previous version using `DraftBuilder`s. +The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: + +```java +// SDK v1: ShoppingListDraftBuilder.of takes parameters 'key', 'name' and 1 line item +final ShoppingListDraft shoppingListDraft = + ShoppingListDraftBuilder.of(LocalizedString.ofEnglish("name")) + .key("key") + .plusLineItems(LineItemDraftBuilder.ofSku("sku", Long.valueOf(1)).build()) + .build() + +// SDK v2: ShoppingListDraftBuilder without draftTemplate +final ShoppingListDraft shoppingListDraft = + ShoppingListDraftBuilder.of() + .name(LocalizedString.ofEnglish("name")) + .key("product-type-key") + .lineItems(ShoppingListLineItemDraftBuilder.of().sku("SKU-1").quantity(1L).build()) + .build(); +``` +For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). + +### Query for ShoppingLists (syncing from CTP project) + +If you sync shopping lists between different commercetools projects you probably use [ShoppingListTransformUtils#toShoppingListDrafts](#todo) to transform `ShoppingList` into `ShoppingListDraft` which can be used by the shopping-list-sync. +However, if you need to query `ShoppingLists` from a commercetools project instead of passing `ShoppingListQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. +Here's an example: + +```java +// SDK v1: ShoppingListQuery to fetch all shopping lists +final ShoppingListQuery query = ShoppingListQuery.of(); + +final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); + +// SDK v2: Create and execute query to fetch all shopping lists in one line +final ShoppingListPagedQueryResponse result = apiRoot.shoppingLists().get().executeBlocking().getBody(); +``` +[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. + +### JVM-SDK-V2 migration guide + +On any other needs to migrate your project using jvm-sdk-v2 please refer to its [Migration Guide](https://docs.commercetools.com/sdk/java-sdk-migrate). diff --git a/docs/usage/STATE_SYNC.md b/docs/usage/STATE_SYNC.md index b33649ce75..b969342189 100644 --- a/docs/usage/STATE_SYNC.md +++ b/docs/usage/STATE_SYNC.md @@ -1,16 +1,15 @@ # State Sync The module used for importing/syncing States into a commercetools project. -It also provides utilities for generating update actions based on the comparison a [State](https://docs.commercetools.com/http-api-projects-states#states) (which basically represents what commercetools already has) -against a [StateDraft](https://docs.commercetools.com/http-api-projects-states#statedraft) (which represents a new version of the state supplied by the user). +It also provides utilities for generating update actions based on the comparison a [State](https://docs.commercetools.com/api/projects/states#state) (which basically represents what commercetools already has) +against a [StateDraft](https://docs.commercetools.com/api/projects/states#statedraft) (which represents a new version of the state supplied by the user). - - [Usage](#usage) - - [Prerequisites](#prerequisites) - - [SphereClient](#sphereclient) + - [Prerequisites](#prerequisites) + - [ProjectApiRoot](#projectapiroot) - [Required Fields](#required-fields) - [Reference Resolution](#reference-resolution) - [Syncing from a commercetools project](#syncing-from-a-commercetools-project) @@ -27,21 +26,34 @@ against a [StateDraft](https://docs.commercetools.com/http-api-projects-states#s - [More examples of how to use the sync](#more-examples-of-how-to-use-the-sync) - [Build all update actions](#build-all-update-actions) - [Build particular update action(s)](#build-particular-update-actions) +- [Migration Guide](#migration-guide) + - [Client configuration and creation](#client-configuration-and-creation) + - [Signature of StateSyncOptions](#signature-of-statesyncoptions) + - [Build StateDraft (syncing from external project)](#build-statedraft-syncing-from-external-project) + - [Query for states (syncing from CTP project)](#query-for-states-syncing-from-ctp-project) + - [Referencing other states in transitions](#referencing-other-states-in-transitions) ## Usage -#### Prerequisites -#### SphereClient +### Prerequisites -Use the [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/9.2.3/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L45) which apply the best practices for `SphereClient` creation. -If you have custom requirements for the sphere client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). +#### ProjectApiRoot -````java -final SphereClientConfig clientConfig = SphereClientConfig.of("project-key", "client-id", "client-secret"); -final SphereClient sphereClient = ClientConfigurationUtils.createClient(clientConfig); +Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](#todo) +If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). + +````java +final ClientCredentials clientCredentials = + new ClientCredentialsBuilder() + .withClientId("client-id") + .withClientSecret("client-secret") + .withScopes("scopes") + .build(); +final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); ```` #### Required Fields @@ -50,44 +62,38 @@ The following fields are **required** to be set in, otherwise, they won't be mat |Draft|Required Fields|Note| |---|---|---| -| [StateDraft](https://docs.commercetools.com/http-api-projects-states#statedraft)| `key` | Also, the states in the target project are expected to have the `key` fields set. | +| [StateDraft](https://docs.commercetools.com/api/projects/states#statedraft)| `key` | Also, the states in the target project are expected to have the `key` fields set. | #### Reference Resolution -`Transitions` are a way to describe possible transformations of the current state to other states of the same type (for example Initial -> Shipped). When performing a [SetTransitions](https://docs.commercetools.com/api/projects/states#set-transitions), an array of [Reference](https://docs.commercetools.com/api/types#reference) to State is needed. -In commercetools, a reference can be created by providing the key instead of the ID with the type [ResourceIdentifier](https://docs.commercetools.com/api/types#resourceidentifier). -When the reference key is provided with a `ResourceIdentifier`, the sync will resolve the resource with the given key and use the ID of the found resource to create or update a reference. -Currently, commercetools API does not support the [ResourceIdentifier](https://docs.commercetools.com/api/types#resourceidentifier) for the `transitions`, for those `transition` references you have to provide the `key` value on the `id` field of the reference. This means that calling `getId()` on the -reference should return its `key`. +`Transitions` are a way to describe possible transformations of the current state to other states of the same type (for example Initial -> Shipped). When performing a [SetTransitions](https://docs.commercetools.com/api/projects/states#set-transitions), an array of [ResourceIdentifiers](https://docs.commercetools.com/api/projects/states#ctp:api:type:StateResourceIdentifier) to State is needed. +In commercetools, a [ResourceIdentifier](https://docs.commercetools.com/api/projects/states#ctp:api:type:StateResourceIdentifier) can be created by providing either the key or the ID. +When the key to a referenced state is provided with a `ResourceIdentifier`, the sync will resolve the resource with the given key and use the ID of the found resource to create or update a reference. -|Reference Field|Type| -|:---|:---| -| `transitions` | Array of Reference to State | +| ResourceIdentifier Field | Type | +|:-------------------------|:------------------------------------------| +| `transitions` | Array of StateResourceIdentifiers | ##### Syncing from a commercetools project -When syncing from a source commercetools project, you can use [`toStateDrafts`](https://commercetools.github.io/commercetools-sync-java/v/9.2.3/com/commercetools/sync/states/utils/StateTransformUtils.html#toStateDrafts-java.util.List-) +When syncing from a source commercetools project, you can use [`toStateDrafts`](#todo) method that transforms(resolves by querying and caching key-id pairs) and maps from a `State` to `StateDraft` using cache in order to make them ready for reference resolution by the sync, for example: ````java -// Build a StateQuery for fetching shopping lists from a source CTP project without any references expanded for the sync: -final StateQuery stateQuery = StateQuery.of(); +// Build a ByProjectKeyStatesGet for fetching states from a source CTP project without any references expanded for the sync: +final ByProjectKeyStatesGet byProjectKeyStatesGet = client.states().get(); // Query all states (NOTE this is just for example, please adjust your logic) -final List states = - CtpQueryUtils - .queryAll(sphereClient, stateQuery, Function.identity()) - .thenApply(fetchedResources -> fetchedResources - .stream() - .flatMap(List::stream) - .collect(Collectors.toList())) +final List states = QueryUtils.queryAll(byProjectKeyStatesGet, + (states) -> states) + .thenApply(lists -> lists.stream().flatMap(List::stream).collect(Collectors.toList())) .toCompletableFuture() .join(); ```` In order to transform and map the `State` to `StateDraft`, -Utils method `toStateDrafts` requires `sphereClient`, implementation of [`ReferenceIdToKeyCache`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/ReferenceIdToKeyCache.java) and `states` as parameters. -For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](https://github.com/commercetools/commercetools-sync-java/tree/master/src/main/java/com/commercetools/sync/commons/utils/CaffeineReferenceIdToKeyCacheImpl.java). +Utils method `toStateDrafts` requires `projectApiRoot`, implementation of [`ReferenceIdToKeyCache`](#todo) and `states` as parameters. +For cache implementation, You can use your own cache implementation or use the class in the library - which implements the cache using caffeine library with an LRU (Least Recently Used) based cache eviction strategy[`CaffeineReferenceIdToKeyCacheImpl`](#todo). Example as shown below: ````java @@ -95,26 +101,29 @@ Example as shown below: final ReferenceIdToKeyCache referenceIdToKeyCache = new CaffeineReferenceIdToKeyCacheImpl(); //For every reference fetch its key using id, cache it and map from State to StateDraft. With help of the cache same reference keys can be reused. -CompletableFuture> stateDrafts = StateTransformUtils.toStateDrafts(client, referenceIdToKeyCache, states); +final CompletableFuture> stateDrafts = StateTransformUtils.toStateDrafts(client, referenceIdToKeyCache, states); ```` ##### Syncing from an external resource +- When syncing from an external resource, `ResourceIdentifier`s with their `key`s have to be supplied as following example: + ````java -final StateDraft stateDraft = StateDraftBuilder - .of("state-key", StateType.LINE_ITEM_STATE) - .transitions(asSet(State.referenceOfId("another-state-key"))) // note that state transition key is provided in the id field of reference. - .build(); +final StateDraft stateDraft = StateDraftBuilder.of() + .key("state-key") + .type(StateTypeEnum.LINE_ITEM_STATE) + .transitions(StateResourceIdentifierBuilder.of().key("another-state-key").build()) + .build(); ```` #### SyncOptions -After the `sphereClient` is set up, a `StateSyncOptions` should be built as follows: +After the `projectApiRoot` is set up, a `StateSyncOptions` should be built as follows: ````java // instantiating a StateSyncOptions - final StateSyncOptions stateSyncOptions = StateSyncOptionsBuilder.of(sphereClient).build(); + final StateSyncOptions stateSyncOptions = StateSyncOptionsBuilder.of(projectApiRoot).build(); ```` `SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. @@ -133,7 +142,7 @@ following context about the error-event: ````java final Logger logger = LoggerFactory.getLogger(StateSync.class); final StateSyncOptions stateSyncOptions = StateSyncOptionsBuilder - .of(sphereClient) + .of(projectApiRoot) .errorCallback((syncException, draft, state, updateActions) -> logger.error(new SyncException("My customized message"), syncException)).build(); ```` @@ -151,8 +160,8 @@ following context about the warning message: ````java final Logger logger = LoggerFactory.getLogger(StateSync.class); final StateSyncOptions stateSyncOptions = StateSyncOptionsBuilder - .of(sphereClient) - .warningCallback((syncException, draft, state, updateActions) -> + .of(projectApiRoot) + .warningCallback((syncException, draft, state) -> logger.warn(new SyncException("My customized message"), syncException)).build(); ```` @@ -167,14 +176,14 @@ update actions array with custom actions or discard unwanted actions. The callba ````java final TriFunction< - List>, StateDraft, State, List>> + List, StateDraft, State, List> beforeUpdateStateCallback = (updateActions, newStateDraft, oldState) -> updateActions.stream() - .filter(updateAction -> !(updateAction instanceof RemoveRoles)) + .filter(updateAction -> !(updateAction instanceof StateRemoveRolesAction)) .collect(Collectors.toList()); final StateSyncOptions stateSyncOptions = - StateSyncOptionsBuilder.of(sphereClient).beforeUpdateCallback(beforeUpdateStateCallback).build(); + StateSyncOptionsBuilder.of(projectApiRoot).beforeUpdateCallback(beforeUpdateStateCallback).build(); ```` ##### beforeCreateCallback @@ -191,7 +200,7 @@ from the target project on the commecetools platform in a single request. Playin ````java final StateSyncOptions stateSyncOptions = - StateSyncOptionsBuilder.of(sphereClient).batchSize(30).build(); + StateSyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); ```` ##### cacheSize @@ -203,7 +212,7 @@ Playing with this option can change the memory usage of the library. If it is no ````java final StateSyncOptions stateSyncOptions = - StateSyncOptionsBuilder.of(sphereClient).cacheSize(5000).build(); + StateSyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); ```` @@ -277,11 +286,11 @@ It being persisted as `CustomObject` means that the referenced StateDrafts with As soon, as the referenced StateDrafts are supplied to the sync, the draft will be created/updated and the `CustomObject` will be removed from the target project. -Keeping the old custom objects around forever can negatively influence the performance of your project and the time it takes to restore it from a backup. Deleting unused data ensures the best performance for your project. Please have a look into the [Cleanup guide](CLEANUP_GUIDE.md) to cleanup old unresolved custom objects. +Keeping the old custom objects around forever can negatively influence the performance of your project and the time it takes to restore it from a backup. Deleting unused data ensures the best performance for your project. Please have a look into the [Cleanup guide](CLEANUP_GUIDE.md) to cleanup old unresolved custom objects. #### More examples of how to use the sync - 1. [Sync usages](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/externalsource/states/StateSyncIT.java). + 1. [Sync usages](#todo). *Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* @@ -291,7 +300,7 @@ Keeping the old custom objects around forever can negatively influence the perfo A utility method provided by the library to compare a `State` with a new `StateDraft` and results in a list of state update actions. update actions. ```java -List> updateActions = StateSyncUtils.buildActions(state, stateDraft, stateSyncOptions); +List updateActions = StateSyncUtils.buildActions(state, stateDraft, stateSyncOptions); ``` ### Build particular update action(s) @@ -299,6 +308,110 @@ List> updateActions = StateSyncUtils.buildActions(state, sta Utility methods provided by the library to compare the specific fields of a `State` and a new `StateDraft`, and in turn builds the update action. One example is the `buildSetNameAction` which compares names: ````java -Optional> updateAction = StateUpdateActionUtils.buildSetNameAction(oldState, stateDraft); +Optional updateAction = StateUpdateActionUtils.buildSetNameAction(oldState, stateDraft); ```` -More examples of those utils for different types can be found [here](https://github.com/commercetools/commercetools-sync-java/tree/master/src/test/java/com/commercetools/sync/states/utils/StateUpdateActionUtilsTest.java). +More examples of those utils for different types can be found [here](#todo). + + +## Migration Guide + +The state-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with +any HTTP client module. The default one is `commercetools-http-client`. + +```xml + + + LATEST + + + + + com.commercetools.sdk + commercetools-http-client + ${commercetools.version} + + + com.commercetools.sdk + commercetools-sdk-java-api + ${commercetools.version} + + + +``` + +### Client configuration and creation + +For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). + +### Signature of StateSyncOptions + +As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `State`, `StateDraft` and `StateUpdateAction` from `package com.commercetools.api.models.state.*` + +> Note: Type `StateUpdateAction` has changed to `StateUpdateAction`. Make sure you create and supply a specific StateUpdateAction in `beforeUpdateCallback`. For that you can use the [library-utilities](#todo) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): + +```java +// Example: Create a state update action to change name taking the 'newName' of the stateDraft + final Function createBeforeUpdateAction = + (newName) -> StateSetNameAction.builder().name(newName).build(); + +// Add the change name action to the list of update actions before update is executed + final TriFunction< + List, StateDraft, State, List> + beforeUpdateStateCallback = + (updateActions, newStateDraft, oldState) -> { + final StateUpdateAction beforeUpdateAction = + createBeforeUpdateAction.apply(newStateDraft.getName()); + updateActions.add(beforeUpdateAction); + return updateActions; + }; +``` + +### Build StateDraft (syncing from external project) + +The state-sync expects a list of `StateDraft`s to process. If you use java-sync-library to sync your states from any external system into a commercetools platform project you have to convert your data into CTP compatible `StateDraft` type. This was done in previous version using `DraftBuilder`s. +The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: + +```java +// StateDraftBuilder in v1 takes parameters 'key', 'type' +final StateDraft stateDraft = + StateDraftBuilder.of("key", StateType.LINE_ITEM_STATE) + .name(ofEnglish("state-name")) + .description(ofEnglish("state-desc")) + .roles(Collections.singleton(StateRole.RETURN)) + .initial(false) + .build(); + +// StateDraftBuilder in v2 +final StateDraft stateDraft = + StateDraftBuilder.of() + .key("key") + .type(StateTypeEnum.LINE_ITEM_STATE) + .name(ofEnglish("state-name")) + .description(ofEnglish("state-desc")) + .roles(StateRoleEnum.RETURN) + .initial(false) + .build(); +``` +For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). + +### Query for states (syncing from CTP project) + +If you sync states between different commercetools projects you probably use [StateTransformUtils#toStateDrafts](#todo) to transform `State` into `StateDraft` which can be used by the state-sync. +However, if you need to query `states` from a commercetools project instead of passing `StateQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. +Here's an example: + +```java +// SDK v1: StateQuery to fetch all states +final StateQuery query = StateQuery.of(); + +final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); + +// SDK v2: Create and execute query to fetch all states in one line +final StatePagedQueryResponse result = apiRoot.states().get().executeBlocking().getBody(); +``` +[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. + +### Referencing other states in transitions + +When you use references to other states in the field `transitions`, the state-sync needs to do the reference resolution process. In the previous java-sdk-v1 it was required to provide the `key` value on the `id` field of the reference. In the current java-sdk-v2 you must provide the `key` field in `StateResourceIdentifier`. For detailed information see the [Reference resolution section](#reference-resolution). diff --git a/docs/usage/TAX_CATEGORY_SYNC.md b/docs/usage/TAX_CATEGORY_SYNC.md index 9fe2d526da..ed2c53c1aa 100644 --- a/docs/usage/TAX_CATEGORY_SYNC.md +++ b/docs/usage/TAX_CATEGORY_SYNC.md @@ -1,16 +1,15 @@ # Tax Category Sync Allows importing/syncing TaxCategory into a commercetools project. -It also provides utilities for generating update actions based on the comparison of a [TaxCategory](https://docs.commercetools.com/http-api-projects-taxCategories#taxcategory) -against a [TaxCategoryDraft](https://docs.commercetools.com/http-api-projects-taxCategories#taxcategorydraft). +It also provides utilities for generating update actions based on the comparison of a [TaxCategory](https://docs.commercetools.com/api/projects/taxCategories#taxcategory) +against a [TaxCategoryDraft](https://docs.commercetools.com/api/projects/taxCategories#taxcategorydraft). - - [Usage](#usage) - [Prerequisites](#prerequisites) - - [SphereClient](#sphereclient) + - [ProjectApiRoot](#projectapiroot) - [Required Fields](#required-fields) - [SyncOptions](#syncoptions) - [errorCallback](#errorcallback) @@ -23,6 +22,12 @@ against a [TaxCategoryDraft](https://docs.commercetools.com/http-api-projects-ta - [More examples of how to use the sync](#more-examples-of-how-to-use-the-sync) - [Build all update actions](#build-all-update-actions) - [Build particular update action(s)](#build-particular-update-actions) +- [Migration Guide](#migration-guide) + - [Client configuration and creation](#client-configuration-and-creation) + - [Signature of TaxCategorySyncOptions](#signature-of-taxcategorysyncoptions) + - [Build TaxCategoryDraft (syncing from external project)](#build-taxcategorydraft-syncing-from-external-project) + - [Query for TaxCategories (syncing from CTP project)](#query-for-taxcategories-syncing-from-ctp-project) + - [JVM-SDK-V2 migration guide](#jvm-sdk-v2-migration-guide) @@ -30,14 +35,20 @@ against a [TaxCategoryDraft](https://docs.commercetools.com/http-api-projects-ta ### Prerequisites -#### SphereClient -Use the [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/9.2.3/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L45) which apply the best practices for `SphereClient` creation. -If you have custom requirements for the sphere client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). +#### ProjectApiRoot -````java -final SphereClientConfig clientConfig = SphereClientConfig.of("project-key", "client-id", "client-secret"); +Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](#todo) +If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). -final SphereClient sphereClient = ClientConfigurationUtils.createClient(clientConfig); +````java +final ClientCredentials clientCredentials = + new ClientCredentialsBuilder() + .withClientId("client-id") + .withClientSecret("client-secret") + .withScopes("scopes") + .build(); +final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); ```` #### Required Fields @@ -46,14 +57,14 @@ The following fields are **required** to be set in, otherwise, they won't be mat |Draft|Required Fields|Note| |---|---|---| -| [TaxCategoryDraft](https://docs.commercetools.com/http-api-projects-taxCategories#taxcategorydraft) | `key` | Also, the tax categories in the target project are expected to have the `key` fields set. | +| [TaxCategoryDraft](https://docs.commercetools.com/api/projects/taxCategories#taxcategorydraft) | `key` | Also, the tax categories in the target project are expected to have the `key` fields set. | #### SyncOptions -After the `sphereClient` is set up, a `TaxCategorySyncOptions` should be built as follows: +After the `projectApiRoot` is set up, a `TaxCategorySyncOptions` should be built as follows: ````java // instantiating a TaxCategorySyncOptions -final TaxCategorySyncOptions taxCategorySyncOptions = TaxCategorySyncOptionsBuilder.of(sphereClient).build(); +final TaxCategorySyncOptions taxCategorySyncOptions = TaxCategorySyncOptionsBuilder.of(projectApiRoot).build(); ```` `SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. @@ -72,7 +83,7 @@ following context about the error-event: ````java final Logger logger = LoggerFactory.getLogger(TaxCategorySync.class); final TaxCategorySyncOptions taxCategorySyncOptions = TaxCategorySyncOptionsBuilder - .of(sphereClient) + .of(projectApiRoot) .errorCallback((syncException, draft, taxCategory, updateActions) -> logger.error(new SyncException("My customized message"), syncException)).build(); ```` @@ -89,8 +100,8 @@ following context about the warning message: ````java final Logger logger = LoggerFactory.getLogger(TaxCategorySync.class); final TaxCategorySyncOptions taxCategorySyncOptions = TaxCategorySyncOptionsBuilder - .of(sphereClient) - .warningCallback((syncException, draft, taxCategory, updateActions) -> + .of(projectApiRoot) + .warningCallback((syncException, draft, taxCategory) -> logger.warn(new SyncException("My customized message"), syncException)).build(); ```` @@ -105,14 +116,14 @@ update actions array with custom actions or discard unwanted actions. The callba ````java final TriFunction< - List>, TaxCategoryDraft, TaxCategory, List>> + List, TaxCategoryDraft, TaxCategory, List> beforeUpdateTaxCategoryCallback = (updateActions, newTaxCategoryDraft, oldTaxCategory) -> updateActions.stream() - .filter(updateAction -> !(updateAction instanceof RemoveTaxRate)) + .filter(updateAction -> !(updateAction instanceof TaxCategoryRemoveTaxRateAction)) .collect(Collectors.toList()); final TaxCategorySyncOptions taxCategorySyncOptions = - TaxCategorySyncOptionsBuilder.of(sphereClient).beforeUpdateCallback(beforeUpdateTaxCategoryCallback).build(); + TaxCategorySyncOptionsBuilder.of(projectApiRoot).beforeUpdateCallback(beforeUpdateTaxCategoryCallback).build(); ```` ##### beforeCreateCallback @@ -120,7 +131,7 @@ During the sync process, if a tax category draft should be created, this callbac * tax category draft that should be created -Please refer to [example in product sync document](PRODUCT_SYNC.md#example-set-publish-stage-if-category-references-of-given-product-draft-exists). +Please refer to [example in product sync document](PRODUCT_SYNC.md#beforecreatecallback). ##### batchSize A number that could be used to set the batch size with which tax categories are fetched and processed, @@ -128,7 +139,7 @@ as tax categories are obtained from the target project on the commercetools plat ````java final TaxCategorySyncOptions taxCategorySyncOptions = - TaxCategorySyncOptionsBuilder.of(sphereClient).batchSize(30).build(); + TaxCategorySyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); ```` ##### cacheSize @@ -140,7 +151,7 @@ Playing with this option can change the memory usage of the library. If it is no ````java final TaxCategorySyncOptions taxCategorySyncOptions = - TaxCategorySyncOptionsBuilder.of(sphereClient).cacheSize(5000).build(); + TaxCategorySyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); ```` ### Running the sync @@ -170,7 +181,7 @@ __Note__ The statistics object contains the processing time of the last batch on #### More examples of how to use the sync -- [Sync from an external source](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/externalsource/taxcategories/TaxCategorySyncIT.java). +- [Sync from an external source](#todo). *Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* @@ -178,7 +189,7 @@ __Note__ The statistics object contains the processing time of the last batch on A utility method provided by the library to compare a `TaxCategory` with a new `TaxCategoryDraft` and results in a list of tax category update actions. ```java -List> updateActions = TaxCategorySyncUtils.buildActions(taxCategory, taxCategoryDraft, taxCategorySyncOptions); +List updateActions = TaxCategorySyncUtils.buildActions(taxCategory, taxCategoryDraft, taxCategorySyncOptions); ``` ### Build particular update action(s) @@ -186,6 +197,105 @@ List> updateActions = TaxCategorySyncUtils.buildAction Utility methods provided by the library to compare the specific fields of a `TaxCategory` and a new `TaxCategoryDraft`, and in turn builds the update action. One example is the `buildChangeNameUpdateAction` which compares names: ````java -Optional> updateAction = TaxCategoryUpdateActionUtils.buildChangeNameAction(oldTaxCategory, taxCategoryDraft); +Optional updateAction = TaxCategoryUpdateActionUtils.buildChangeNameAction(oldTaxCategory, taxCategoryDraft); ```` -More examples of those utils for different tax categories can be found [here](https://github.com/commercetools/commercetools-sync-java/tree/master/src/test/java/com/commercetools/sync/taxcategories/utils/TaxCategoryUpdateActionUtilsTest.java). +More examples of those utils for different tax categories can be found [here](#todo). + +## Migration Guide + +The tax-category-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with +any HTTP client module. The default one is `commercetools-http-client`. + +```xml + + + LATEST + + + + + com.commercetools.sdk + commercetools-http-client + ${commercetools.version} + + + com.commercetools.sdk + commercetools-sdk-java-api + ${commercetools.version} + + + +``` + +### Client configuration and creation + +For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). + +### Signature of TaxCategorySyncOptions + +As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `TaxCategoryDraft`, `TaxCategory` and `TaxCategoryUpdateAction` from `package com.commercetools.api.models.tax_category.*` + +> Note: Type `UpdateAction` has changed to `TaxCategoryUpdateAction`. Make sure you create and supply a specific TaxCategoryUpdateAction in `beforeUpdateCallback`. For that you can use the [library-utilities](#todo) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): + +```java +// Example: Create a tax-category update action to change name taking the 'newName' of the taxCategoryDraft + final Function changeNameBeforeUpdateAction = + (newName) -> TaxCategoryChangeNameAction.builder().name(newName).build(); + +// Add the change name action to the list of update actions before update is executed + final TriFunction< + List, TaxCategoryDraft, TaxCategory, List> + beforeUpdateTypeCallback = + (updateActions, newTaxCategoryDraft, oldTaxCategory) -> { + final TaxCategoryUpdateAction beforeUpdateAction = + changeNameBeforeUpdateAction.apply(newTaxCategoryDraft.getName()); + updateActions.add(beforeUpdateAction); + return updateActions; + }; +``` + +### Build TaxCategoryDraft (syncing from external project) + +The tax-category-sync expects a list of `TaxCategoryDraft`s to process. If you use java-sync-library to sync your types from any external system into a commercetools platform project you have to convert your data into CTP compatible `TaxCategoryDraft` type. This was done in previous version using `DraftBuilder`s. +The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: + +```java +// TaxCategoryDraftBuilder in v1 takes parameters 'name', 'taxRates' and 'description' +final TaxCategoryDraft taxCategoryDraft = + TaxCategoryDraftBuilder + .of("name", emptyList(), "description") + .key("key") + .build(); + +// TaxCategoryDraftBuilder in v2. +final TaxCategoryDraft taxCategoryDraft = + TaxCategoryDraftBuilder.of() + .key("key") + .name("name") + .rates(emptyList()) + .description("description") + .build(); +``` +For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). + +### Query for TaxCategories (syncing from CTP project) + +If you sync types between different commercetools projects you have to transform `TaxCategory` into `TaxCategoryDraft`. +However, if you need to query `TaxCategory` from a commercetools project instead of passing `TaxCategoryQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. +Here's an example: + +```java +// SDK v1: TaxCategoryQuery to fetch all taxCategories +final TaxCategoryQuery query = TaxCategoryQuery.of(); + +final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); + +// SDK v2: Create and execute query to fetch all tax-categories in one line +final TaxCategoryPagedQueryResponse result = apiRoot.taxCategories().get().executeBlocking().getBody(); +``` +[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. + +### JVM-SDK-V2 migration guide + +On any other needs to migrate your project using jvm-sdk-v2 please refer to it's [Migration Guide](https://docs.commercetools.com/sdk/java-sdk-migrate). diff --git a/docs/usage/TYPE_SYNC.md b/docs/usage/TYPE_SYNC.md index 991418aca1..dddb348e1c 100644 --- a/docs/usage/TYPE_SYNC.md +++ b/docs/usage/TYPE_SYNC.md @@ -1,8 +1,8 @@ # Type Sync The module used for importing/syncing Types into a commercetools project. -It also provides utilities for generating update actions based on the comparison of a [Type](https://docs.commercetools.com/http-api-projects-types.html#type) -against a [TypeDraft](https://docs.commercetools.com/http-api-projects-types.html#typedraft). +It also provides utilities for generating update actions based on the comparison of a [Type](https://docs.commercetools.com/api/projects/types#type) +against a [TypeDraft](https://docs.commercetools.com/api/projects/types#typedraft). @@ -31,15 +31,21 @@ against a [TypeDraft](https://docs.commercetools.com/http-api-projects-types.htm ## Usage ### Prerequisites -#### SphereClient -Use the [ClientConfigurationUtils](https://github.com/commercetools/commercetools-sync-java/blob/9.2.3/src/main/java/com/commercetools/sync/commons/utils/ClientConfigurationUtils.java#L45) which apply the best practices for `SphereClient` creation. -If you have custom requirements for the sphere client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). +#### ProjectApiRoot -````java -final SphereClientConfig clientConfig = SphereClientConfig.of("project-key", "client-id", "client-secret"); +Use the [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +To create `ClientCredentials` which are required for creating a client please use the `ClientCredentialsBuilder` provided in java-sdk-v2 [Client OAUTH2 package](#todo) +If you have custom requirements for the client creation, have a look into the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md). -final SphereClient sphereClient = ClientConfigurationUtils.createClient(clientConfig); +````java +final ClientCredentials clientCredentials = + new ClientCredentialsBuilder() + .withClientId("client-id") + .withClientSecret("client-secret") + .withScopes("scopes") + .build(); +final ProjectApiRoot apiRoot = ClientConfigurationUtils.createClient("project-key", clientCredentials, "auth-url", "api-url"); ```` #### Required Fields @@ -48,14 +54,14 @@ The following fields are **required** to be set in, otherwise, they won't be mat |Draft|Required Fields|Note| |---|---|---| -| [TypeDraft](https://docs.commercetools.com/http-api-projects-types.html#typedraft) | `key` | Also, the types in the target project are expected to have the `key` fields set. | +| [TypeDraft](https://docs.commercetools.com/api/projects/types#typedraft) | `key` | Also, the types in the target project are expected to have the `key` fields set. | #### SyncOptions -After the `sphereClient` is set up, a `TypeSyncOptions` should be built as follows: +After the `projectApiRoot` is set up, a `TypeSyncOptions` should be built as follows: ````java // instantiating a TypeSyncOptions -final TypeSyncOptions typeSyncOptions = TypeSyncOptionsBuilder.of(sphereClient).build(); +final TypeSyncOptions typeSyncOptions = TypeSyncOptionsBuilder.of(projectApiRoot).build(); ```` `SyncOptions` is an object which provides a place for users to add certain configurations to customize the sync process. @@ -74,7 +80,7 @@ following context about the error-event: ````java final Logger logger = LoggerFactory.getLogger(TypeSync.class); final TypeSyncOptions typeSyncOptions = TypeSyncOptionsBuilder - .of(sphereClient) + .of(projectApiRoot) .errorCallback((syncException, draft, type, updateActions) -> logger.error(new SyncException("My customized message"), syncException)).build(); ```` @@ -91,8 +97,8 @@ following context about the warning message: ````java final Logger logger = LoggerFactory.getLogger(TypeSync.class); final TypeSyncOptions typeSyncOptions = TypeSyncOptionsBuilder - .of(sphereClient) - .warningCallback((syncException, draft, type, updateActions) -> + .of(projectApiRoot) + .warningCallback((syncException, draft, type) -> logger.warn(new SyncException("My customized message"), syncException)).build(); ```` @@ -106,15 +112,16 @@ update actions array with custom actions or discard unwanted actions. The callba * update actions that were calculated after comparing both ````java +// Example: Ignore update actions that remove field definition final TriFunction< - List>, TypeDraft, Type, List>> + List, TypeDraft, Type, List> beforeUpdateTypeCallback = (updateActions, newTypeDraft, oldType) -> updateActions.stream() - .filter(updateAction -> !(updateAction instanceof RemoveFieldDefinition)) + .filter(updateAction -> !(updateAction instanceof TypeRemoveFieldDefinitionAction)) .collect(Collectors.toList()); final TypeSyncOptions typeSyncOptions = - TypeSyncOptionsBuilder.of(sphereClient).beforeUpdateCallback(beforeUpdateTypeCallback).build(); + TypeSyncOptionsBuilder.of(projectApiRoot).beforeUpdateCallback(beforeUpdateTypeCallback).build(); ```` ##### beforeCreateCallback @@ -122,7 +129,7 @@ During the sync process, if a type draft should be created, this callback can be * type draft that should be created -Please refer to [example in product sync document](PRODUCT_SYNC.md#example-set-publish-stage-if-category-references-of-given-product-draft-exists). +Please refer to [example in product sync document](PRODUCT_SYNC.md#beforecreatecallback). ##### batchSize A number that could be used to set the batch size with which types are fetched and processed, @@ -130,7 +137,7 @@ as types are obtained from the target project on commercetools platform in batch ````java final TypeSyncOptions typeSyncOptions = - TypeSyncOptionsBuilder.of(sphereClient).batchSize(30).build(); + TypeSyncOptionsBuilder.of(projectApiRoot).batchSize(30).build(); ```` ##### cacheSize @@ -142,7 +149,7 @@ Playing with this option can change the memory usage of the library. If it is no ````java final TypeSyncOptions typeSyncOptions = - TypeSyncOptionsBuilder.of(sphereClient).cacheSize(5000).build(); + TypeSyncOptionsBuilder.of(projectApiRoot).cacheSize(5000).build(); ```` @@ -175,12 +182,12 @@ __Note__ The statistics object contains the processing time of the last batch on 1. If two matching `fieldDefinition`s (old and new) on the matching `type`s (old and new) have a different `FieldType`, the sync will **remove** the existing `fieldDefinition` and then **add** a new `fieldDefinition` with the new `FieldType`. -2. The `fieldDefinition` for which the `fieldType` is not defined (`null`) will not be synced. +2. The `fieldDefinition` with missing `fieldType` (is `null`) will not be synced. #### More examples of how to use the sync - 1. [Sync from another CTP project as a source](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/ctpprojectsource/types/TypeSyncIT.java). - 2. [Sync from an external source](https://github.com/commercetools/commercetools-sync-java/tree/master/src/integration-test/java/com/commercetools/sync/integration/externalsource/types/TypeSyncIT.java). + 1. [Sync from another CTP project as a source](#todo). + 2. [Sync from an external source](#todo). *Make sure to read the [Important Usage Tips](IMPORTANT_USAGE_TIPS.md) for optimal performance.* @@ -188,7 +195,7 @@ __Note__ The statistics object contains the processing time of the last batch on A utility method provided by the library to compare a `Type` with a new `TypeDraft` and results in a list of type update actions. ```java -List> updateActions = TypeSyncUtils.buildActions(type, typeDraft, typeSyncOptions); +List updateActions = TypeSyncUtils.buildActions(type, typeDraft, typeSyncOptions); ``` ### Build particular update action(s) @@ -196,12 +203,102 @@ List> updateActions = TypeSyncUtils.buildActions(type, typeDr Utility methods provided by the library to compare the specific fields of a `Type` and a new `TypeDraft`, and in turn builds the update action. One example is the `buildChangeNameUpdateAction` which compares names: ````java -Optional> updateAction = TypeUpdateActionUtils.buildChangeNameAction(oldType, typeDraft); +Optional updateAction = TypeUpdateActionUtils.buildChangeNameUpdateAction(oldType, typeDraft); ```` -More examples of those utils for different types can be found [here](https://github.com/commercetools/commercetools-sync-java/tree/master/src/test/java/com/commercetools/sync/types/utils/TypeUpdateActionUtilsTest.java). +More examples of those utils for different types can be found [here](#todo). + +## Migration Guide + +The type-sync uses the [JVM-SDK-V2](http://commercetools.github.io/commercetools-sdk-java-v2), therefore ensure you [Install JVM SDK](https://docs.commercetools.com/sdk/java-sdk-getting-started#install-the-java-sdk) module `commercetools-sdk-java-api` with +any HTTP client module. The default one is `commercetools-http-client`. + +```xml + + + LATEST + + + + + com.commercetools.sdk + commercetools-http-client + ${commercetools.version} + + + com.commercetools.sdk + commercetools-sdk-java-api + ${commercetools.version} + + + +``` + +### Client configuration and creation + +For client creation use [ClientConfigurationUtils](#todo) which apply the best practices for `ProjectApiRoot` creation. +If you have custom requirements for the client creation make sure to replace `SphereClientFactory` with `ApiRootBuilder` as described in this [Migration Document](https://docs.commercetools.com/sdk/java-sdk-migrate#client-configuration-and-creation). + +### Signature of TypeSyncOptions + +As models and update actions have changed in the JVM-SDK-V2 the signature of SyncOptions is different. It's constructor now takes a `ProjectApiRoot` as first argument. The callback functions are signed with `TypeDraft`, `Type` and `TypeUpdateAction` from `package com.commercetools.api.models.type.*` + +> Note: Type `UpdateAction` has changed to `TypeUpdateAction`. Make sure you create and supply a specific TypeUpdateAction in `beforeUpdateCallback`. For that you can use the [library-utilities](#todo) or use a JVM-SDK builder ([see also](https://docs.commercetools.com/sdk/java-sdk-migrate#update-resources)): + +```java +// Example: Create a type update action to change name taking the 'newName' of the typeDraft + final Function changeNameBeforeUpdateAction = + (newName) -> TypeChangeNameAction.builder().name(newName).build(); + +// Add the change name action to the list of update actions before update is executed + final TriFunction< + List, TypeDraft, Type, List> + beforeUpdateTypeCallback = + (updateActions, newTypeDraft, oldType) -> { + final TypeUpdateAction beforeUpdateAction = + changeNameBeforeUpdateAction.apply(newTypeDraft.getName()); + updateActions.add(beforeUpdateAction); + return updateActions; + }; +``` + +### Build TypeDraft (syncing from external project) + +The type-sync expects a list of `TypeDraft`s to process. If you use java-sync-library to sync your types from any external system into a commercetools platform project you have to convert your data into CTP compatible `TypeDraft` type. This was done in previous version using `DraftBuilder`s. +The V2 SDK do not have inheritance for `DraftBuilder` classes but the differences are minor and you can replace it easily. Here's an example: + +```java +// TypeDraftBuilder in v1 takes parameters 'key', 'name' and a set of 'resourceTypeIds' +final TypeDraft typeDraft = + TypeDraftBuilder + .of("type-key", ofEnglish("name"), ResourceTypeIdsSetBuilder.of().addCategories().build()) + .build(); + +// TypeDraftBuilder in v2. 'resourceTypeIds' is a list + TypeDraftBuilder.of() + .key("type-key") + .name(LocalizedString.ofEnglish("name")) + .resourceTypeIds(ResourceTypeId.CATEGORY) + .build(); +``` +For more information, see the [Guide to replace DraftBuilders](https://docs.commercetools.com/sdk/java-sdk-migrate#using-draftbuilders). + +### Query for Types (syncing from CTP project) + +If you sync types between different commercetools projects you have to transform `Type` into `TypeDraft`. +However, if you need to query `Types` from a commercetools project instead of passing `TypeQuery`s to a `sphereClient`, create (and execute) requests directly from the `apiRoot`. +Here's an example: + +```java +// SDK v1: TypeQuery to fetch all types +final TypeQuery query = TypeQuery.of(); + +final PagedQueryResult pagedQueryResult = sphereClient.executeBlocking(query); + +// SDK v2: Create and execute query to fetch all types in one line +final TypePagedQueryResponse result = apiRoot.types().get().executeBlocking().getBody(); +``` +[Read more](https://docs.commercetools.com/sdk/java-sdk-migrate#query-resources) about querying resources. -## Caveats +### JVM-SDK-V2 migration guide -1. Updating the label of enum values and localized enum values of field definition are not supported yet. [#339](https://github.com/commercetools/commercetools-sync-java/issues/339) -2. Removing the enum values and localized enum values from the field definition are not supported yet. [#339](https://github.com/commercetools/commercetools-sync-java/issues/339) -3. Updating the input hint of a field definition is not supported yet. [#339](https://github.com/commercetools/commercetools-sync-java/issues/339) +On any other needs to migrate your project using jvm-sdk-v2 please refer to it's [Migration Guide](https://docs.commercetools.com/sdk/java-sdk-migrate).