cancel
Showing results for 
Search instead for 
Did you mean: 

Create or modify Job / Timer by program

aeross
Champ in-the-making
Champ in-the-making
Hi,

I want to create or modify a Job / Timer by program. a possible use case is a priority changement that leads dueDate change and necessarily associated Job . I tested like this :

1. I'm looking for a job  that i want to modify and modify it

// get actual Job and modifying it
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
final Date d = sdf.parse((String) processEngine .getRuntimeService().getVariable(processInstanceId, "dueDate"));
final Long expirationTime = d.getTime() - 2700000;
final Date expirationDate = new Date(expirationTime);
final StringBuilder sb = new StringBuilder("R3/");
sb.append(sdf.format(expirationDate));
sb.append("/PT15M");

final JobEntity j = (JobEntity) processEngine.getManagementService()
                                             .createJobQuery()
                                             .processInstanceId(processInstanceId)
                                             .singleResult();
final TimerEntity timer = (TimerEntity) j;
timer.setDuedate(d);
timer.setRepeat(sb.toString());



2. I test to record theses changes

Context.getCommandContext().getJobEntityManager().schedule(timer);

[indent]In this case CommandContext is  null and I don't know why. Can you light me?[/indent]



3. After looking to code "JobEntityManager.java" at line 53 and "JobEntity.java" at line 83 it test that

final Command<String> c = new Command<String>() {
                @Override
                public String execute(CommandContext cc) {
                    MessageEntity message = new MessageEntity();
                    cc.getJobEntityManager().send(message);
                    return message.getId();
                }
            };
final CommandContext cc = ((ProcessEngineImpl) processEngine).getProcessEngineConfiguration()
                                                             .getCommandContextFactory()
                                                             .createCommandContext©;

cc.getDbSqlSession().update(timer);

[indent]No errors but Job is not updated, I test with flushing and commit DbSqlSession with no more results.[/indent]



What i'm doing wrong? Or what is necessary that i not doing?

Thanks.

6 REPLIES 6

trademak
Star Contributor
Star Contributor
Hi,

What you are trying to do is internal functionality and therefore it's not part of our public api.
The command context is null because there is no command context in the thread local context of the Context class yet. You can create a command context via processEngineConfig.getCommandExecutorTxRequired().execute(command). That should work fine.

Best regards,

aeross
Champ in-the-making
Champ in-the-making
Thank Tijs ,
clear and fast response!

It works.

If i can abuse a little, i have a second question about timer, boundaryTimer precisely.
I have in my bpmnModel a boundaryTimer that i use to send reminder mail, i repeat it 3 times at 45 minutes to the due date.
Until then all is well, but is exist a way to bypass or cancel a boundaryEvent?

Thanks

trademak
Star Contributor
Star Contributor
No there's no way to cancel a boundary event. But what you could do is add some conditional logic based on a variable that you set to check if the boundary event logic should be executed.

Best regards,

aeross
Champ in-the-making
Champ in-the-making
Hi Tijs, i don't understand completely your workaround.

My BpmnModel look likes that :

<code>
<userTask id="validation" name="validation" activitiSmiley Tongueriority="${priority}">
     <extensionElements>
          <activiti:taskListener class="com.aeross.activiti.ejb.listeners.TaskListener" />
     </extensionElements>
</userTask>

<userTask id="inProgress" name="inProgress" activitiSmiley Tongueriority="${priority}">
     <extensionElements>
          <activiti:taskListener class="com.aeross.activiti.ejb.listeners.TaskListener" />
     </extensionElements>
</userTask>



<boundaryEvent id="dueDateValidationTimer" cancelActivity="false" attachedToRef="validation">
     <timerEventDefinition>
          <timeCycle>${reminderTimerRepeat}</timeCycle>
     </timerEventDefinition>
</boundaryEvent>

<boundaryEvent id="dueDateInProgressTimer" cancelActivity="false" attachedToRef="inProgress">
     <timerEventDefinition>
          <timeCycle>${reminderTimerRepeat}</timeCycle>
     </timerEventDefinition>
</boundaryEvent>


<serviceTask id="reminder" activiti:class="com.aeross.activiti.ejb.listeners.ReminderTimer"/>

<sequenceFlow id='flow3' sourceRef='validation' targetRef='inProgress' />
<sequenceFlow id='flow4' sourceRef='inProgress' targetRef='theEnd' />
<sequenceFlow id="flow5" sourceRef="dueDateValidationTimer" targetRef="reminder" />
<sequenceFlow id="flow6" sourceRef="dueDateInProgressTimer" targetRef="reminder" />
</code>

I attached to userTask ("validation" and "inProgress") a boundaryEvent that will repeat 3 times at 15 minutes interval from 45 before dueDate, boundaryEvent call serviceTask who send mail and log information.
When timer expired and i want to complete "validation" task where time was attached, i have this error : "activiti org.activiti.engine.ActivitiIllegalArgumentException: duedate is null".
I think activiti engine want to schedule timer attached to "inProgress" task and i don't know how to solve this problem.


Can you explain to me what's your workaround with these new information?

Thanks in advance.

aeross
Champ in-the-making
Champ in-the-making
Hi,
to come back to my problem, i just test a workaround that satisfy me, that is:
1. to compare dueDate and the current time (new Date())
2. if dueDate is less than the current time
3. setting reminder variable to "0 0/5 * * * ?" the timeCyle will be unbounded
4. in ReminderTimer class checking task is assigned (no mail is sent) or not (a mail is sent to group / user candidate)

It works.

Best Regards.

frederikherema1
Star Contributor
Star Contributor
Thanks for posting back the solution you came up with.