Sitecore Commerce Data, A Practical Approach: Part 2 (Better)

Time to read: About 5-7 minutes
Intended for: Sitecore commerce developers, Sitecore developers, Senior developers & leads
Key takeaway: In this “Better” approach, leverage the Initialize pipeline in Sitecore Commerce to create entities that are common to all environments.

In part 1, I covered how you could use Postman to automate the initialization of data in your Sitecore Commerce environments. If you haven’t read Part 1, I suggested that while using Postman was at least “good” for creating consistent, automated data in a Commerce environment, there were some significant drawbacks. In this post, I will cover an alternative approach, which has fewer of the drawback we saw in the first approach.

The Commerce Initialization pipeline

This approach leverages the Initialize pipeline within Commerce to perform the initialization steps from the first approach. Since it is likely that integration, UAT and production need the same initial setup, it makes sense to have this configured and executed during the Initialization Pipeline. In the image below, the Initialization Pipeline is used to create the catalogs, price books, and other Commerce entities that are common to all environments.

File Edit 
@ Debug 
sql 
Tax 
context) . '"Sync () ; 
Yiew project 
itiaIizeEnvironment810ck.cs -E 
Build 
Debug 
Test Analyze Tools 
Any CPU 
Extensions Window Help 
Sitecore.Commerce.Engine 
Search Visual Studio (Ctrl+Q) 
Sitecore.Commerce.Engine • • 
. nitia n me ntE 
x 
Caleres.Commerce.PIugin.CataIog 
• IntitiaIizeCataIogs(CommercePipeIineExecutionContext context) 
[Inferr edpipel ineDispI ( Initi ali zeEnvi ronrntBIock) ) ] 
public class InitializeEnvironmentBIock : Pipeline810ckcstring, string, a—rcePipeIineExecutionC1text» 
IS E: 
37 
private readonly a—rceCumander; 
private readonly IPersistEntityPipeIine persistEntityPipeIine; 
o I 52 1 2 
public cumerceC—Mer, 
s. cumercecc—nder = ; 
s.persistEntityPipeIine = persistEntityPipeIine; 
IPersistEntityPipeIine 
persi stEntityP ipel ine) 
public m'erride async Task<string» Run(string arg, CumercePipeIineExecutionContext 
await Intitializecatalogs(context) . W$mc(); 
await 
await Nosync(); 
return arg; 
cmtext) 
protected internal virtual async Task mtitiaIizeCataIogs(ComercePipeIineExecutionContext 
context) 
var webstores = .GetWebStores(); 
foreach (var wåStore in *bStores) 
await 
.Rm(new webStore.DispIayNanE.RepIace( 
. Nosync(); 
Store", "Catalog"))• 
cmtext) 
protected internal virtual async Task mtitiaIizePriceBooks(CcmercePipeIineExecutionContext 
var webstores = .GetWebStores(); 
foreach (var wåStore in *bStores) 
var = await 
cumercec—nder. . Rim ( new 
cult ext) 
Pri ceBookNar) , 
Solution Explorer 
Search Solution Explorer (Ctrl+;) 
Database 
ExternalLibraries 
Plugins 
PluginTempIate_ 
Carts 
Catalog 
Composer 
Coupons 
Customers 
Fraud 
Fulfillment 
Gift Cards 
Inventory 
Journaling 
ManagedLists 
Management 
Orders 
Payme nts 
Pricing 
Promotions 
Reports 
Returns 
Rules 
Search 
Stores 
Views 
WebStore 
Shared 
b Weh 
Solution Explorer Unit Test Explorer 
Properties 
Team Explorer 
81 % 
neWriceBook.DispIayNar = Store", "Price Book"); 
neWriceBook.Description = S"This is the {webStor-e.DispIayNar. Store", "Price Bc:ok")}. 
var persistResuIt 
await persistEntityPipeIine.Rm(new PersistEntityArgLrnt(newPriceBook), context) . W$mc(); 
if (persistResuIt?.Entity 
null) 
var errorText = S"FaiIed to update {newPriceBmk.DispIayNaæ)."; 
@ No issues found 
Data Tools Operations 
NuGet browser 
Package Manager Console 
CodeLens 
Find Results 
Error List 
Output 
Data Tools Operations 
Sitecore_Commerce 
feature/add-date-to-datafeeds •

While this Initialization Pipeline could still be executed with Postman, I will suggest another way. In the latest Sitecore Commerce project, we needed to create custom Commerce APIs to handle the creation of Sellable Items, prices, load inventory, etc. This approach was recommended by the Sitecore Lighthouse team, since the existing Commerce APIs (which we used in the first article) for creating these entities is quite cumbersome.

These custom APIs are then used to load Commerce data from the existing Product Information Management (PIM) system. I expect this is quite common across the Sitecore Commerce landscape. Since the Commerce data’s true “source of truth” is in the PIM, We used this data as a source of information for a custom application.

The “TestData” .NET application

This application is simply a .NET Framework 4.7.2 Console Application, which I creatively called “TestData.” The TestData application is responsible for calling all of the Commerce APIs that were called by Postman in the first article. This includes calling the Bootstrap, Clean, Initialize and the other APIs.

First, the TestData app must be able to authenticate against the Commerce APIs. This can be done one of two ways.

  • A username and password can be sent to the GetToken API endpoint on the Sitecore Identity Server
  • The TestData app can use the Commerce Engine certificate to authenticate.

I prefer using the Commerce Engine certificate, since the token received from the GetToken API can timeout before the TestData app finished executing. However, the advantage of the GetToken API is that it requires the person executing the TestData app to have valid credentials and permissions to do all that the TestData has to do.

This can be a valuable advantage in environments that must be tightly controlled, especially under PCI compliance. This approach can also prevent developers from accidentally running the TestData application in higher environments.

The TestData app must be capable of executing APIs in all the Sitecore Commerce environments, integration, UAT and production, as this is the data that will be used to validate each of those environments.

As I am sure everyone is aware, setting up and configuring a Sitecore Commerce environment is not a trivial task.  Having predictable test data for validation can greatly accelerate the delivery of a new environment, and ensure that everything is working correctly.

TestData details

The TestData application that I have written begins by calling Bootstrap, then Clean, then Initialize. It then enters a loop, calling the Check Long Running process endpoint until an “OK” response is received. It then calls Ensure/Sync Content Paths, and enters a similar loop. Once that is completed, the Commerce environment is ready to receive the set of test data.

I formatted all of the test data files that I used as JSON, so that they were in exactly the format the custom Commerce APIs expected. This way we can just read in the files and pass the data directly to the APIs without parsing them. The data includes products, prices, inventory, variants, etc.  Perhaps just as important, the whole process runs in about 20 minutes, giving developers a clean slate to work from in the time it takes to grab more water and hit the restroom. 

There are some distinct advantages to this approach compared with the Postman approach:

  • All the code is C#, and along with the data, can easily be committed to a source control repository
  • Maintenance, extensibility and troubleshooting is far easier (in my opinion) in C# than Postman
  • The TestData application runs as “fire and forget,” where the Postman approach needs more supervision and human intervention

In Part 3 of this series, I will show you another way to load data into your Commerce Environment. I am choosing to call this last way “Best,” for reasons which will be made clear. Stay tuned!