Start a conversation

Custom Apex Observer No-Arg Constructor Missing Causing ExecutionException

Problem

When performing an action in the CloudSense Configurator or Solution Management Console (e.g., saving discounts, calculating totals, or saving a product configuration), an error occurs:

"ExecutionException: [ClassName] does not have a no-arg constructor"

For example:
- ExecutionException: CS_DiscountObserverAfterSave does not have a no-arg constructor

The action fails, and changes are not saved.

Cause

This error occurs when a custom Apex observer class is registered with CloudSense (e.g., as a discount observer, pricing observer, or configuration observer), but the class does not have a public or global no-argument constructor.

CloudSense uses reflection to instantiate observer classes dynamically. If the class does not have a no-arg constructor, or if the constructor is not accessible (e.g., it is private or protected), the instantiation fails, causing the error.

Common Scenarios

  1. Constructor with Parameters Only: The class has a constructor that requires parameters, but no no-arg constructor.
  2. Private or Protected Constructor: The class has a no-arg constructor, but it is not public or global.
  3. Missing Constructor: The class relies on the default constructor, but the default constructor is not accessible due to the class visibility (e.g., the class is public but the constructor is implicitly private).

Resolution

Step 1: Identify the Affected Apex Class

  1. Note the class name from the error message (e.g., CS_DiscountObserverAfterSave).
  2. Navigate to Setup > Apex Classes in Salesforce.
  3. Locate and open the class.

Step 2: Add a Global No-Arg Constructor

Modify the class to include a global no-argument constructor:

Example: Before

public class CS_DiscountObserverAfterSave implements cscfga.IDiscountObserver {
    private String configId;

    // Constructor with parameters
    public CS_DiscountObserverAfterSave(String configId) {
        this.configId = configId;
    }

    public void execute(cscfga.DiscountContext context) {
        // Observer logic
    }
}

Example: After

public class CS_DiscountObserverAfterSave implements cscfga.IDiscountObserver {
    private String configId;

    // Global no-arg constructor
    global CS_DiscountObserverAfterSave() {
        // Initialize with default values or leave empty
    }

    // Constructor with parameters (if needed)
    public CS_DiscountObserverAfterSave(String configId) {
        this.configId = configId;
    }

    public void execute(cscfga.DiscountContext context) {
        // Observer logic
    }
}

Step 3: Save and Deploy the Class

  1. Save the updated Apex class.
  2. If you are working in a sandbox, deploy the class to production using a change set or your preferred deployment tool.

Step 4: Test the Action

  1. Navigate to the CloudSense Configurator or Solution Management Console.
  2. Repeat the action that previously caused the error (e.g., save discounts, calculate totals).
  3. Verify that the action completes successfully without the error.

Prevention

  • Code Review: When creating custom observer classes, always include a global no-arg constructor, even if the class also has constructors with parameters.
  • Template: Maintain a template for custom observer classes that includes the required constructor:
global class MyObserver implements cscfga.IObserverInterface {
    // Global no-arg constructor
    global MyObserver() {
        // Initialize with default values or leave empty
    }

    // Observer logic
    global void execute(cscfga.ObserverContext context) {
        // Implementation
    }
}
  • Unit Tests: Implement unit tests that verify the observer can be instantiated dynamically:
@isTest
private class MyObserverTest {
    @isTest
    static void testNoArgConstructor() {
        // Verify the observer can be instantiated without parameters
        MyObserver observer = new MyObserver();
        System.assertNotEquals(null, observer);
    }
}

Additional Notes

  • The global keyword is required (not just public) because CloudSense managed packages use reflection to instantiate the observer, and managed packages can only access global constructors in customer code.
  • If your observer class does not require any initialization logic, the no-arg constructor can be empty.
  • This issue is specific to custom observer classes. Out-of-the-box CloudSense observers do not exhibit this behavior.
Choose files or drag and drop files
Was this article helpful?
Yes
No
  1. Priyanka Bhotika

  2. Posted

Comments