Finding Job instance associated with a user task in a given process instance

Disclaimer: I’m aware of the following similar questions asked on the forum.

None of them provided me the answer. Therefore, I’m taking liberty to post my question.

In the given simple process there is a timer which monitors the user task with a deadline.

The attempt is to acquire the timer Job instance programmatically so that it can be suspended/resumed at will.

In order to achieve that, a combined JavaDelegate and TaskListner class has been added to User Task “Random User Task”. Unfortunately though, it cannot find any job instances. The delegate class has been attached to start execusion listner for the user task as well as to create and assignment events as task listner.
The code in the execution/task listener looks like below.

final ManagementService managementService = execution.getProcessEngineServices().getManagementService();

LOGGER.info("How many jobs are there for current process instance? "
   + managementService
  .createJobQuery()
  .processInstanceId(execution.getProcessInstanceId())
  .count());
LOGGER.info("How many jobs are there in total? " + managementService.createJobQuery().count());
for (var job : managementService.createJobQuery().list()) {
  LOGGER.info("\nJob Details: " + job.toString());
}

The example log extracts are:


INFORMATION:

LoggerDelegate::execute invoked by processDefinitionId=JobFinder:1:3, activtyId=randomUserTask, activtyName='Random User Task', processInstanceId=5, businessKey=null, executionId=7

Jan. 24, 2020 3:14:50 NACHM. test.camunda.delegation.LoggerDelegate execute

INFORMATION: How many jobs are there for current process instance? 0

Jan. 24, 2020 3:14:50 NACHM. test.camunda.delegation.LoggerDelegate execute

INFORMATION: How many jobs are there in total? 0

Jan. 24, 2020 3:14:50 NACHM. test.camunda.delegation.LoggerDelegate notify

INFORMATION:

LoggerDelegate::notify invoked by processDefinitionId=JobFinder:1:3, activtyId=randomUserTask, activtyName='Random User Task', processInstanceId=5, businessKey=null, executionId=7

Jan. 24, 2020 3:14:50 NACHM. test.camunda.delegation.LoggerDelegate notify

INFORMATION: Current Event: create

Jan. 24, 2020 3:14:50 NACHM. test.camunda.delegation.LoggerDelegate notify

INFORMATION: How many jobs are there for current process instance? 0

Jan. 24, 2020 3:14:50 NACHM. test.camunda.delegation.LoggerDelegate notify

INFORMATION: How many jobs are there in total? 0

Jan. 24, 2020 3:14:50 NACHM. test.camunda.delegation.LoggerDelegate notify

INFORMATION:

LoggerDelegate::notify invoked by processDefinitionId=JobFinder:1:3, activtyId=randomUserTask, activtyName='Random User Task', processInstanceId=5, businessKey=null, executionId=7

Jan. 24, 2020 3:14:50 NACHM. test.camunda.delegation.LoggerDelegate notify

INFORMATION: Current Event: assignment

Jan. 24, 2020 3:14:50 NACHM. test.camunda.delegation.LoggerDelegate notify

INFORMATION: How many jobs are there for current process instance? 0

Jan. 24, 2020 3:14:50 NACHM. test.camunda.delegation.LoggerDelegate notify

INFORMATION: How many jobs are there in total? 0

On the other hand, the process can be driven through a test JUnit test driver application. There using the management service instance acquired through process engine object can indeed display the job.
The code in the test driver function is

System.out.println("\nJob Count: " + query.count());
for (var job : query.list()) {
  System.out.println("\nJob Details: " + job.toString());      
}

The output on console is below.


===========================================================

Job Count: 1

Job Details: TimerEntity[repeat=null, id=9, revision=1, duedate=Sat Jan 25 15:14:50 CET 2020, repeatOffset=0, lockOwner=null, lockExpirationTime=null, executionId=7, processInstanceId=5, isExclusive=true, retries=3, jobHandlerType=timer-transition, jobHandlerConfiguration=timerTaskTerminator, exceptionByteArray=null, exceptionByteArrayId=null, exceptionMessage=null, deploymentId=1]

===========================================================

I’m trying to solve this mystery, why execution listener cannot see any jobs whereas test application can. Could anyone please help me?
The link to full fledged application code is here

Thanks and Regards
Chaitanya

Hey chaitanyajoshi,

I’m kinda new at camunda, so don’t take too much out of my response :slight_smile:

I checked out your code and added another wait-state to the user task ( asynchronous Before + exclusive ). Although user tasks are always wait-states, I’d assume calling the listener comes first in comparison to actually creating the job and writing the transaction to the database.

Anyways: try changing Asynchronous Continuations to your user task in the general properties panel of your user task.
This is what my log afterwards said:

LoggerDelegate::notify invoked by processDefinitionId=JobFinder:2:e824cf80-404c-11ea-bb99-001f1fc10ed5, activtyId=randomUserTask, activtyName=‘Random User Task’, processInstanceId=0933f21a-404d-11ea-bb99-001f1fc10ed5, businessKey=222, executionId=09359fce-404d-11ea-bb99-001f1fc10ed5
16:03:39,956 INFO [test.camunda.delegation.LoggerDelegate] (pool-15-thread-11) Current Event: create
16:03:39,957 INFO [test.camunda.delegation.LoggerDelegate] (pool-15-thread-11) How many jobs are there for current process instance? 1
16:03:39,958 INFO [test.camunda.delegation.LoggerDelegate] (pool-15-thread-11) How many jobs are there in total? 5

@ chaitanyajoshi - Hi Chaitanya ,

You code looks correct . Its strange that it doesnt return any results . Did you try to get the exact job id for the task using the “activityId” and see if anything is getting printed in the logs . i used the below code with a non interrupting timer and it worked .

ManagementService managementService = execution.getProcessEngineServices().getManagementService();
TaskService taskService = execution.getProcessEngineServices().getTaskService();
Job timerJob = managementService.createJobQuery().
processInstanceId(execution.getProcessInstanceId()).activityId(execution.getCurrentActivityId()).singleResult();

  Task task = taskService.createTaskQuery().executionId(timerJob.getExecutionId()).singleResult();

  task.setPriority(task.getPriority()+10);

Norman, Dinesh, First of all thanks a lot for your support and answers.

@Norman_Luering I tried your approach. I do get a job object but it is not a timer job. Kindly see the log line below which reflects that it is a MessageEntity object which I am pretty sure is introduced by asynchronous before. This proves it - jobHandlerType=async-continuation, jobHandlerConfiguration=transition-create-scope

Job Details: MessageEntity[repeat=null, id=20, revision=2, duedate=null, lockOwner=345016e8-6e01-43b4-94ef-33312f1212e2, lockExpirationTime=Mon Jan 27 10:07:44 CET 2020, executionId=16, processInstanceId=16, isExclusive=true, retries=3, jobHandlerType=async-continuation, jobHandlerConfiguration=transition-create-scope, exceptionByteArray=null, exceptionByteArrayId=null, exceptionMessage=null, deploymentId=1]

@dineshsb Yes I have already tried it without any success.

Just for comparison, the test driver which has access to processEngine object externally can extract a precise timer job (of type TimerEntity) like this.

Job Details: TimerEntity[repeat=null, id=21, revision=1, duedate=Thu Jan 30 10:00:31 CET 2020, repeatOffset=0, lockOwner=null, lockExpirationTime=null, executionId=19, processInstanceId=15, isExclusive=true, retries=3, jobHandlerType=timer-transition, jobHandlerConfiguration=timerModeratorFormCheck, exceptionByteArray=null, exceptionByteArrayId=null, exceptionMessage=null, deploymentId=1]

I’m out of my wits.

Thanks and Regards
Chaitanya

Hi Chaitanya ,

Was a listener defined on the time shape ? Below is how my setup looks . Not sure if it is a issue with the interrupting boundary .

@dineshsb Yes, mine is interrupting timer. It has to be under the requirement.
I am also beginning to worry that it’s a bug or something.

Also which version are you on ?

Tested on 7.12 and 7.13-SNAPSHOT.
Tested using test-runner as well as Camunda Docker image.
Can it be some scope or user rights issue? Or Is there some restriction that execution or task listeners cannot see jobs for a shared engine or something?

After running some more experiments, I have come to a bizarre conclusion for this mystery.
I found that when more than one process instances are running, Management Service API JobQuery can find all previous jobs except for the current process instance. That means,

  • for 3 process instances, timer jobs queried in the third process instance delegate are for the 2 previous process instancs,
  • for 2 process instances, timer job found is for 1 previous process instance and so on.
    When there is only one instance, there is no previous process instance and therefore, total job count is 0. Due to this, jobs for current querying process instance are always zero.

Please read my detailed analysis on github as it’s too long to produce here.

As of 29.01.2020, Camunda v7.13.0-SNAPSHOT, this is a definite bug in JobQuery implementation in Java Management Service API. I am opening a new thread indicating this bug . I hope I can attract attention of Camunda developers.

Update: A Camunda developer has answered it as a limitation of the design.
See the answer here. [Java API] Bug in `JobQuery` implementation in Management Service API?
Also see: Lookup Timer Due date for a Boundary event from Task Create Listener

1 Like