We use Camunda BPM with Spring Boot and MS SqlServer and we would like to implement generic service task which decides at runtime if it runs sync or async (based on metadata of service being invoked). It would allow us to model specific process easily without "hardcoding" information if service works in sync/async way.
It works pretty well using following code:
class CustomServiceTask : AbstractBpmnActivityBehavior() {
@Throws(Exception::class)
override fun execute(execution: ActivityExecution) {
val isSync: Boolean = ... // get service info
if (isSync) {
// do your stuff in sync mode
// invoke service, for example via REST
leave(execution)
} else {
// do your async stuff here - do something like:
// - submit jms/kafka/... message
// - start another process
// - ...
// TODO: enforce persisting process to db here?
}
}
@Throws(Exception::class)
override fun signal(execution: ActivityExecution, signalName: String?, signalData: Any?) {
logger.info("${execution.activity.id}: Received signal for execution [${execution.id}] now, leaving execution now.")
// leave the service task activity:
leave(execution)
}
companion object {
private val logger = LoggerFactory.getLogger(CustomServiceTask::class.java)!!
}
}
Anyway there is one more problem - sometimes it happens, that the async service is too fast and it signals the process yet before it's state is persisted to camunda database - if I understand that correctly, it is fixed by marking the service task asyncBefore/asyncAfter, which forces the transaction to be committed after executing the service task code. (Correct?)
Is there any way to achieve the same from the code of service task itself?
I was trying something like
Context.getCommandContext().transactionContext.commit()
but not sure if it is correct.