Camunda MockExpressionManager doesn't work when the delegate invoked by timer - java

I've configured Camunda engine with org.camunda.bpm.engine.test.mock.MockExpressionManager.
At first glance it works as expected: when I do
Mocks.register("myDelegate", myDelegateMock), the bpmn process invokes my mock, but not the real delegate.
But when there is a task, that invoked by some timer boundary event, the mock is ignored and the real delegate becomes invoked.
I've looked at the code, and found that mocks are stored in the ThreadLocal. And if the tasks is invoked by timer, the execution happens in different thread. And that's looks like a root cause of such behavior. Probably mocks also will not work if the task is marked as asynchronous.
I've also tried the extension
https://github.com/camunda/camunda-bpm-mockito
but looks like internally it uses the same Mocks.register, and also doesn't work for me.
May be there are some other possibilities to mock delegate that will work for the case with timer?

Well, the this is already answered in the thread you mentioned:
Mocks.register is meant to be used in a purely single-threaded,
no-job-executor, "unit test" environment. In such an environment,
instead of setting the time and waiting for the job executor to
process the jobs, you need to explicitly trigger the timer job in your
own testing thread:
Job job = processEngineRule.getManagementService().createJobQuery().singleResult();
processEngineRule.getManagementService().executeJob(job.getId());
Then it should happily resolve the name and should work.
So the solution is: let the process run into the timer event, and then manually execute the job() so the process continues as if the timer was reached. This is a good idea even without the single-thread problem: do not simulate timers in camunda tests, just verify that the process is waiting in the correct step and control if the timer condition (due date) is equal to the one you expected.

Related

How to let a ScheduledExecutorService run a Runnable ahead of the scheduled time?

I'm using a ScheduledExecutorService to run a particular job (implemented as an ordinary Runnable) periodically once in a minute (using method scheduleAtFixedDelay()).
Occasionally, however, I would like it to wake up immediately, invoke the Runnable and then return to its ordinary policy (i.e. wait 1 minute again).
Is there a simple way to achieve this?
I've checked the API of the ScheduledExecutorService and its superclasses, but so far didn't find anything suitable.
Of course I could resort to some other method, like pass the same Runnable to a separate Thread created for the exceptional purpose, but using a method of the ScheduledExecutorService would be more elegant.
Just remember the ScheduledFuture from your call to schedule.
If you then want to run it ahead of time, call future.cancel(), submit the Task again for immediate execution and then schedule it again.

Do aspects execute in their own thread?

I have a pretty short question in relation to AspectJ.
Do aspects execute from a separate thread or do they execute on the existing thread (i.e. the one your main method executes from)?
They execute in the same thread where the advised code was executing. AspectJ is not concerned about threading in any way. Of course, nothing stops you from developing an aspect that, when triggered, would go on and create new threads, or schedule work to an executor service, or whatever else you might come to think of.
It executes on the same thread that your code was initially run from. Aspects are exactly the same as normal code, it is just code that is abstracted away behind some sort of handler. You would need to inspect the code of the actual aspect to determine whether or not it is using multiple threads behind the scenes. But no, by default annotations and aspects will not be run in different threads.

What is a preferred way of closing a third-application thread without waiting for it to complete?

I am currently running the JAR that I cannot change, and sometimes it simply gets stuck for no good reason. I have tried finding the ways to interrupt the thread, stop the thread, etceteras, but no luck.
Each solution offered was about doing the complete exit or waiting for a thread to complete.
What I want to do is to simply close the thread, exactly when the timeout completes, and carry on with the program.
What I do not want to do is use the while loop with a timeout, java.util.concurrent.Future, System.exit, and make a Thread.interrupt call.
None of these will help!
You can't forcibly stop a thread in mid-execution. The Thread.destroy() method would have done that, but it was never implemented, and its documentation explains why it would be unsafe to use even if it worked.
There are some other deprecated methods like Thread.stop() and Thread.suspend() which may actually work, but they're also unsafe to use; again, their documentation explains why.
Telling the thread that it should terminate itself, and then waiting for it to do so, is the only safe way to stop a thread.
As an workaround, you could run your task in an entirely separate process, so that you can destroy it when you want it to stop. That is safe, since processes are isolated from each other and destroying the child process can't leave the parent process in an unstable state.
Interacting with a separate process is more difficult, though, since you can't share variables between processes like you can with threads. You'd need to send messages through the process's input and output streams.
Actually, you can't really solve this!
What I mean is: even if you would manage to kill "your" thread that you used to trigger the 3rd party code - you have no way of killing threads or processes created by the code you are invoking.
If you want to be absolutely sure to kill all and anything, you might have to look into rather complex solutions like:
instead of just using a thread, you create a new process with a new JVM B
in that JVM B, you can call that library
but of course, that requires that you put additional code around; so that "your" code in JVM A can talk to "your" code in JVM B
And now you might be able to tear down that process, and all artifacts belonging to it. Maybe.
And seriously: to be really really sure that the 3rd party library didn't kick of anything that you can't stop; you might even have to run that JVM inside some kind of container (for example a docker instance). That you could tear down and be sure that everything is gone.
Long story short: I think there is no way to absolutely control the threads created in a thread. If you need that level of control, you need to look into "outsourcing" those calls.
You can use Executor for this. It allows you to submit tasks (e.g. runnable) and executes those tasks parallely. Also, once you call shutdown(), it lets you configure the timeout and kills all the workers if they are not finished by that time. An example would look like this:
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.execute(() -> {
//logic to call the method of third party jar
});
//Other business logic
executor.awaitTermination(1, TimeUnit.MINUTES);
executor.shutdownNow();
TimeUnit is an enum, with values like SECONDS, HOURS, MINUTES etc (here's javadoc) so you can configure different time units. A couple of points:
Once shutdownNow is called, no new tasks will be accepted (i.e. you can't call execute or submit) and existing tasks will be stopped. So, we are basically waiting for a minute for tasks to be complete and if it is not complete, we are killing that task.
awaitTermination throws InterruptedException (as it interrupts the threads internally if they are not finished) so you will have to wrap it inside try-catch block.
Here's javadoc for Executor.

How to terminate(or abort) a timetask immediately

I want to terminate(or abort) a task immediately when it is running, not to wait its ending. I search in JDK, the Timer class and the TimerTask class not satisfied, their cancel method is not proper for me, for the task will contiue to execute util it finish, but I want to stop it immediately.
What should I do? I serach for Spring and Quartz, but no good idea...
This is not something that is recommended to do in a multi threaded environment as it can break your code in all sorts of ways. For example imagine you are half way through changing something and suddenly your thread gets killed leaving it in a half-modified state. Because it is not recommended no easy way is provided to do it.
The correct way to do this is to use a Thread and interrupt it.
http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
Inside your Thread code you can check isInterrupted() at times where it would be appropriate to abort and abort, but the abort is controlled by the running thread which is the only thing that knows when it is safe to do so.
The ScheduledExecutorService also allows you to work with a ScheduledFuture and cancel that, which then works in the same way as interrupting the thread does.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#cancel(boolean)

How to cancel Spring timer execution

I need to cancel Spring timer execution or at least change the execution frequency based on some conditions. Was using both org.springframework.scheduling.quartz.SimpleTriggerBean and org.springframework.scheduling.timer.ScheduledTimerTask. Cannot find the way how to do it.
NOTE: This is for Spring 3.0+
Read Spring documentation on scheduling tasks
Use a TaskScheduler service, such as a TimerManagerTaskScheduler or ThreadPoolTaskScheduler.
Schedule your task by calling some TaskScheduler.schedule*() method and store the returning ScheduledFuture.
When you want to cancel execution, invoke ScheduledFuture.cancel(). That will stop further invocations of your task. At this time, you can reschedule if you want by calling TaskScheduler.schedule*() for your task with different parameters.
This is by far not the best solution but if you can't come up with anything else you could always use a boolean that would be checked each time the event is fired and if the boolean is false the run method of the timertask should immediately terminate.
The solution is to assign an id to the org.springframework.scheduling.timer.TimerFactoryBean and then retrieve this bean from the application, cast it to Timer and call cancel method on that object.

Categories