cancel
Showing results for 
Search instead for 
Did you mean: 

Non Recursive Looping and Border Timers Trouble

coner
Champ in-the-making
Champ in-the-making
activiti 5.6, eclipse plugin

(2 part question)

1:
I have been having trouble creating border timer events successfully.

My model is a simple diagram with 2 service tasks, they only have System.out.println's inside of them.

I have been trying to setup the diagram such that the first event executes, and if it takes > 3 seconds to complete, the second task will also execute. Then the program will end.

Start -> Print Hello -> Exit
Timer:LimitExceeded
Print Slow Process -> Exit

this example is nearly identical to the one in the userguide except i am using PT4S instead of PT4H. I have been testing the timer by using Thread.sleep() in the first service task.

Also <property name="jobExecutorActivate" value="true" /> is in the activiti.cfg.xml file.

the error that appears is:

Jul 21, 2011 5:48:15 PM org.activiti.engine.impl.interceptor.CommandContext close
SEVERE: Error while closing command context
java.lang.NullPointerException
at org.activiti.engine.impl.jobexecutor.TimerExecuteNestedActivityJobHandler.execute(TimerExecuteNestedActivityJobHandler.java:39)
at org.activiti.engine.impl.persistence.entity.JobEntity.execute(JobEntity.java:78)
at org.activiti.engine.impl.persistence.entity.TimerEntity.execute(TimerEntity.java:62)
at org.activiti.engine.impl.cmd.ExecuteJobsCmd.execute(ExecuteJobsCmd.java:58)
at org.activiti.engine.impl.interceptor.CommandExecutorImpl.execute(CommandExecutorImpl.java:24)
at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:42)
at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:33)
at org.activiti.engine.impl.jobexecutor.ExecuteJobsRunnable.run(ExecuteJobsRunnable.java:36)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Exception in thread "pool-1-thread-6" java.lang.NullPointerException
at org.activiti.engine.impl.jobexecutor.TimerExecuteNestedActivityJobHandler.execute(TimerExecuteNestedActivityJobHandler.java:39)
at org.activiti.engine.impl.persistence.entity.JobEntity.execute(JobEntity.java:78)
at org.activiti.engine.impl.persistence.entity.TimerEntity.execute(TimerEntity.java:62)
at org.activiti.engine.impl.cmd.ExecuteJobsCmd.execute(ExecuteJobsCmd.java:58)
at org.activiti.engine.impl.interceptor.CommandExecutorImpl.execute(CommandExecutorImpl.java:24)
at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:42)
at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:33)
at org.activiti.engine.impl.jobexecutor.ExecuteJobsRunnable.run(ExecuteJobsRunnable.java:36)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)







————————————————————————————————————


2:

Because of the above problem I decided to use exclusive gates to branch back to an earlier part of my application (essentially a loop) but….

start -> print "hello" -> Thread.sleep() -> exclusiveGate (goto Hello) -> exit

I have run into a problem where the branch is apparently a recursive call within the workflow.

Is every step inside of the workflow actually a recursive type call to the next step (aka from start -> hello or hello -> sleep)?  Or are only the branching steps recursive (aka from gate -> hello)?

Furthermore, what is the solution for non-recursive looping without putting the entire workflow into a 3rd party scheduler?


edit:

are any optimizations done on workflows that use the same javaDelegate? or will it re-create the instance of the class within that service task every time it is replicated? -> I am wondering about this because I am trying to test the stack depth limit on activiti.  (I do not know the overhead of the engine's creation of new tasks within the flow)
8 REPLIES 8

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
First of all, it is always better to use two posts for two issues, even if they seam related.

1: Your example is identical besides using PT4S instead of PT4H… BUT you also use service tasks instead of user tasks… This latter is a huge difference, since a user task is a wait state and the services task is not. It sounds like your service task is actually doing things when the timeout occurs, ok sleep() but the thread is used. Cancelling a running servicetask might be a problem… That is not what it was designed for afaik. So if you want this analysed more, create a minimal example of a unittest with a bpmn file that demonstrates the problem. Happy to help then. Or describe what you actually want to achieve. Since e.g. using a send/receive task combination for long running external processes with a timeout might be a solution

2: it's not recursive, it's a loop

A solution for (non-recursive??) looping without waitstates but modeled as a loop? Uhhmm… don't that is 'ab'using bpmn constructs in a way they were never ment to be used.
Again, what is it you want to achieve?

coner
Champ in-the-making
Champ in-the-making
1:

so is it impossible for service tasks to have interaction with BPMN timers?
I would like for the userguide example to function with service tasks (instead of user tasks)…. they can be as trivial as printing out hello and world in java delegate classes.

using a send/receive task combination requires the timeouts to be specified in code and not within the BPMN model correct? (specifying them as activiti process variables is also not acceptable, i would like the model to completely control these timeouts via a drag and drop style creation)

does this mean that interrupts with service tasks also do not work?

2:

it may not be recursive, but the stacktrace that the engine is developing upon the invocation of every service task is recursively built.
the BPMN2.0 spec allows loops as well as infinite loops….

I had intended on moving daemon processes into a workflow which would contain a sleep step (few minutes / hours / days) at which point control would return to the primary service task… loop

instead of that I have had to create 2 workflows that call each other so that the stack does not explode…. this has added a lot of overhead in the startup / kill of each workflow.

coner
Champ in-the-making
Champ in-the-making
re merge from the other thread.

why should canceling a service task be any different than canceling any other task via border timer events?

(why does it matter that a java thread is executing instead of a waitstate that is waiting to be invoked? the java execution should be a thread and so should the timer right? any inconsistency that arises in the java code from being terminated by a timer is the fault of the designer using the boundry timer on a service task.)

is there any way to use service tasks in conjunction with border timer events?
if yes, how?

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
so is it impossible for service tasks to have interaction with BPMN timers?
I think not
using a send/receive task combination requires the timeouts to be specified in code and not within the BPMN model correct?
No, why do you think this?

(specifying them as activiti process variables is also not acceptable, i would like the model to completely control these timeouts via a drag and drop style creation)
Look at thecustom elements in the designer… great solution to have both…

the BPMN2.0 spec allows loops as well as infinite loops….
Agreed, but loops in tasks is something different than looping with transitions back to the same task. The spec is not explicit on the execution semantics of these regarding 'transactions' etc… But it could be that the choice made by Activiti is not the best for what you want technically, but it fits lots of other usecases better and that is a 'compromise' made by the Activiti team based on years of experience. But it does not mean that what you want cannot be achieved, it just is a little (emphasis on little) more complex for you. And the Async continuations being one of the 'additions' that would make your usecase easier to implement.

Regarding your solution, see my reply in the other post….

coner
Champ in-the-making
Champ in-the-making
merge with other thread (dev forum) answer:

example of working java service task + border timer event (i've tried numerous configurations and they all have thread pool errors)?


or merge other answer to this thread from dev forum instead plz

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
why should canceling a service task be any different than canceling any other task via border timer events?
Because they are not the same things…. A send task and script task would have the same 'difficulties'  Compare it with removing a record from a db to a thread that participates in an XA transaction, writing to a file (rollback??) etc.. The amount of work behind the scenes is way more difficult for the latter.

(why does it matter that a java thread is executing instead of a waitstate that is waiting to be invoked?
Technically? A lot… a wait state waiting to be invoked is nothing more than a record in the db (hence my example above) while the javathread is the thread of the engine, participating in transactions etc…Keep in mind that BPMN has no notion of java service tasks!


the java execution should be a thread and so should the timer right?
Yes, but in different transactions etc and more complicating things.

And I never said that this was not something that should not be looked into being supported, it is just not something that is simple to do, or that
'we' even have a good indication if it is worth the effort

edit: cancelling the service task that is.

any inconsistency that arises in the java code from being terminated by a timer is the fault of the designer using the boundry timer on a service task.)
As it is always…

is there any way to use service tasks in conjunction with border timer events?
Have you explicitly tried without the cancelActivitiy? I only above that you used different configurations, but that could as well be different types of databases, or using Linux instead of windows…

if yes, how?
Without cancelActivity it should be supported. If that does not work, it can be concidered a bug and then a jira issue can be made that needs to be fixed. With cancelActivity it is way more complicated as stated above, so no idea what the outcome of that will be.

coner
Champ in-the-making
Champ in-the-making
so if the cancelActiviti = false on the border timer event what will occur -> it will just branch while the first one continues executing?

what would happen when the branch taken out of the border event hits the end node? should it still fail to close the first service task if it has not completed?


i had meant that, yes it is complicated to halt an executing service task thread, but if someone decides to put the border event on a service task they should be writing javacode that is relatively "safe" in regards to when that timer event occurs.

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
so if the cancelActiviti = false on the border timer event what will occur -> it will just branch while the first one continues executing?
Yes.

what would happen when the branch taken out of the border event hits the end node? should it still fail to close the first service task if it has not completed?
I think it will stil 'fail' to cancel an active thread. There will not be a real difference I think (never tried/needed it)

i had meant that, yes it is complicated to halt an executing service task thread, but if someone decides to put the border event on a service task they should be writing javacode that is relatively "safe" in regards to when that timer event occurs.
Agreed, and a 'generic' way of achieving this should be looked into. The methods that need to be implemented in a java class might become more complicated, but maybe a baseclass can be provided. But maybe it is enough to let the actual service run to it's end and just make sure the outgoing transition from the service task is not taken. This will be fairly simple if it can be combined with Async continuations.
Getting started

Tags


Find what you came for

We want to make your experience in Hyland Connect as valuable as possible, so we put together some helpful links.