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
- Constructor with Parameters Only: The class has a constructor that requires parameters, but no no-arg constructor.
- Private or Protected Constructor: The class has a no-arg constructor, but it is not
publicorglobal. - 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
publicbut the constructor is implicitlyprivate).
Resolution
Step 1: Identify the Affected Apex Class
- Note the class name from the error message (e.g.,
CS_DiscountObserverAfterSave). - Navigate to Setup > Apex Classes in Salesforce.
- 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
- Save the updated Apex class.
- 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
- Navigate to the CloudSense Configurator or Solution Management Console.
- Repeat the action that previously caused the error (e.g., save discounts, calculate totals).
- Verify that the action completes successfully without the error.
Prevention
- Code Review: When creating custom observer classes, always include a
globalno-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
globalkeyword is required (not justpublic) because CloudSense managed packages use reflection to instantiate the observer, and managed packages can only accessglobalconstructors 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.
Priyanka Bhotika
Comments