Executing a async task with Java Future

I am trying to create a simple process with async operations.
Here is my sample process

start → serviceTask1 → serviceTask2 → end

Here my serviceTask1 and ServiceTask2 are a bit log running operations, and the from the service task, I am calling a method which returns Java Future. I do not want to use blocking call by using .get on Future and instead was trying to send the signal to camunda from the Future completion.
However, I am getting a NullPointerException on doing so.

java.lang.NullPointerException
at org.camunda.bpm.engine.impl.context.ProcessApplicationContextUtil.getTargetProcessApplication(ProcessApplicationContextUtil.java:115)
at org.camunda.bpm.engine.impl.context.ProcessApplicationContextUtil.getTargetProcessApplication(ProcessApplicationContextUtil.java:89)
at org.camunda.bpm.engine.impl.context.ProcessApplicationContextUtil.getTargetProcessApplication(ProcessApplicationContextUtil.java:51)
at org.camunda.bpm.engine.impl.bpmn.behavior.ClassDelegateActivityBehavior.signal(ClassDelegateActivityBehavior.java:77)
at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.signal(PvmExecutionImpl.java:726)
at com.reactore.hf.FuturePblm$.$anonfun$completeAndSendSignal$1(FuturePblm.scala:30)
at com.reactore.hf.FuturePblm$.$anonfun$completeAndSendSignal$1$adapted(FuturePblm.scala:27)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64)
at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)

So for the time being, I thought of not using the Future operation and signal the task directly. I was expecting the task(serviceTask1) to get stuck and the process not going forward to serviceTask2 if I comment out the signal operation. However, it is not working as I expected.

    public class CustomServiceTask extends AbstractBpmnActivityBehavior {

        @Override
        public void execute(ActivityExecution execution) throws Exception {
            System.out.println("****Inside service task 1 ****");
            execution.setVariable("inLineProcess", "test");
            String procesInstanceId = execution.getProcessInstanceId();
            execution.getProcessEngine().getRuntimeService().signal(procesInstanceId);
            System.out.println("After sending signal from task 1 ");
    //        Thread.sleep(5000);
    //        leave(execution);
    //        FuturePblm.completeAndSendSignal(execution, FuturePblm.futureValue());
            System.out.println(" after future");
        }
    }

Can someone let me know what I am doing wrong here? Or help me to handle the Future scenario from the service tasks ?
Is my understanding of signal wrong ?

Note: For this test, I was creating the process programmatically, and tried asyncBefore and asyncAfter on the service tasks also.

Yadu, if your code above is the code you are running, then you are still calling:

execution.getProcessEngine().getRuntimeService().signal(procesInstanceId);

and therefore the task gets completed. Why call the signal method from within the execute method? Everything would still be executed in the same (blocking, synchronous) thread.

Please see this example (just confirmed it works against v7.12)

This is a simple implementation of the {@link SignallableActivityBehavior} * interface.

* *

The {@link SignallableActivityBehavior} provides two methods: *

    * *
  • The {@link #execute(ActivityExecution)}-Method is invoked when the service * task is entered. It is typically used for sending an asynchronous message to the * actual service. When the method returns, the process engine will NOT continue * execution. The {@link SignallableActivityBehavior} acts as a wait state.
  • * *
  • The {@link #signal(ActivityExecution, String, Object)} method is invoked as * the process engine is being triggered by the callback. The signal-Method is * responsible for leaving the service task activity.
  • *

The example implementation uses a separate signal method, which gets invoked when the async job is completed.

However, this approach uses internal API. Have you considered working with a send Send Task | docs.camunda.org
and a receive task
Receive Task | docs.camunda.org
or using an external task pattern
External Tasks | docs.camunda.org
?

Thanks, I will try that out right away.