Start a conversation

Custom Code Fails After Upgrade Due to Deprecated Internal API (addonService.relatedProductData)

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

  1. Review the error logs to identify which custom JavaScript file is causing the failure
  2. Common files that may be affected:
  3. Custom submission service files (e.g., vassubmissionservice.js)
  4. Custom basket validation files
  5. Custom MACD workflow files
  6. Any custom code that interacts with add-on components

  7. Search for references to relatedProductData in your custom code:

  8. Use your IDE or text editor to search for relatedProductData across all custom JavaScript files
  9. 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

  1. Update the custom JavaScript file with the new code
  2. Test the updated code in a sandbox environment:
  3. Create a test basket with and without the add-on component
  4. Trigger the custom workflow (e.g., basket submission, MACD operation)
  5. Verify that the add-on is correctly added when it exists, and skipped when it doesn't

  6. Deploy the updated code to production:

  7. Upload the updated JavaScript file to the Static Resource or Custom Metadata
  8. Clear any caching if applicable
  9. Notify users that the fix has been deployed

Step 5: Verify the Fix

  1. Retry the operation that was previously failing (e.g., basket submission, MACD)
  2. Monitor the browser console for any errors
  3. Verify the add-on component is correctly added to the configuration
  4. 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 relatedProductData function 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
Choose files or drag and drop files
Was this article helpful?
Yes
No
  1. Priyanka Bhotika

  2. Posted

Comments