Autowired not working in JavaDelegate for ServiceTask

Hello @wwitt,

Here is the bpmn,

<?xml version="1.0" encoding="UTF-8"?>

<bpmn:definitions
xmlns:bpmn=“http://www.omg.org/spec/BPMN/20100524/MODEL
xmlns:di=“http://www.omg.org/spec/BPMN/20100524/DI
xmlns:dc=“http://www.omg.org/spec/DD/20100524/DC
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance
xmlns:di_1=“http://www.omg.org/spec/DD/20100524/DI
xmlns:flowable=“http://flowable.org/bpmn
id=“idCASImportProcessDefinition”
targetNamespace=“http://bpmn.io/schema/bpmn
exporter=“bpmn-js (https://demo.bpmn.io)”
exporterVersion=“7.3.0”>
<bpmn:process id=“CAS_IMPORT” name=“CAS Import Scenario” isExecutable=“true”>

    <bpmn:startEvent id="idStartEvent" name="Start Event" />

    <bpmn:sequenceFlow id="idsequenceFlow1" sourceRef="idStartEvent" targetRef="idParseDescriptorsAndValidationsAndOrderList" />

    <bpmn:serviceTask id="idParseDescriptorsAndValidationsAndOrderList" name="Parse descriptors and Validations"  flowable:delegateExpression="${parseDescriptorsAndValidationsAndOrderList}"/>

    <bpmn:sequenceFlow id="Flow_1unfx48" sourceRef="idParseDescriptorsAndValidationsAndOrderList" targetRef="idUploadAndDeploy">
        <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression"><![CDATA[${(isValidDescriptor == "YES")}]]></bpmn:conditionExpression>
    </bpmn:sequenceFlow>

    <bpmn:serviceTask id="idUploadAndDeploy" name="Upload and Deploy" flowable:delegateExpression="${uploadAndDeploy}"/>

    <bpmn:sequenceFlow id="idsequenceFlow3" sourceRef="idUploadAndDeploy" targetRef="idGetGACDStatus" />

    <bpmn:serviceTask id="idGetGACDStatus" name="Get Status" flowable:class="com.sap.cloud.lm.sl.contentlm.cas.utils.flowable.GetGACDStatus" />

    <bpmn:sequenceFlow id="idsequenceFlow4" sourceRef="idGetGACDStatus" targetRef="idGetGACDLogs" />

    <bpmn:serviceTask id="idGetGACDLogs" name="Get Logs" flowable:class="com.sap.cloud.lm.sl.contentlm.cas.utils.flowable.GetGACDLogs" />

    <bpmn:sequenceFlow id="idsequenceFlow5" sourceRef="idGetGACDLogs" targetRef="idGACDDelete" />

    <bpmn:serviceTask id="idGACDDelete" name="Delete Content" flowable:class="com.sap.cloud.lm.sl.contentlm.cas.utils.flowable.GACDDelete" />

    <bpmn:sequenceFlow id="idsequenceFlow6" sourceRef="idGACDDelete" targetRef="idEndEvent" />

    <bpmn:sequenceFlow id="Flow_0gqeaos" sourceRef="idParseDescriptorsAndValidationsAndOrderList" targetRef="idGACDDelete">
        <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression"><![CDATA[${(isValidDescriptor == "NO")}]]></bpmn:conditionExpression>
    </bpmn:sequenceFlow>

    <bpmn:endEvent id="idEndEvent" name="End Event">
    </bpmn:endEvent>
</bpmn:process>

</bpmn:definitions>

Here is the class implementing JavaDelegate,

@Named(“parseDescriptorsAndValidationsAndOrderList”)
@Component
public class ParseDescriptorsAndValidationsAndOrderList implements JavaDelegate {

private final Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
MtaArchiveHandler mtaArchiveHandler;

public void execute(DelegateExecution execution) {
    logger.info("first--> " + mtaArchiveHandler.toString());
    logger.info("hello from process instance " + execution.getProcessInstanceId() + " and event name " + execution.getId());
}

}

Now I’ve two issues which I’m facing:

  1. In case I use specify like flowable:delegateExpression="{parseDescriptorsAndValidationsAndOrderList}", I'm getting below error: unknown property used in expression: {parseDescriptorsAndValidationsAndOrderList}

  2. Since delegateExpression is not working, then I’m unable to Autowire dependencies in the classes which are implementing JavaDelegate.

Could you please help me to figure out what could be the possible reason? Or let me know if you need more information from my side.

Regards,
Ashmita Sinha

Do you have ComponentScan defined for the application?
Have you properly configured the Spring Boot engine you are using?
Are you using the Flowable as embedded engine in your Spring Boot app or do you want to “deploy” the class to lib folder?

@ComponentScan(“org.sample.cas”)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

Could you please be more specific about what could be the missing link?
But I’ve tried to Autowire ParseDescriptorsAndValidationsAndOrderList class out of flowable context and I’m able to.

Here is the flowable configuration which I’ve done,

@Configuration
public class FlowableEngineConfiguration {

private final Logger logger = LoggerFactory.getLogger(FlowableEngineConfiguration.class);

@Autowired
public DataSource dataSource;

@Autowired
DbServiceImpl casDbService;

@Autowired
StrongUuidGenerator uuidGenerator;

@PostConstruct
private void init() throws Exception {
    casDbService.updateAdminTenant();
}

//	@Lazy
@Bean(name = "processEngineConfiguration")
public ProcessEngineConfigurationImpl processEngineConfiguration() throws Exception {
    init();
    javax.sql.DataSource ds = (javax.sql.DataSource) dataSource;
    SpringProcessEngineConfiguration processEngineConfiguration = new SpringProcessEngineConfiguration();
    processEngineConfiguration.setDatabaseSchema(TCMConstants.DbQuery.CAS_SCHEMA_NAME);
    processEngineConfiguration.setDataSource(ds);
    processEngineConfiguration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
    processEngineConfiguration.setTransactionManager(annotationDrivenTransactionManager());
    processEngineConfiguration.setIdGenerator(uuidGenerator);													//to generate process instance id as UUID
    processEngineConfiguration.setHistory(HistoryLevel.NONE.getKey());											//by default archiving of process instance and related data would be stopped
    //processEngineConfiguration.setAsyncExecutorNumberOfRetries(0);        //for retries
    logger.debug("processEngineConfiguration bean created");
    return processEngineConfiguration;
}

@Bean(name = "ProcessEngine")
public ProcessEngine processEngine() {
    try {
        return processEngineConfiguration().buildProcessEngine();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

@PostConstruct
public void deployDefinedProcess() throws IOException {
    repositoryService()
            .createDeployment()
            .name("casimport")
            .addClasspathResource("processes/casimport.bpmn20.xml")
            .deploy();
}

@Bean(name = "transactionManager")
public PlatformTransactionManager annotationDrivenTransactionManager() {
    DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
    javax.sql.DataSource ds = (javax.sql.DataSource) dataSource;
    transactionManager.setDataSource(ds);
    logger.debug("transactionManager bean created");
    return transactionManager;
}

@Bean
public RepositoryService repositoryService() {
    return processEngine().getRepositoryService();
}

}

Any help would be really appreciable since tried multiple things but as of now, I’m blocked because of this issue.

Regards,
Ashmita Sinha

Okay, the configuration looks fine and you have component scan enabled.

I’m not really sure what’s the problem here then, since you are obviously doing things correctly and correctly referencing the JavaDelegate implementing class.

Best bet would be to wait for either someone from the Flowable team, or someone more experienced with this case.

Give this a try and let us know if it goes well:

@Service("parseDescriptorsAndValidationsAndOrderList")
public class ParseDescriptorsAndValidationsAndOrderList implements JavaDelegate {
    private final Logger logger = LoggerFactory.getLogger(ParseDescriptorsAndValidationsAndOrderList.class);
    private MtaArchiveHandler mtaArchiveHandler;
	
    public ParseDescriptorsAndValidationsAndOrderList(MtaArchiveHandler mtaArchiveHandler) {
	    this.mtaArchiveHandler = mtaArchiveHandler;
    }

    @Override
    public void execute(DelegateExecution execution) {
        logger.info("first--> " + mtaArchiveHandler.toString());
        logger.info("hello from process instance " + execution.getProcessInstanceId() + " and event name " + execution.getId());
    }
}

Thanks @fiki574,

I can try this, but I don’t think so I can use it as final solution. I’m just wondering why flowable:delegateExpression="${parseDescriptorsAndValidationsAndOrderList}" is giving error. Atleast this should have worked according to the documentation.

Regards,
Ashmita Sinha

Correct, according to the documentation, your implementation would be sufficient so I’m now also wondering why doesn’t it work.

@wwitt @filiphr Any suggestions?

Regards,
Ashmita Sinha

@joram Can you comment

The delegateExpression works indeed as you describe. If the delegateExpression doesn’t resolve, it means Flowable can’t access the Spring applicationContext.

Can you share your setup? Is this Spring Boot or regular Spring.?The SpringApplication seems to indicate it’s Spring Boot. But the fact you’re setting up a transaction manager manually seems to point at regular Spring?

More specifically, how are you setting up the ProcessEngineConfiguration? Using Spring it needs to be SpringProcessEngineConfiguration, which does the logic to get access to the applicationContext. Assuming that this is not Spring Boot of course, where this will happen automatically.

No need to ping me. We try to look at all forum questions regularly (but as everyone here, we’ve got work priorities, too).

Ok, I’ve now seen that the forum had hidden part of the post for me. It is a regular Spring setup, i.e. non-Spring Boot.

When using ‘regular’ Spring, you also need to register the ProcessEngineFactoryBean. This will take the engineConfiguration and create a SpringExpressionManager (https://github.com/flowable/flowable-engine/blob/master/modules/flowable-spring/src/main/java/org/flowable/spring/SpringExpressionManager.java) that has access to the expression manager. Meaning that your Bean(name = “ProcessEngine”) is incorrect.

The docs for such a setup are here: https://flowable.com/open-source/docs/bpmn/ch05-Spring/#processenginefactorybean (in old-style Spring xml, but the in java config the setup is the same)

Thank you so much @joram, your comment really helped. I’ve gone through the documentation again, specific to spring boot this time. And in Spring Boot, only beans need to be created and flowable will do the configurations on its own.

As of now, I’m only using Datasource bean (which I’ve created) and added dependency “flowable-spring-boot-starter” and it’s working.

Regards,
Ashmita Sinha