I remember that we cannot kill the current running Quartz Job but we can interrupt and have a boolean check wherever is necessary whether we need to proceed further with the subsequent operations or not.
Even when we implement the InterruptableJob and call the scheduler.interrupt to interrupt the Job, the current executed job will be still running in the server.
Ex:
A named SQL query has been triggered by the job via Hibernate which takes a long time
A call has been made to a third party server where the third party server takes a long time to respond
http://neopatel.blogspot.in/2011/05/quartz-stop-job.html
http://forums.terracotta.org/forums/posts/list/3191.page
Could someone corrects my understanding and explain me how we can kill or stop the "currently" executing Job ?
you can create new abstract class called JobBase for example that implements IJob interface and insert abstract method:
public abstract void ExecuteJob(IJobExecutionContext context);
On JobBase you can implements method Execute like this
public abstract class JobBase : IJob,IInterruptableJob
{
private Thread currentThread;
private ILog logger;
public JobBase(ILog logger)
{
this.logger=logger;
}
public void Execute(IJobExecutionContext context)
{
var thread = new Thread(()=>
{
try
{
this.ExecuteJob(context);
}
catch(Exception ex)
{
this.logger.ErrorFormat("Unhandled exception {0}",ex.ToString());
}
});
thread.Start();
this.currentThread = thread;
this.currentThread.Join();
}
public abstract void ExecuteJob(IJobExecutionContext context);
public void Interrupt()
{
currentThread.Abort();
}
}
Each Job will implements JobExecute method.
public class TestJob :JobBase
{
private ILog logger;
public TeJob(ILog logger):base(logger)
{
}
public override ExecuteJob(IJobExecutionContext context)
{
}
}
Assumes that use some factory for creating a Job
For Stopping a Job you will call method scheduler.Interrupt(new JobKey(jobName));
As you told, there is no way to interrupt "brutally" a job in quartz, neither in JAVA.
You can encapsulate your job's logic in a separate Thread and run it with the ExecutorService.
Take a look to this example: https://stackoverflow.com/a/2275596/1517816
Assume your QuartzJob is the Test class and move your business logic in the Task class.
Hope it helps
I don't know why nobody mentioned this, or maybe this was not available at the time the question was asked.
There is a method called shutdown for a Scheduler instance.
SchedulerFactory factory = new StdSchedulerFactor();
Scheduler scheduler = factory.getScheduler();
The above is used to start a job like
scheduler.start();
Use a flag or something to know when to stop the job from running. Then use
scheduler.shutdown();
How I implemented my requirement:
if(flag==true)
{
scheduler.start();
scheduler.scheduleJob(jobDetail, simpleTrigger);
}
else if(flag==false)
{
scheduler.shutdown();
}
Where jobDetail and simpleTrigger are self explanatory.
Hope it helps. :)
Related
I have a Task Scheduler running in my Micronaut Application as described here. What I want is an option to shutdown this task if I receive some kind of request from the user. How can I do that?
In order to cancel a scheduled task you need to work directly with the TaskScheduler.
The following example explains cancelling of a job.
#Singleton
public class SomeBeanThatDoesScheduling {
private final TaskScheduler taskScheduler;
private ScheduledFuture<?> scheduledFuture;
public SomeBeanThatDoesScheduling(#Named(TaskExecutors.SCHEDULED) TaskScheduler taskScheduler) {
this.taskScheduler = taskScheduler;
}
// on application startup you can register your scheduled task
#EventListener
public void onStartup(StartupEvent startupEvent) {
scheduledFuture = taskScheduler.scheduleWithFixedDelay(initialDelay, interval, this::execute);
}
public void execute() {
System.out.println("The task has been executed");
}
// use this method to cancel the job
public void cancelTheJob() {
if (this.scheduledFuture != null) {
this.scheduledFuture.cancel(false);
}
}
}
I have a problem with sending email with method annotated as #Async.
Firstly, I am not sure if it is possible to work as I want so I need help with explanation.
Here is what am doing now:
In main method i have annotation
#EnableAsync(proxyTargetClass = true)
Next I have AsyncConfig class
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import java.util.concurrent.Executor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
#Configuration
public class AsyncConfig extends AsyncConfigurerSupport {
#Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("email-");
executor.initialize();
return executor;
}
}
Of course, its rest application so i have controller, service etc, looks normally, nothing special
My async method looks like this:
#Async
public void sendEmail() throws InterruptedException {
log.info("Sleep");
Thread.sleep(10000L);
//method code
log.info("Done");
}
I executing this method in another service method:
#Override
public boolean sendSystemEmail() {
try {
this.sendEmail();
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("pending sendEmail method");
return true;
}
Now what I want archive is to ignore executing sendEmail() function and execute return true; meanwhile function sendEmail() will be executing in another Thread. Of course it doesn't work now as I want. Unfortunately.
Note that I am new into async programming, so I have lack of knowledge in some parts of this programming method.
Thanks for any help.
First – let’s go over the rules – #Async has two limitations:
it must be applied to public methods only
self-invocation – calling the async method from within the same class – won’t work
The reasons are simple – the method needs to be public so that it can be proxied. And self-invocation doesn’t work because it bypasses the proxy and calls the underlying method directly.
http://www.baeldung.com/spring-async
I have one situation.
I have one Eclipse job with following code:
private class ExecutionJob extends Job {
public static final String MY_FAMILY = "myJobFamily";
public ExecutionJob(String name) {
super(name);
}
#Override
protected IStatus run(IProgressMonitor monitor) {
monitor.beginTask("executing ...... ", IProgressMonitor.UNKNOWN);
methodForExecution();
monitor.done();
return Status.OK_STATUS;
}
#Override
public boolean belongsTo(Object family) {
return family == MY_FAMILY;
}
}
And this methodForExecution() has code as below :
public void methodForExecution(){
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView("view_id");
}
Now, the situation is, job opens up something like progressmonitor, and my method is trying to access UI which is actually behind this job's progressmonitor. And it gives NullPointerException as the progress monitor does not have ActiveWorkbenchWindow.
I can not use UIJob, as I have to execute this methodForExecution() asynchronously.
Can someone please help me resolving this.
The code you want to run must run in the UI thead.
If most of the work in the job is updating the UI and there is no long running non-UI code then you should use UIJob to run this. This is still scheduled as a job but the runInUIThread method is executed in the UI thread.
If you have a lot of non-UI code especially long running code then use a normal Job but you will have to use Display.asyncExec to run the method in the UI thread:
Display.getDefault().asyncExec(new Runnable()
{
#Override
public void run()
{
methodForExecution();
}
});
In Java 8 you could do:
Display.getDefault().asyncExec(this::methodForExecution);
You can also use syncExec instead of asyncExec to wait for the UI to update.
If the showView is all you want to do you could just do the asyncExec without using a Job.
I'd like to create an Esper engine long running process but I'm not sure of Esper's threading model nor the model I should implement to do this. Naively I tried the following:
public class EsperTest {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
//EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider();
EPServiceProvider epService = EPServiceProviderManager.getProvider("CoreEngine");
epService.addServiceStateListener(new EPServiceStateListener() {
#Override
public void onEPServiceDestroyRequested(EPServiceProvider epsp) {
System.out.println("Service destroyed");
}
#Override
public void onEPServiceInitialized(EPServiceProvider epsp) {
System.out.println("System initialised");
}
});
epService.initialize();
}
}
But the code appears to execute to the end of the main() method and the JVM ends.
Referring to the Esper documentation, section 14.7 p456:
In the default configuration, each engine instance maintains a single timer thread (internal timer)
providing for time or schedule-based processing within the engine. The default resolution at which
the internal timer operates is 100 milliseconds. The internal timer thread can be disabled and
applications can instead send external time events to an engine instance to perform timer or
scheduled processing at the resolution required by an application.
Consequently I thought that by creating a an engine instance ("CoreEngine") at least one (timer) thread would be created and assuming this is not a daemon thread the main() method would not complete but this appears not to be the case.
Do I have to implement my own infinite loop in main() or is there a configuration which can be provided to Esper which will allow it to run 'forever.?
The timer threads is a daemon thread.
Instead of a loop use a latch like this.
final CountDownLatch shutdownLatch = new CountDownLatch(1);
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
shutdownLatch.countDown();
}
});
shutdownLatch.await();
My problem is that in the main class I have some osgi references that work just fine when the class is call. But after that all the references became null. When I close the main windows and call shutdown method, the hubService reference returns null. What do I do wrong here?
private void shutdown() {
if(hubService == null) {
throw new NullPointerException();
}
hubService.shutdownHub(); // why is hubService null?
}
// bind hub service
public synchronized void setHubService(IHubService service) {
hubService = service;
try {
hubService.startHub(PORT, authenticationHandler);
} catch (Exception e) {
JOptionPane.showMessageDialog(mainFrame, e.toString(), "Server", JOptionPane.ERROR_MESSAGE);
System.exit(0);
}
}
// remove hub service
public synchronized void unsetHubService(IHubService service) {
hubService.shutdownHub();
hubService = null;
}
If a field can be read and written by multiple threads, you must protect access to read as well as write. Your first method, shutdown, does not protect the read of hubService so that the value of hubService can change between the first read and the second read. You don't show the declaration of the hubService field. You could make it volatile or only read when synchronized (on the same object used to synchronized when writing the field). Then your shutdown implementation could look like:
private volatile IHubService hubService;
private void shutdown() {
IHubService service = hubService; // make a copy of the field in a local variable
if (service != null) // use local var from now on since the field could have changed
service.shutdownHub();
}
I assume your shutdown method is the DS deactivate method? If so, why do you shutdown in the unset method as well in the shutdown method?
Overall the design does not seem very sound. The IHubService is used as a factory and should return some object that is then closed in the deactivate method. You made the IHubService effectively a singleton. Since it must come from another bundle, it should handle its life cycle itself.
Since you also do not use annotations, it is not clear if your set/unset methods are static/dynamic and/or single/multiple. The following code should not have your problems (exammple code with bnd annotations):
#Component public class MyImpl {
IHubService hub;
#Activate
void activate() {
hubService.startHub(PORT, authenticationHandler);
}
#DeActivate
void deactivate() {
hubService.shutdown();
}
#Reference
void setHub(IHubService hub) { this.hub = hub; }
}