Camunda-bpm-assert-scenario - Delegate java class not been loaded on test

Hello,

I am using camunda scenario to do my testing, and after adding delegates, my scenarios are not being able to load the classes.
I am having this error

11:21:55.498 [main] DEBUG org.camunda.bpm.engine.bpmn.behavior - ENGINE-02002 Leaving activity ‘StartEvent_RRSPInstruction’.
11:21:55.498 [main] DEBUG org.camunda.bpm.engine.context - ENGINE-16001 Executing atomic operation org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationTransitionNotifyListenerEnd@2a9ea03f on ProcessInstance[6426844f-8e7b-11ec-bed3-5c80b61ccf1e]
11:21:55.513 [main] DEBUG org.camunda.bpm.engine.util - ENGINE-09016 Attempting to load class ‘ca.bnc.wealth.iiroc.camunda.rspwithdrawal.bpm.delegate.listener.execution.CreateRequestExecutionListener’ with current thread context classloader: jdk.internal.loader.ClassLoaders$AppClassLoader@77556fd
11:21:55.515 [main] DEBUG org.camunda.bpm.engine.context - ENGINE-16006 BPMN Stack Trace:
StartEvent_RRSPInstruction (transition-notify-listener-end, ProcessInstance[6426844f-8e7b-11ec-bed3-5c80b61ccf1e])
StartEvent_RRSPInstruction, name=Start RRSP Instruction

11:21:55.515 [main] DEBUG org.camunda.bpm.engine.cmd - ENGINE-13011 closing existing command context
11:21:55.515 [main] ERROR org.camunda.bpm.engine.context - ENGINE-16004 Exception while closing command context: ENGINE-09008 Exception while instantiating class ‘ca.bnc.wealth.iiroc.camunda.rspwithdrawal.bpm.delegate.listener.execution.CreateRequestExecutionListener’: couldn’t instantiate class ca.bnc.wealth.iiroc.camunda.rspwithdrawal.bpm.delegate.listener.execution.CreateRequestExecutionListener
org.camunda.bpm.engine.ProcessEngineException: ENGINE-09008 Exception while instantiating class ‘ca.bnc.wealth.iiroc.camunda.rspwithdrawal.bpm.delegate.listener.execution.CreateRequestExecutionListener’: couldn’t instantiate class ca.bnc.wealth.iiroc.camunda.rspwithdrawal.bpm.delegate.listener.execution.CreateRequestExecutionListener

Has someone experienced this?

Thanks

Hi @Alejandra , can You please share the delegate classes used in a test case scenario?

Hello @Michal_Stefaniuk emphasized text,
Thanks for replying, this is my delegate

@Component
@RequiredArgsConstructor
public class CreateRequestExecutionListener implements ExecutionListener {
private final DataRequestRepository dataRequestRepository;

@Override
public void notify(DelegateExecution delegateExecution) throws Exception {
    var dataRequest = new DataRequest();
    dataRequest.setRequestId(delegateExecution.getBusinessKey());
    dataRequestRepository.save(dataRequest);
}

}

The delegate is called like this


image

and my test class
@Deployment(resources = {“bpmn/DetermineFunctionCode.dmn”, “bpmn/Intervention.bpmn”
, “bpmn/UpdateInstructionStatus.bpmn”, “bpmn/rrsp_withdrawal.bpmn”
})
public class RRSPWithdrawalProcessScenarioTest {

private static final String PROCESS_DEFINITION_KEY = "rrsp_withdrawal";
private static final String NBDB_DEALER_CODE = "D07";
private static final String NBF_DEALER_CODE = "B41";
private static final String MOSTV_NBIN_DEALER_CODE = "L52";
private static final String OTHER_NBIN_DEALER_CODE = "L65";
private static final String NBF_PARTNER_ID = "NBF";
private static final String NBIN_PARTNER_ID = "NBIN";
private static final String NBDB_PARTNER_ID = "NBDB";

@Mock
private ProcessScenario rrspWithdrawalProcessScenario;

@Mock
private ProcessScenario updateInstructionStatusProcessScenario;

@Mock
private ProcessScenario updatePendingReviewStatusProcessScenario;

@Mock
private ProcessScenario interventionProcessScenario;

@Mock
private ProcessScenario manualInputProcessScenario;

@Mock
private ProcessScenario manualInputUpdateInstructionStatusProcessScenario;

@Mock
private ProcessScenario updateRejectedStatusProcessScenario;

@Mock
private CreateRequestExecutionListener createRequestExecutionListener;



@Rule
@ClassRule
public static ProcessEngineRule rule = TestCoverageProcessEngineRuleBuilder.create().build();


private Map<String, Object> variables;

private Scenario scenario;

@Test
public void testApprovalCreditNBDBManagerInt() {
validateIntervetionBehavior(“isAppCrNBDBM”,
NBDB_DEALER_CODE,
“INUCHKDC”,
“Cheque request - NBDB Manager”,
“Chèque - Directeur CDBN”,
“CHK_REQ_DIR_SEC”);
}

private void validateIntervetionBehavior(String interventionFlagName,
Object interventionFlagValue,
String dealerCode,
String candidateGroupName,
long grossAmount,
String interventionDescrEn,
String interventionDescrFr,
String interventionRefName){

    variables.put(interventionFlagName, interventionFlagValue);
    variables.put("dealerCode", dealerCode);
    variables.put("isTransmission", false);
    variables.put("grossAmount", grossAmount);


    when(interventionProcessScenario.waitsAtUserTask("Task_Intervention")).thenReturn((task) -> {
        assertThat(task).hasCandidateGroup(candidateGroupName);
        task.complete(withVariables("taskStatusCode", "04"));
    });

    scenario = Scenario.run(rrspWithdrawalProcessScenario)
            .withMockedProcess("transmissionProcess")
            .startByKey(PROCESS_DEFINITION_KEY, variables)
            .execute();

    assertThat(scenario.instances(interventionProcessScenario)).anySatisfy(process -> {
        assertThat(process).variables().containsEntry("taskNameDescrEn", interventionDescrEn);
        assertThat(process).variables().containsEntry("taskNameDescrFr", interventionDescrFr);
        assertThat(process).variables().containsEntry("interventionRefName", interventionRefName);

    });

    assertThat(scenario.instances(rrspWithdrawalProcessScenario)).anySatisfy(process ->
            assertThat(process).isEnded()
    );

    ProcessInstance updatePendingReviewStatusProcessInstance = scenario.instances(updatePendingReviewStatusProcessScenario).get(0);
    assertThat(updatePendingReviewStatusProcessInstance).variables().containsEntry("statusCd", "PENDING_REVIEW");

    for (ProcessInstance updateStatusProcessInstance : scenario.instances(updateInstructionStatusProcessScenario)) {
        assertThat(updateStatusProcessInstance).variables().containsEntry("statusCd", "UNDER_REVIEW");
    }
}

private void validateAdminProManualInputIntervention(){

    assertThat(scenario.instances(manualInputProcessScenario)).anySatisfy(process -> {
    assertThat(process).variables().containsEntry("taskNameDescrEn", "Manual Input");
    assertThat(process).variables().containsEntry("taskNameDescrFr", "Saisie Manuelle");
    assertThat(process).variables().containsEntry("interventionRefName", "MAN_OSS_ACT_ADM");

    });

    for (ProcessInstance rrsProcessInstance : scenario.instances(rrspWithdrawalProcessScenario)) {
        assertThat(rrsProcessInstance).variables().containsEntry("cancellable", false);
    }

}

First of all I would recommend to validate the event in the listener itself i.e

if (ExecutionListener.EVENTNAME_END.equals(delegateExecution.getEvent())

Second of all, there might be an issue with transactions. Setting proper transaction boundaries is very important. I see that You already played around with asynchronous approach, please verify if this post will be helpful

Thanks again for the reply.
For the fist recommendation, could you tell me where please?
The engine actually runs correctly locally, but the tests are the ones that are having this issue.
For the second recommendation, this boundary was required because the class was not being found when not using the asynchronous after.

The first recommendation was regarding the notify method in the ExecutionListener itself, but You might find that irrelevant, according to your business case, it just might be a good practice.

What I would suggest to check then, if the *.bpmn file definitions are actually stored under /test/resources/bpmn directory. The most commont apporach would be to place them in test/resources/ and then to annotate the particular test case with @Deployment(resources = { "your_bpm_file.bpmn" }), instead of annotating the whole test class. You might want to try it out.

Also, is there a need to include to ProcessEngineRule any other different way rather than just ?

@Rule
  public ProcessEngineRule processEngineRule = new ProcessEngineRule();

If that doesn’t help, could You share the bpmn file? And please try to initialize the createRequestExecutionListener class instead of mocking it (maybe through @BeforeAll if necessary)?