How to schedule tasks without Quartz - java

Can anyone tell,advice how to run a scheduler without Quartz in java. I want to implement such features that if application server remain stop , my scheduler will run. So I thought the executable class to place outside of the war file. So can anyone give me suggestion ? Thanks.

Regarding scheduling tasks without Quartz, you can use Java's ScheduledExecutorService:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
final Runnable beeper = new Runnable() {
public void run() { System.out.println("beep"); }
};
// Beeps every 10 seconds
scheduler.scheduleAtFixedRate(beeper, 0, 10, TimeUnit.SECONDS);
Now, regarding doing it when your application is not running, I see three options:
Develop a stand-alone application with your scheduled tasks, decoupled from your webapp
Look up for Application Server features for that purpose
OS scheduled tasks, as Linux's cron job

Related

ThreadPool Executor not executing threads in GAE

I am trying to use executor framework in Google App engine. Bellow is the code that I am trying to run.
Thread thread = ThreadManager.createBackgroundThread(new Runnable(){
public void run(){
try{
LOGGER.info( "Checking background thread");
Thread.sleep(10);
}
catch (InterruptedException ex){
throw new RuntimeException("Exception:", ex);
}
}
});
ScheduledThreadPoolExecutor executor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(10, ThreadManager.backgroundThreadFactory());
executor.scheduleAtFixedRate(thread, 0, 30, TimeUnit.MINUTES);
But this doesn't start the thread. But if I use thread.start() it works properly. I have checked Whitelisted Classes and it does provide Executor classes. So where I am doing it wrong ?
Saikat,
You should always try to avoid creating threads on App Engine, because of it's distributed and dynamic nature it tends to have really bad/unexpected results.
In your case multiple instances will spawn multiple (local) threads sending many times the same notification. Also, bear in mind GAE front end instances have a 1 minute request limit, so after that time the server will kill that request.
Fortunately App Engine provides the Cron service for exactly this situations.
The Cron Service will allow you to schedule a job to run at a given time or every given period. When the cron is triggered GAE will call a configured URL so you can do your process, in your case send notifications.
Eg:(from the link provided)
<cron>
<url>/weeklyreport</url>
<description>Mail out a weekly report</description>
<schedule>every monday 08:30</schedule>
<timezone>America/New_York</timezone>
</cron>
will make an HTTP request to /weeklyreport every monday #8:30.

How can I automatically invoke a servlet periodically at specified time intervals [duplicate]

This question already has answers here:
How to run a background task in a servlet based web application?
(5 answers)
Closed 8 years ago.
Have to call the servlet periodically.(like service concept in andorid)
How to do this. Using timer or any other solution?
Thanks in advance.
To expand on the comments by JB Nizet…
The formerly accepted answer is kind of a hack. If the goal is to get some regular task to be performed as part of your web app, Java provides a crew slick technologies to make this happen.
ServletContextListener
The first is a hook defined by the Servlet spec to have code invoked when a web app is deployed and when a web app is shutting down. This hook is the ServletContextListener.
ScheduledExecutorService
The second piece is the executor service added to recent versions of Java as a more sophisticated alternative to the old Timer class. In particular you need the ScheduledExecutorService.
So when your web app start up, the ServletContextListener launches a ScheduledExecutorService. When the ServletContextListener is informed of a shutdown, it tells the executor to gracefully quit.
One trick to this: Be sure to capture all exceptions in your executor. If an exception leaks, the executor silently stops executing. This is a feature not a bug. Read the doc and study up with some googling.
Jakarta Concurrency
Some Servlet containers support Jakarta Concurrency. This specification provides for automatic management of the executor services discussed above.
You can use ,
response.addHeader("Refresh", "5");
"5" denotes 5 seconds .The response.addHeader("Refresh", "5") call adds a response header that is sent back to the client indicating that the browser should make another request of the servlet after 5 seconds.
Same thing can be done using html too,
<meta http-equiv="refresh" content="5" />
you can aslo pass the url here as ,
<meta http-equiv="refresh" content="5" url="example.com"/>
Also have a look at here ..
If you use Java EE 6, an EJB can be packaged in the war, and you can use a #Schedule annotated EJB.
It will be executed periodically, you don't have to do anything else (run threads, or sleep).
You can do this using Java Threads.
Schedule a servlet to load on server startup. See How can I set a servlet to load on startup of the container, rather than on the first request?
In this servlet's init() method, spawn a thread.
In this thread's run() method, calculate the number of milliseconds to wait until the task should be performed. Then call Thread.sleep(msec). Then do the task, and loop (infinitely).
The java.util.Timer class can help a lot.
Use the schedule() method of the java.util.Timer class:
long now = System.currentTimeMillis();
Date whenToRun = new Date(now+millisecondsInFuture);
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
// job code here
}
};
timer.schedule(task, whenToRun);
Or use the scheduleAtFixedRate() method of the java.util.Timer class:
int initialDelay = 30000; // start after 30 seconds
int period = 5000; // repeat every 5 seconds
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
// job code here
}
};
timer.scheduleAtFixedRate(task, initialDelay, period);

Java cron4j scheduled files

I am using the cron4j library for scheduling a program. Here is my code:
public class Main {
public static void main(String[] args) {
// Declares the file.
File file = new File("cron4j.txt");
// Creates the scheduler.
Scheduler scheduler = new Scheduler();
// Schedules the file.
scheduler.scheduleFile(file);
// Starts the scheduler.
scheduler.start();
// Stays alive for five minutes.
try {
Thread.sleep(5L * 60L * 1000L);
} catch (InterruptedException e) {
;
}
// Stops the scheduler.
scheduler.stop();
}
}
Inside the "cron4j.txt" file I have set my program to run every minute.
Must this file (class Main) with the object scheduler be running in order for the program in the file to be executed every minute?
Or once I run this once will the scheduler pass off this job to the operating system?
The program must be continuously running. Cron4j is just hiding the scheduling for you but in reality is a bunch of threads sleeping and waiting for the time to come for execution. The operating system just sees your program as a normal one continuously running.
In order to use the operating system's scheduling mechanisms, you do not use Cron4j but use crontab (on linux) or the task scheduler on Windows.
One more sophisticated scheduler for Java, which is more considered the Industry standard is Quartz Scheduler. However the concept is the same, your program needs to be running for the scheduled tasks to happen.

putting a timeout for each of executes in java.​util.​concurrent.ExecutorService

How can I create a timeout for each command that is running in parallel using java.​util.​concurrent.ExecutorService?
My code is something like this:
For example in the code below I need obj1 run for maximum 1 min, and obj2 for 2 mins and others 5 mins.
ExecutorService exService;
exService = Executors.newCachedThreadPool();
exService.execute(obj1);
exService.execute(obj2);
exService.execute(obj3);
exService.execute(obj4);
exService.shutdown();
boolean finshed = exService.awaitTermination(5, TimeUnit.MINUTES);
if (finshed) {
//Doing something
}
EDIT:
Unfortunately the class of obj1 - obj4 is scraping some web pages using WebHarvest that uses jakarta HttpClient for reading web pages and HttpClient (And neither WebHarvest itself) doesn't have any feature for timeout on entire page reading and/or scraping job.
This is my time consuming task and I thought about killing ExecutorService thread after a timeout to handle this problem.
In general, there is no reliable way to make a separate thread quit. In particular, there is no reliable way to interrupt and stop your task after a timeout from outside that task. What you need to do is make the tasks themselves responsible for stopping after their time runs out. Depending on what they do, you might be able to abstract this behaviour into a superclass something like:
public abstract class TimeoutRunnable implements Runnable {
private final long timeLimitMillis;
private long startTimeMillis;
public TimeoutRunnable(long timeLimitMillis) {
this.timeLimitMillis = timeLimitMillis;
}
public final void run() {
startTimeMillis = System.currentTimeMillis();
while (System.currentTimeMillis() - startTimeMillis < timeLimitMillis) {
runIteration();
}
}
protected abstract void runIteration();
}
Then in your subclass override, runIteration() and perform a single "step" of the task.
The only reasonably reliable way to kill a task is to run it in a separate process and kill that process if it times out. Using any other approach with a library which does not support timeouts is likely to be error prone at best.
from my point of view I think that such stuff requires some more robust foundations than plain Java standard classes , that 's why I would suggest to use any scheduler infrastructure (Quartz or any other project) which may gives you handles (job identifiers) to kill your time consuming tasks .
You may have something like this :
Main Thread launches the Quartz Scheduler , receive subscriptions from different jobs
saying : Job1,Job 2 and TimeCheckerJob
TimeCheckerJob would be a forever job ,notified to any new job and would check for living time for each any new job... In this job you would have to deal with start time of each job, beware of the OS clocks and don't try to setup too hard constraints (nanoseconds is pure fiction).
HTH
My 2 cents
Jerome

Java: addScheduledJobAfterDelay() - can I force a scheduled job to start?

I'm developing a poker game. On the betting stage I create a scheduled job using Red5 iSchedulingService that will run every 8 seconds to forward to the next player to place a bet. Now if the user placed a bet before the 8 seconds are over, I want to manually force the next scheduled job to start.
Is there a way to force the scheduled job to start immediately when required?
You can do this with Executors. There are cleaner implementations, but this is a stab and something basic that does what you want using Future and Callable.
// wherever you set up the betting stage
ScheduledExecutorService bettingExecutor =
Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> future = bettingExecutor.schedule(new BettingStage(), 8,
TimeUnit.SECONDS);
//...
// in the same class (or elsewhere as a default/protected/public class)
private class BettingStage implements Callable<ScheduledFuture<?>> () {
public ScheduledFuture<?> call() thows ExecutionException {
ScheduledFuture<?> future = bettingExecutor.schedule(new BettingStage(), 8,
TimeUnit.SECONDS);
// betting code here
boolean canceled = future.cancel(false); // cancels the task if not running yet
if(canceled) {
// run immediately
future = bettingExecutor.schedule(new BettingStage(),
0, TimeUnit.SECONDS)
}
return future;
}
}
an answer to my specific question that I started with in this thread:
i cannot force to start a scheduled job, but what I can do is remove the scheduled job and start a new job with a delay of 0 seconds.
addScheduledJobAfterDelay() return a string that represents the job id. i can use it to remove the scheduled job. The problem is that there is no way to know if I'm interrupting the scheduled job or not. Executors do provide that information. that is why Executors are better choice in this specific case then using the red5 scheduling service.
how to remove a scheduled job (red5):
ISchedulingService scheduler = (ISchedulingService) getScope().getContext().getBean(ISchedulingService.BEAN_NAME);
scheduler.removeScheduledJob("ScheduleJobString");
the string ScheduleJobString should be replaced with the string that you have received from creating the job:
String scheduleJobString = scheduler.addScheduledOnceJob(DelayInSeconds*1000,new MyJob());

Categories

Resources