AEM Assets events for PIM integration
Learn how to integrate AEM Assets with a third-party system, such as a Product Information Management (PIM) or Product Line Management (PLM) system, to update asset metadata using native AEM IO events. Upon receiving an AEM Assets event, the asset metadata can be updated in AEM, the PIM, or both systems, based on the business requirements. However, this example demonstrates updating the asset metadata in AEM.
To run the asset metadata update code outside of AEM, the Adobe I/O Runtime, a serverless platform is used.
The event processing flow is as follows:
- The AEM Author service triggers an Asset Processing Completed event when an asset upload is completed and all asset processing activities have completed. Waiting for processing to complete ensures that any out-of-the-box processing, such as metadata extraction, has completed.
- The event is sent to the Adobe I/O Events service.
- The Adobe I/O Events service passes the event to the Adobe I/O Runtime Action for processing.
- The Adobe I/O Runtime Action calls the API of the PIM system to retrieve additional metadata like SKU, supplier information, or other details.
- The additional metadata retrieved from the PIM is then updated in AEM Assets using the Assets Author API.
Prerequisites
To complete this tutorial, you need:
-
AEM as a Cloud Service environment with AEM Eventing enabled. Also, the sample WKND Sites project must be deployed on to it.
-
Access to Adobe Developer Console.
-
Adobe Developer CLI installed on your local machine.
Development steps
The high-level development steps are:
- Create a project in the Adobe Developer Console (ADC)
- Initialize the project for local development
- Configure the project in ADC
- Configure the AEM Author service to enable ADC project communication
- Develop a runtime action that orchestrates metadata retrieval and update
- Upload an asset to the AEM Author service and verify that the metadata has been updated
For details on steps 1-2, refer to the Adobe I/O Runtime Action and AEM Events example, and for steps 3-6 refer to the following sections.
Configure the project in Adobe Developer Console (ADC)
To receive AEM Assets Events and execute the Adobe I/O Runtime Action created in the previous step, configure the project in ADC.
-
In ADC, navigate to the project. Select the
Stage
workspace, this is where runtime action got deployed. -
Click the Add Service button and select the Event option. In the Add Events dialog, select Experience Cloud > AEM Assets, and click Next. Follow additional configuration steps, select AEMCS instance, Asset Processing Completed event, OAuth Server-to-Server authentication type, and other details.
-
Finally, in the How to receive events step, expand Runtime action option and select the generic action created in the previous step. Click Save configured events.
-
Likewise, click the Add Service button and select the API option. In the Add an API modal, select Experience Cloud > AEM as a Cloud Service API and click Next.
-
Then select OAuth Server-to-Server for authentication type and click Next.
-
Then select the AEM Administrators-XXX product profile and click Save configured API. To update the asset in question, the selected product profile must be associated with the AEM Assets environment from which the event is being produced and have sufficient access to update assets there.
Configure AEM Author service to enable ADC project communication
To update the asset metadata in AEM from the above ADC project, configure AEM Author service with ADC project’s client id. The client id is added as environment variable using the Adobe Cloud Manager UI.
-
Login to Adobe Cloud Manager, select Program > Environment > Ellipsis > View Details > Configuration tab.
-
Then Add Configuration button and enter the variable details as
table 0-row-4 1-row-4 Name Value AEM service Type ADOBE_PROVIDED_CLIENT_ID <COPY_FROM_ADC_PROJECT_CREDENTIALS> Author Variable -
Click Add and Save the configuration.
Develop runtime action
To perform the metadata retrieval and update, start by updating the auto created generic action code in src/dx-excshell-1/actions/generic
folder.
Refer to the attached WKND-Assets-PIM-Integration.zip file for the complete code, and below section highlights the key files.
-
The
src/dx-excshell-1/actions/generic/mockPIMCommunicator.js
file mocks the PIM API call to retrieve additional metadata like SKU and supplier name. This file is used for demo purposes. Once you have the end-to-end flow working, replace this function with a call to your real PIM system to retrieve metadata for the asset.code language-javascript /** * Mock PIM API to get the product data such as SKU, Supplier, etc. * * In a real-world scenario, this function would call the PIM API to get the product data. * For this example, we are returning mock data. * * @param {string} assetId - The assetId to get the product data. */ module.exports = { async getPIMData(assetId) { if (!assetId) { throw new Error('Invalid assetId'); } // Mock response data for demo purposes const data = { SKUID: 'MockSKU 123', SupplierName: 'mock-supplier', // ... other product data }; return data; }, };
-
The
src/dx-excshell-1/actions/generic/aemCommunicator.js
file updates the asset metadata in AEM using the Assets Author API.code language-javascript const fetch = require('node-fetch'); ... /** * Get IMS Access Token using Client Credentials Flow * * @param {*} clientId - IMS Client ID from ADC project's OAuth Server-to-Server Integration * @param {*} clientSecret - IMS Client Secret from ADC project's OAuth Server-to-Server Integration * @param {*} scopes - IMS Meta Scopes from ADC project's OAuth Server-to-Server Integration as comma separated strings * @returns {string} - Returns the IMS Access Token */ async function getIMSAccessToken(clientId, clientSecret, scopes) { const adobeIMSV3TokenEndpointURL = 'https://ims-na1.adobelogin.com/ims/token/v3'; const options = { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: `grant_type=client_credentials&client_id=${clientId}&client_secret=${clientSecret}&scope=${scopes}`, }; const response = await fetch(adobeIMSV3TokenEndpointURL, options); const responseJSON = await response.json(); return responseJSON.access_token; } async function updateAEMAssetMetadata(metadataDetails, aemAssetEvent, params) { ... // Transform the metadata details to JSON Patch format, // see https://developer.adobe.com/experience-cloud/experience-manager-apis/api/experimental/assets/author/#operation/patchAssetMetadata const transformedMetadata = Object.keys(metadataDetails).map((key) => ({ op: 'add', path: `wknd-${key.toLowerCase()}`, value: metadataDetails[key], })); ... // Get ADC project's OAuth Server-to-Server Integration credentials const clientId = params.ADC_CECREDENTIALS_CLIENTID; const clientSecret = params.ADC_CECREDENTIALS_CLIENTSECRET; const scopes = params.ADC_CECREDENTIALS_METASCOPES; // Get IMS Access Token using Client Credentials Flow const access_token = await getIMSAccessToken(clientId, clientSecret, scopes); // Call AEM Author service to update the metadata using Assets Author API // See https://developer.adobe.com/experience-cloud/experience-manager-apis/api/experimental/assets/author/ const res = await fetch(`${aemAuthorHost}/adobe/assets/${assetId}/metadata`, { method: 'PATCH', headers: { 'Content-Type': 'application/json-patch+json', 'If-Match': '*', 'X-Adobe-Accept-Experimental': '1', 'X-Api-Key': 'aem-assets-management-api', // temporary value Authorization: `Bearer ${access_token}`, }, body: JSON.stringify(transformedMetadata), }); ... } module.exports = { updateAEMAssetMetadata };
The
.env
file stores the ADC project’s OAuth Server-to-Server credentials details, and they are passed as parameters to the action usingext.config.yaml
file. Refer to the App Builder Configuration Files for managing secrets and action parameters. -
The
src/dx-excshell-1/actions/model
folder containsaemAssetEvent.js
anderrors.js
files, which are used by the action to parse the received event and handle errors respectively. -
The
src/dx-excshell-1/actions/generic/index.js
file uses the previously mentioned modules to orchestrate the metadata retrieval and update.code language-javascript ... let responseMsg; // handle the challenge probe request, they are sent by I/O to verify the action is valid if (params.challenge) { logger.info('Challenge probe request detected'); responseMsg = JSON.stringify({ challenge: params.challenge }); } else { logger.info('AEM Asset Event request received'); // create AEM Asset Event object from request parameters const aemAssetEvent = new AEMAssetEvent(params); // Call mock PIM API to get the product data such as SKU, Supplier, etc. const mockPIMData = await mockPIMAPI.getPIMData( aemAssetEvent.getAssetName(), ); logger.info('Mock PIM API response', mockPIMData); // Update PIM received data in AEM as Asset metadata const aemUpdateStatus = await updateAEMAssetMetadata( mockPIMData, aemAssetEvent, params, ); logger.info('AEM Asset metadata update status', aemUpdateStatus); if (aemUpdateStatus) { // create response message responseMsg = JSON.stringify({ message: 'AEM Asset Event processed successfully, updated the asset metadata with PIM data.', assetdata: { assetName: aemAssetEvent.getAssetName(), assetPath: aemAssetEvent.getAssetPath(), assetId: aemAssetEvent.getAssetId(), aemHost: aemAssetEvent.getAEMHost(), pimdata: mockPIMData, }, }); } // response object const response = { statusCode: 200, body: responseMsg, }; // Return the response to the caller return response; ... }
Deploy the updated action to Adobe I/O Runtime using the following command:
$ aio app deploy
Asset upload and metadata verification
To verify the AEM Assets and PIM integration, follow these steps:
-
To view the mock PIM provided metadata like SKU, and Supplier Name, create metadata schema in AEM Assets see Metadata schema that displays the SKU and supplier name metadata properties.
-
Upload an asset in AEM Author service and verify the metadata update.
Concept and key takeaways
The asset metadata synchronization between AEM and other systems like PIM are often required in the enterprise. Using AEM Eventing such requirements can be achieved.
- The asset metadata retrieval code is executed outside of AEM, avoiding the load on AEM Author service thus event-driven architecture that scales independently.
- The newly introduced Assets Author API is used to update the asset metadata in AEM.
- The API authentication uses OAuth server-to-server (aka client credentials flow), see OAuth Server-to-Server credential implementation guide.
- Instead of Adobe I/O Runtime Actions, other webhooks or Amazon EventBridge can be used to receive the AEM Assets event and process the metadata update.
- Asset Events via AEM Eventing empower businesses to automate and streamline critical processes, fostering efficiency and coherence across content ecosystem.