Installing the Cartridge
The SAP Commerce Cartridge is a single extension, constructorcore, that runs inside your SAP Commerce system. It exports your catalog to Constructor on a cron job. This guide walks you through installing it, connecting it to Constructor, and scheduling your first exports.
For assistance with the installation process, please contact our team at [email protected]. A Constructor engineer will gladly guide you through the installation steps beyond what is covered in this document.
Requirements
- SAP Commerce: 2205 or 2211, on-premise or on SAP Commerce Cloud (CCv2).
- Java: Java 17 or Java 21.
- The cartridge package. It ships as
constructor-sap-<version>.zip, together with aconstructor-sap-<version>.zip.sha256checksum file. One package covers every supported SAP Commerce and Java version. To get it, please ask your Constructor team. - Your Constructor credentials. Constructor sets up the connection for you and provides:
- One API token for your company.
- One index key for each Constructor index you export to. Each index holds one language, so a store in three languages uses three index keys.
- Network access. The nodes that run cron jobs must be able to reach
https://connect.cnstrc.comover HTTPS. - Encryption keys. The cartridge stores index keys encrypted, using SAP Commerce's transparent attribute encryption. Make sure your system has its encryption keys (
symmetric.key.*) configured.
Step 1: Add the extension
From the directory that holds both files, verify the package against its checksum:
shasum -a 256 -c constructor-sap-<version>.zip.sha256Unpack it into your custom extensions folder:
unzip constructor-sap-<version>.zip -d hybris/bin/custom/constructor/Then add the extension to hybris/config/localextensions.xml:
<extension name="constructorcore"/>The extension does not require any other extension, so it builds on any SAP Commerce system.
SAP Commerce Cloud (CCv2)On CCv2, commit the unpacked extension into your repository under
core-customize/hybris/bin/custom/constructor/, and addconstructorcoreto theextensionslist in yourmanifest.json. The normal cloud build picks it up from there.
UpgradingTo upgrade, delete the old
constructorcore/folder first, then unpack the new package in its place. Continue with Step 2.
Step 2: Build and update the system
From hybris/bin/platform, build the platform:
. ./setantenv.sh && ant clean allThen update the running system. This step is required. The extension declares its own item types, and the update creates their columns and imports the export job:
ant updatesystemYou can also run the update from HAC > Platform > Update, with Update running system selected.
Check the update log
ant updatesystemexits with code 0 even when the update fails. Check its log forBUILD SUCCESSFUL.
On CCv2, deploy the build with the Migrate data deployment mode, which runs the system update.
After a restart, verify that the export job exists. In HAC > Console > Scripting Languages, run this Groovy script:
spring.getBean("cronJobService").getJob("constructorProductExportJob")?.codeThe result should read constructorProductExportJob.
Step 3: Set the endpoint and API token
The endpoint and the API token describe your environment and your company, so they are properties. They are the same for every export target on the system:
constructorcore.export.url=https://connect.cnstrc.com
constructorcore.export.apiToken=<your API token>Put them in hybris/config/local.properties on-premise, or in the environment properties in the CCv2 Cloud Portal. Never put them in the extension's own project.properties, and never commit the token to your repository.
SAP Commerce reads these properties at startup, so restart the server after you set them. On CCv2, redeploy.
Use the host only
constructorcore.export.urltakes the host only, with no path. The cartridge adds the paths itself, so a value such ashttps://connect.cnstrc.com/cartridge/feed/productmakes every request fail.
For reference, for example to allow traffic through a firewall, the cartridge calls these endpoints:
https://connect.cnstrc.com/cartridge/feed/producthttps://connect.cnstrc.com/cartridge/feed/categoryhttps://connect.cnstrc.com/cartridge/complete_feed
Keeping the endpoint and key in the API registry
If your system keeps its outbound integrations in the SAP API registry, a target can read the endpoint and its index key from a ConsumedDestination instead. Set destinationId on the target (see Step 4). The destination's url then replaces constructorcore.export.url, and its ConsumedOAuthCredential's clientSecret replaces the target's apiKey. The API token always stays a property.
This requires the apiregistryservices extension in localextensions.xml.
INSERT_UPDATE DestinationTarget;id[unique=true];destinationChannel(code)[default=DEFAULT];template
;constructor;;false
INSERT_UPDATE ConsumedOAuthCredential;id[unique=true];clientId;clientSecret
;constructorKeyUkEn;constructor;<your index key>
INSERT_UPDATE ConsumedDestination;id[unique=true];destinationTarget(id)[unique=true];url;credential(id);active
;constructorUkEn;constructor;https://connect.cnstrc.com;constructorKeyUkEn;trueEach credential holds one index key, so create one credential per index. clientId is required by SAP Commerce but is not used.
Step 4: Create export targets
An export target is a ConstructorExportCronJob. One target exports one store, in one language, to one Constructor index. The extension ships no targets, because each one needs an index key and a store that only you can supply.
Create targets with ImpEx, from HAC > Console > ImpEx Import:
INSERT_UPDATE ConstructorExportCronJob;code[unique=true];job(code);baseStoreUid;sessionLanguage(isocode);apiKey;strategy(code);mediaBaseUrl;productUrlPattern;categoryRoots
;constructorExportUkDelta;constructorProductExportJob;apparel-uk;en;<your index key>;DELTA;https://shop.example.co.uk;https://shop.example.co.uk/p/{code};categories,collections
;constructorExportUkFull;constructorProductExportJob;apparel-uk;en;<your index key>;FULL;https://shop.example.co.uk;https://shop.example.co.uk/p/{code};categories,collectionsThis example creates two targets for the same store and index: a DELTA target that sends recent changes, and a FULL target that replaces the whole catalog. Most indexes use this pair. For every target field, the difference between DELTA and FULL, and how to send extra fields, see Catalog integration.
The apiKey field accepts either your index key or a connection slug:
Using connection slugsConnection slugs are unique identifiers for Constructor connections. You can use a connection slug in place of the index key in
apiKey.To retrieve a connection slug:
- Log in to the Constructor dashboard.
- Go to Integration > Connections.
- Find your SAP Commerce connection.
- Copy the value from the Slug column (it starts with
con_).
To keep the key out of the database, leave apiKey empty and set the property constructor.api.key.<target code> instead. Set one property for each target, including both the DELTA and FULL targets of an index. For example:
constructor.api.key.constructorExportUkDelta=<your index key>
constructor.api.key.constructorExportUkFull=<your index key>
Use ImpEx for targetsCreate and edit targets with ImpEx. Backoffice's labelled tabs do not show the cartridge's fields, and it cannot create field mappings.
Step 5: Schedule the exports
The extension ships no triggers. Give each target a Trigger with a cron expression:
INSERT_UPDATE Trigger;cronJob(code)[unique=true];cronExpression;active
;constructorExportUkDelta;0 30 * * * ?;true
;constructorExportUkFull;0 0 3 ? * SUN;trueWe suggest a frequent DELTA target, such as every hour, and a FULL target once a day or once a week. Schedule them so they do not run at the same time. A FULL run that is still running when a DELTA run starts can overwrite the newer data with its older snapshot.
Triggers only load at startup when cronjob.timertask.loadonstartup=true is set on the nodes that should run them. To pause a target, set its trigger's active flag to false.
To run a target by hand, run this Groovy script in HAC > Console > Scripting Languages. It runs synchronously, so a failure shows in the result pane:
cronJobService.performCronJob(cronJobService.getCronJob("constructorExportUkFull"), true)
println cronJobService.getCronJob("constructorExportUkFull").resultStep 6: Check your first export
Run your FULL target by hand, as shown above. When it finishes, look at the result in the Constructor dashboard:
- Go to Integration > Connections. Your SAP Commerce connection shows its status and when it last synced.
- Go to Integration > Catalog Uploads, and select the index you exported to. Each upload shows whether Constructor accepted it. A
FULLrun withcategoryRootsset makes two uploads: one for the categories, then one for the products.
A successful run can still be rejectedConstructor rejects a catalog upload that would deactivate or remove more than half of what the index holds. Constructor applies this rule after the cron job ends, so the cron job still shows as successful. Open Catalog Uploads to confirm the upload was accepted. To learn when and how to override this rule, see Catalog integration.
Troubleshooting
If none of the following resources solves your issue, please contact us at [email protected], and an engineer will be glad to assist.
A target with a wrong or missing setting fails its run instead of exporting incomplete data. The cron job ends with the result FAILURE, and the log names the cause. A run that fails part way leaves its upload incomplete on purpose: Constructor never ingests an incomplete upload.
| Symptom | Cause | Fix |
|---|---|---|
The run fails and the log says constructorcore.export.url is not set, or the API token is not set. | The properties from Step 3 are missing, or are in a file the server does not read. | Set constructorcore.export.url and constructorcore.export.apiToken, then restart. |
| The run fails with a 401 from the service. | The API token or the target's key is wrong. | Verify constructorcore.export.apiToken, and confirm that the target's apiKey is a valid index key or connection slug. |
| The run fails with a connection error or a timeout. | The node cannot reach Constructor. | Allow outbound HTTPS from the nodes that run cron jobs to connect.cnstrc.com. |
| The run fails with a 404, or another non-2xx reply. | constructorcore.export.url contains a path, or the reply is an error from Constructor. | Set the URL to https://connect.cnstrc.com with no path. The log quotes the reply for other errors. |
| The run fails because no API key was found. | The target has no apiKey, no destinationId, and no constructor.api.key.<target code> property. | Set one of the three. |
| The run fails because no products were selected. | The target has neither catalogVersions nor a baseStoreUid with online catalog versions, or the selection holds no products. | Check baseStoreUid, or set catalogVersions. |
| The run fails and names a missing module. | The target uses baseStoreUid without basecommerce, or destinationId without apiregistryservices. | Add the module to localextensions.xml, or configure the target without it. |
| The run fails before sending anything, naming a field mapping. | A field mapping reads an attribute or classification attribute that no product type declares, or names a missing provider bean. | Fix the mapping. See Catalog integration. |
The run fails, naming categoryRoots. | categoryRoots names no existing category, or the tree holds one code twice. | Fix the category codes on the target. |
The run fails, naming pageSize or deltaOverlapSeconds. | constructorcore.export.pageSize is not positive, or constructorcore.export.deltaOverlapSeconds is negative. | Fix the property value. |
Each run warns about constructorcore.export.strategy, or fails because of it. | An older setup still sets this property. The cartridge no longer reads it: the strategy is set on each target. | Remove the property, and set strategy on each target. |
| The run is successful, but the index did not change. | Constructor rejected the upload because it would remove more than half of the index. | Open Integration > Catalog Uploads. If the drop is intended, use force. See Catalog integration. |
| Scheduled targets never run. | Triggers do not load at startup. | Set cronjob.timertask.loadonstartup=true on the nodes that run cron jobs, and confirm that the trigger is active. |
| The export job does not exist after installing. | The system update did not run, or failed. | Run ant updatesystem again, and read its log for BUILD SUCCESSFUL. |
Updated about 1 hour ago