Problem
After upgrading CloudSense from R33 to later versions (R34, R35, R36, R37), custom JavaScript code that previously worked in R33 now fails with an error similar to:
TypeError: Cannot read property 'relatedProductData' of undefined
or
TypeError: addonService.relatedProductData is not a function
The error typically occurs in custom code that accesses the relatedProductData function under the addonService property of a component object, such as:
const addonRelatedProductData = component.addonService.relatedProductData;
This prevents custom workflows (e.g., MACD operations, basket submissions, add-on management) from completing successfully.
Root Cause
The addonService.relatedProductData function was an internal, undocumented function within the CloudSense package code that existed in R33 but was removed in later versions as part of service refactoring.
Key points:
- The function was never part of the official CloudSense public API
- It was subject to change without prior notice or deprecation warnings
- The function was used internally to check whether an add-on component exists for a configuration and to retrieve related product data
- After R33, the function was removed, causing any custom code that relied on it to fail
Common use cases that relied on this function:
- Checking if an add-on exists in a configuration before adding it
- Retrieving related product data for add-on components
- Validating add-on availability during basket submission or MACD operations
Resolution Steps
Step 1: Identify the Affected Custom Code
- Review the error logs to identify which custom JavaScript file is causing the failure
- Common files that may be affected:
- Custom submission service files (e.g.,
vassubmissionservice.js) - Custom basket validation files
- Custom MACD workflow files
-
Any custom code that interacts with add-on components
-
Search for references to
relatedProductDatain your custom code: - Use your IDE or text editor to search for
relatedProductDataacross all custom JavaScript files - Note the file names and line numbers where the function is used
Step 2: Understand the Original Logic
Before replacing the deprecated function, understand what the original code was trying to achieve. The typical pattern was:
// DEPRECATED CODE (R33)
const addonRelatedProductData = component.addonService.relatedProductData;
// Check if add-on exists in the configuration
if (addonRelatedProductData && addonRelatedProductData.length > 0) {
// Add the add-on to the configuration
addonRelatedProductData.forEach(addon => {
// Process each add-on
});
}
Purpose:
- Check if an add-on component exists for the configuration (e.g., Mobile Service)
- Based on the request containing which add-ons to add, add them if they exist in the config, or skip them if they don't
Step 3: Replace with Documented CloudSense APIs
Use the following documented APIs to achieve the same functionality:
// NEW CODE (R34+)
const solution = await CS.SM.getActiveSolution();
const config = solution.getConfiguration(configurationGuid);
// Get all components in the configuration
const components = config.getComponents();
// Find the add-on component by name or type
const addonComponent = components.find(comp =>
comp.name === "Add-on Service Name" ||
comp.type === "AddOn"
);
// Check if the add-on exists
if (addonComponent) {
// Add the add-on to the configuration
await solution.addComponent(configurationGuid, {
productDefinitionGuid: addonProductDefinitionGuid,
quantity: 1,
// ... other properties
});
console.log("Add-on added successfully");
} else {
console.log("Add-on does not exist in configuration, skipping");
}
Key differences:
- Use config.getComponents() to retrieve all components in the configuration
- Use Array.find() or Array.filter() to locate the specific add-on component
- Use solution.addComponent() to add the add-on if it exists
- All APIs are documented and supported in R34+
Step 4: Update and Deploy the Custom Code
- Update the custom JavaScript file with the new code
- Test the updated code in a sandbox environment:
- Create a test basket with and without the add-on component
- Trigger the custom workflow (e.g., basket submission, MACD operation)
-
Verify that the add-on is correctly added when it exists, and skipped when it doesn't
-
Deploy the updated code to production:
- Upload the updated JavaScript file to the Static Resource or Custom Metadata
- Clear any caching if applicable
- Notify users that the fix has been deployed
Step 5: Verify the Fix
- Retry the operation that was previously failing (e.g., basket submission, MACD)
- Monitor the browser console for any errors
- Verify the add-on component is correctly added to the configuration
- Check downstream systems (e.g., OSS, billing) to ensure the order is processed successfully
Example: Full Code Replacement
Before (R33 - DEPRECATED):
// Check if add-on exists and add it
const addonRelatedProductData = component.addonService.relatedProductData;
if (addonRelatedProductData && addonRelatedProductData.length > 0) {
addonRelatedProductData.forEach(addon => {
// Add the add-on
addAddonToConfiguration(addon);
});
}
After (R34+ - DOCUMENTED API):
// Check if add-on exists and add it
const solution = await CS.SM.getActiveSolution();
const config = solution.getConfiguration(configurationGuid);
const components = config.getComponents();
// Find the add-on component
const addonComponent = components.find(comp =>
comp.type === "AddOn" && comp.name === "Expected Add-on Name"
);
if (addonComponent) {
// Add the add-on using documented API
await solution.addComponent(configurationGuid, {
productDefinitionGuid: addonComponent.productDefinitionGuid,
quantity: 1,
attributes: {
// ... attribute values
}
});
console.log("Add-on added successfully");
} else {
console.log("Add-on does not exist in configuration, skipping");
}
Prevention
To prevent this issue in future upgrades:
- Use only documented CloudSense APIs in custom code
- Avoid accessing internal properties or functions that are not documented in the official API documentation
- Review CloudSense release notes for each upgrade to identify deprecated or removed APIs
- Test custom code in sandbox after each CloudSense package upgrade
- Implement error handling in custom code to gracefully handle missing functions or properties
- Document all custom code dependencies on CloudSense APIs for future reference
- Consult CloudSense Support before using undocumented APIs or internal functions
Important Notes
- The
relatedProductDatafunction was never part of the official CloudSense public API - Internal functions and properties are subject to change without notice
- Always refer to the official CloudSense API documentation when writing custom code
- If you need functionality that is not available via documented APIs, contact CloudSense Support or PS to request a feature or guidance
- This issue may affect multiple custom files in your implementation, so audit all custom code for similar patterns
- The documented APIs provide more flexibility and are guaranteed to be supported across future releases
Priyanka Bhotika
Comments