The problem stems from incorrect workflow action mapping and custom handler registration. Here’s the comprehensive solution:
Workflow Action Mapping Fix:
Your action needs to be registered for all transition contexts. Update the workflow configuration XML:
<workflowAction name="OpportunityApprovalAction"
class="com.custom.OpportunityApprovalAction"
triggerContext="USER,SYSTEM,BATCH"
mandatory="true">
<statusTransition from="Pending" to="Approved"/>
</workflowAction>
The key is including all three contexts: USER (manual), SYSTEM (automated rules), and BATCH (scheduled jobs).
Custom Handler Registration:
Register your action as a workflow handler, not just an action. In your extension configuration:
WorkflowHandlerRegistry.register(
"OpportunityApprovalAction",
OpportunityApprovalAction.class,
EnumSet.of(ExecutionContext.USER,
ExecutionContext.SYSTEM,
ExecutionContext.BATCH)
);
Status Transition Path Verification:
Ensure your batch job uses the correct transition API:
// Pseudocode - Correct batch job implementation:
1. Load opportunities eligible for approval
2. For each opportunity:
a. Call workflowService.transitionStatus(opp, "Approved")
b. NOT opp.setStatus("Approved") - this bypasses workflow
3. Commit transaction after all validations pass
4. Log any opportunities that fail custom validation
Configuration Steps:
- Update workflow definition to mark your action as mandatory for the Pending→Approved transition
- Set the execution priority to ensure your action runs before the status change commits
- In Admin Console → Workflow Engine → Action Registry, verify your action shows all three execution contexts
- Add error handling in your custom action to log failures during batch execution
- Configure the batch job to respect workflow engine responses and rollback on validation failures
Batch Job Modification:
Your nightly batch job needs to use the workflow transition API instead of direct status updates. Replace direct status changes with workflow-aware transitions that will trigger your custom action:
public void processBatchApprovals(List<Opportunity> opportunities) {
WorkflowService wfService = getWorkflowService();
for (Opportunity opp : opportunities) {
try {
wfService.executeTransition(opp, "APPROVE_TRANSITION");
} catch (WorkflowValidationException e) {
logValidationFailure(opp, e);
}
}
}
Testing & Validation:
After implementing these changes:
- Test manual approval - should work as before
- Test automated rule-based approval - should now trigger your action
- Test batch job approval - should execute validation checks
- Monitor logs during next nightly batch run to confirm action execution
- Verify that failed validations properly prevent status transition
The core issue was that your custom action was only registered for interactive (manual) transitions. By registering it for all execution contexts and ensuring your batch job uses the workflow transition API instead of direct status updates, your validation checks will now execute consistently across all approval scenarios. This maintains data integrity and compliance while preserving your automation capabilities.