Liferay 7.1 - Kill a thread execution from scheduler jobs - java

I have my following job in Liferay 7.1 :
#Component(
immediate = true, property = {"cron.expression=0 5 10 * * ? *"},
service = CustomJob.class
)
public class CustomJob extends BaseMessageListener {
....
#Override
protected void doReceive(Message message) throws Exception {
// HERE I CALL A SERVICE FUNCTION TO INACTIVATE USER, SEND MAILS, READ FILES TO IMPORT DATA
RunnableService rs = new RunnableService();
rs.run();
}
....
}
And my RunnableService :
public class RunnableService implements Runnable {
#Override
public synchronized void run() {
// DO MY STUFF
}
}
The job is working great, but another instance of the job can be started even when the service execution from the first call hasn't finished.
Is there any solutions to kill the first process ?
Thanks,

Sounds like there are several options, depending on what you want to achieve with this:
You shouldn't interrupt threads with technical measures. Rather have your long-running task check frequently if it should still be running, otherwise terminate gracefully - with the potential of cleaning up after itself
You can implement your functionality with Liferay's MessageBus - without the need to start a thread (which isn't good behavior in a webapp anyway). The beauty of this is that even in a cluster you end up with only one concurrent execution.
You can implement your functionality outside of the Liferay process and just interact with Liferay's API in order to do anything that needs to have an impact on Liferay. The beauty of this approach is that both can be separated to different machines - e.g. scale.

Related

Using custom thread pool and executors in Jgroups

if we look inside DefaultThreadFactory of Jgroups the following code is present
protected Thread newThread(Runnable r,String name,String addr,String cluster_name) {
String thread_name=getNewThreadName(name, addr, cluster_name);
Thread retval=new Thread(r, thread_name);
retval.setDaemon(createDaemons);
return retval;
}
As new thread is used so I believe in a managed server environment this can cause issues and is also not a good practice.
If I just replace the default thread factories and executors with Managed factories and executors of WebSphere will the behavior of Jgroups be still the same ?
Any pointers will be helpful ..?
Update
My intention is to use JGroups with WebSphere AS 8.5. I am keen to not have any un-managed threads. My main use case is for leader election and some message passing. It will be used to manage Spring Integration pollers and ensure only one poller is running within the cluster.
WAS 8.5 still uses the CommonJ api for Work management.
I am using Spring to abstract the Task Executors and Schedulers.
It was initially easy enough to replace the ThreadPools with task executors as they share the Executor api.
The TaskScheduler had to be adapted to work with your TimeScheduler interface.
They are very similar and perhaps extending from the ScheduledExecutorService could be an option here. I implemented to your interface and delegated to Springs TaskScheduler.
The main issue is with the ThreadFactory. CommonJ does not have this concept. For this I created a ThreadWrapper that encapsulates the Runnable and delegates out to a TaskExecutor when the "Thread's" start method is called. I ignored the thread renaming functionality as this will not have any effect.
public Thread newThread(Runnable command) {
log.debug("newThread");
RunnableWrapper wrappedCommand = new RunnableWrapper(command);
return new ThreadWrapper(taskExecutor, wrappedCommand);
}
public synchronized void start() {
try {
taskExecutor.execute(runnableWrapper);
} catch (Exception e) {
throw new UnableToStartException(e);
}
}
This is where I ran into problems. The issues were in the transports. In a number of cases with in the run method of some of the internal runnables e.g. the DiagnosticsHandler, the TransferQueueBundler of TP and ViewHandler of GMS there is a while statements that checks the thread.
public class DiagnosticsHandler implements Runnable {
public void run() {
byte[] buf;
DatagramPacket packet;
while(Thread.currentThread().equals(thread)) {
//...
}
}
}
protected class TransferQueueBundler extends BaseBundler implements Runnable {
public void run() {
while(Thread.currentThread() == bundler_thread) {
//...
}
}
}
class ViewHandler implements Runnable {
public void run() {
long start_time, wait_time; // ns
long timeout=TimeUnit.NANOSECONDS.convert(max_bundling_time, TimeUnit.MILLISECONDS);
List<Request> requests=new LinkedList<>();
while(Thread.currentThread().equals(thread) && !suspended) {
//...
}
}
}
This does not co-operate with our thread wrapping. If this could be altered so that the equals method is called on the stored thread it would be possible to override it.
As you can see from the various snippets there are various implementations and levels of protections varying from package, protected and public. This is increased the difficulty of extending the classes.
With all of this done it still did not remove completely the issue of unmanaged threads.
I was using the properties file method of creating the protocol stack. This initialises the protocol stack once the properties are set. To remove the Timer threads that are created by the bottom protocol. The TimeScheduler must be set prior the to stack being initialised.
Once this is done the threads are all managed.
Do you have any suggestions on how this could have been achieved more easily?
Yes, you can inject your on thread pools, see [1] for details.
[1] http://www.jgroups.org/manual/index.html#_replacing_the_default_and_oob_thread_pools

Spring-Boot with Swing UI

I want to use dependency injection for my Swing UI components in a Spring-Boot application and having a hard time figuring out, how to properly execute the UI behavior on the Event Dispatch Thread.
What I came up with first was like this:
App
#SpringBootApplication
public class App {
private static AppView view;
#Bean
public AppView appView() {
return view;
}
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(() -> view = new AppView());
SpringApplication app = new SpringApplication(App.class);
app.run(args);
}
}
AppView
public class AppView extends JFrame {
...
#Inject
private DependencyWithTimeConsumingOperations backendController;
#Inject
private JPanel someChildComponent;
#PostConstruct
public void init() {
constructView(); // inits frame properties and child components
showView();
}
private void showView() {
SwingUtilities.invokeLater(() -> {
pack();
setVisible(true);
});
}
...
}
The backend dependency gets called when certain UI events occur. What I observe is, that the backend calls get excuted on the EDT instead of the main application thread, which is bad, I assume. As I understand, not having much experience with Swing, is, that only UI updates should be executed on the EDT.
Is there a better way to wire my dependencies so that everything is executed in its proper thread? What I could find out so far seems a bit outdated or I plainly did not understand the answers :-)
Not sure if it is still relevant to you after so long :), but since it may help others, I'll try to answer.
Spring is only injecting the objects, it is not managing the threads. The behaviour would be the same if you'd instantiated and set the backendController manually, meaning that the EDT (or any thread that is calling the operation) would be the one to execute the code on the controller.
If you explicitly want to run in a different thread, we'd need to know more about the methods in the controller. Are they methods that you want to call and not wait for a reply (fire and forget)? Or maybe you need the reply but can run more than one at the same time? In these scenarios you can take advantage of the Executors class and do something like:
Executors.newSingleThreadExecutor().execute(() -> backendController.timeConsumingOperation1()); // Fire and forget. The operation timeConsumingOperation1 will be executed by a separate thread and the EDT will continue to the next line (won't freeze your GUI)
If you need a result, you may submit it to the pool and poll for the result (maybe with a "refresh" button on the screen). Keep in mind that as soon as you call "get()" the current thread will wait for the pooled thread to finish before proceeding to the next line.
Future result = Executors.newSingleThreadExecutor().execute(() -> backendController.timeConsumingOperation2);
result.isDone(); // You can add a "refresh" button or a scheduled task to check the state...
doSomething(result.get()); // This will hold the current thread until there is a response from the thread running the timeConsumingOperation
Or maybe you do want to freeze the GUI until you have a response from all methods called in the controller, but they can be safely called in parallel:
ExecutorService executorService = Executors.newFixedThreadPool(2);
List<Future<Object>> results = executorService.invokeAll(
Arrays.asList(() -> backendController.timeConsumingOp3(), () -> backendController.timeConsumingOp4));
results.forEach(e -> doSomething(e.get())); // The tasks will be executed in parallel and "doSomething()" will be called as soon as the result for the given index is available
executorService.shutdown(); // Always shutdown
Of course this is just an example, but in large Swing applications it is good practice to create pools of threads (shared by the controllers) to which we submit our long running tasks. You can configure the pool size based on the number of cores (Runtime.getRuntime().availableProcessors()) to best use the resources available on the machine (the tasks submitted will be queued up with no restriction, but only X threads will execute the tasks in parallel, where X is the pool size).
Just use code
SpringApplicationBuilder(Main.class).headless(false).run(args);

How do I interrupt Java code that doesnt finish and doesnt throw ThreadInterruptionException

A load of tasks are submitted to my application but it keeps hanging and I track it down to this code:
uk.ac.shef.wit.simmetrics.tokenisers.TokeniserWhitespace.tokenizeToArrayList(TokeniserWhitespace.java:133)
uk.ac.shef.wit.simmetrics.similaritymetrics.CosineSimilarity.getSimilarity(CosineSimilarity.java:142)
com.jthink.songkong.match.Scorer.compareValues(Scorer.java:74)
com.jthink.songkong.match.Scorer.calculateTitle(Scorer.java:704)
com.jthink.songkong.match.Scorer.matchRecordingOrTrackTitle(Scorer.java:652)
com.jthink.songkong.match.Scorer.calculateTrackScoreWithinRelease(Scorer.java:538)
com.jthink.songkong.match.Scorer.scoreMatrix(Scorer.java:396)
com.jthink.songkong.match.Scorer.calculateReleaseScore(Scorer.java:1234)
It is basically an string matching algorithm in a 3rd party library but it does not throw ThreadInterruptedException so does this mean I cannot interrupt it, but is certainly a long running process having run for 30 minutes. I have a reference to the thread monitoring this code but is there any way to stop it.
Of course I am looking to fix the 3rd party library but in the meantime I need a way to stop my application hanging by cancelling these hanging tasks. What makes it worse for me is that I use Hibernate, and a hibernate session is created in this stack and then because this TokeniserWhitespace method never finishes my session (and hence database connection) is never released therefore eventually I ran out of database connections and the application completely hangs.
I would try Thread.interrupt() as even though the interrupted exception isn't thrown it doesn't necessarily mean that the 3rd party library doesn't handle it correctly in some other way. If that doesn't work then I would consider Thread.stop() even though it is depricated in the hopes that the library's design can handle sudden termination and doesn't end up in an inconsistent state (due to the transactional nature in which you are using it, I doubt there are many shared objects to get corrupted). Thread.stop() will cause the event to stop immediately and throw a ThreadDeath exception no matter what it is doing and it was deprecated by Sun due to the chance of leaving shared objects in an unknown and inconsistent state.
You can can use the Akka library to wrap the problematic code - this will let you kill and restart the code if it hangs.
import scala.concurrent.Future;
public interface ProblemCode {
public Future<String> stringMatch(String string);
}
public class ProblemCodeImpl implements ProblemCode {
public Future<String> stringMatch(String string) {
// implementation
}
}
import akka.actor.ActorSystem;
import akka.actor.TypedActor;
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;
import akka.actor.TypedProps;
public class Controller {
private final ActorSystem system = ActorSystem.create("Name");
private ProblemCode problemCodeActor = getProblemCodeActor();
private ProblemCode getProblemCodeActor() {
return TypedActor.get(system).typedActorOf(new TypedProps<ProblemCodeImpl>(ProblemCode.class, ProblemCodeImpl.class));
}
public String controllerStringMatch(String string) {
while(true) {
try {
// wait for a Future to return a String
return Await.result(problemCodeActor.stringMatch(string), Duration.create(5000, TimeUnit.MILLISECONDS));
} catch (TimeoutException e) {
// Await timed out, so stop the actor and create a new one
TypedActor.get(system).stop(problemCodeActor);
problemCodeActor = getProblemCodeActor();
}
}
}
}
In other words, the controller calls stringMatch on the problem code that has been wrapped in an actor; if this times out (5000 milliseconds in my example) you stop and restart the actor and loop through the controller method again.
ProblemCode will only execute one method at a time (it will enqueue subsequent invocations), so if you want to concurrently execute stringMatch you'll need to create multiple actors and create a router out of them / place them in a queue / etc.

How to run a task in fixed intervals in a multiple-instances Tomcat env.?

I'm scheduling background task to run in fixed-intervals, but as tomcat is running in multiple instances (i.e. multiple start Apache servers; 3 in my case), then the task runs 3 times in each interval.. I would like it to run once (no matter the number of Tomcat instances running).
I'm running a servlet loaded on startup (in web.xml) which will initiate my task:
<servlet>
<servlet-name>OnInit</servlet-name>
<servlet-class>box.OnInit</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
OnInit class initiate single instance of that class:
public class BGTaskRefresh {
private static BGTaskRefresh refreshTaskFactory = null;
private final Timer timer = new Timer();
public BGTaskRefresh() {}
public static void init()
{
if( refreshTaskFactory == null )
{
refreshTaskFactory = new BGTaskRefresh();
refreshTaskFactory.start();
}
}
public void start()
{
timer.schedule(
new TimerTask()
{
public void run()
{
boxService box = new boxService();
box.refreshMethod();
}
},
5 * 60 * 1000, // 5-Min Delay for first run
60 * 60 * 1000); // 60-Mins (Interval between 2 runs)
}
}
You might want to have a look at quartz-scheduler, especially its clustering capabilities:
(source: quartz-scheduler.org)
This might be an overkill in your situation, but Quartz will take care of running the job on only a single instance (using database for synchronization) and will automatically run the job on an idle server.
Another option is hazelcast and distributed locks and queues it provides.
You will need some sort of synchronization mechanism. Although ideally you'd want a distributed scheduler (e.g. Quartz cluster), considering your usage scenario you're likely to have either some mechanism for shared session state or a shared database underlying your application; you can simply record the operation and grab a database-based lock to ensure only one instance will run the command at a time (and double-check after the lock grab to ensure you're not running the same task twice).
Here's one article I've found with a technique for DB-based locking: http://blog.udby.com/archives/15

Is there a way to pause a unit test without blocking the thread

I'm using play 1.2.4 and I'm trying to set up a unit test to test a job.
My job runs at every 2 second and changes the status of certain objects based on some conditions. This is what I use to do this.
#Every("2s")
public class GameScheduler extends Job {
public void doJob(){
//Fetch of object from db and status change based on conditions happens here
}
}
Now in my unit test, I setup those conditions but I want the test to wait say 3 seconds before fetching one of the setup objects and do an assert Equals on its status to see if the job... well did it's job.
If I use
pause(3000);
or something like
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
The test stops but the job also stops. It seems like the job and the test are on the same thread. Is there a way to pause the test without stopping the job? Something like the await() method in the controller
You don't need to test the scheduler because it is supposed to work (since the framework is handling it). What you need is just test if the doJob method is doing its work. So, just write a test like this:
GameScheduler job = new GameScheduler();
job.doJob();
// assert whatever you want here
Though simply testing the job (without waiting for the scheduler to run it for you) would do the trick in most (read this as: probably all) situations, there are some in which it might be interesting to not have to trigger it manually.
For instance, you have a cluster of play apps that share a common configuration set. Change one config in one slave, all the others take note and do the same. Let's say the configuration is kept in memcached. One useful unit test is to manually change some setting using Cache.set, wait for the amount of time it takes for the configurationObserver job to run, then check that the internal config has been updated. This would be even more helpful if there would be a series of jobs updating the configuration, etc.
To do that, you must remember that play in DEV mode uses one thread (this helps debugging a lot, btw). You can simply add this line to your application.conf: %test.application.mode=prod and you'll have multiple threads.
Later edit: It appears that setting the mode to prod doesn't really help in this case. What does help is this: use some "await" magic.
#Test
public void myTest() {
final Lock lock = new ReentrantLock();
final Condition goAhead = lock.newCondition();
/* Here goes everything you need to do before "pausing" */
lock.lock();
try {
/**
* Set whatever time limit you want/need
* You can also use notifiers like goAhead.signal(), from within another thread
*/
goAhead.await(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
assertTrue(whateverINeedToTest);
} finally {
lock.unlock();
}
}

Categories