I'm new to the @Schedule annotations in J2EE6
I want to run a job using EJB 3.x with Glassfish 3.1.
The javax.ejb.Schedule seems to be a good choice for us, so we could think of our custom time as something like:
@Singleton
public class CustomTimer {
@EJB
SettingsFacade settingsFacade;
@Schedule(second="someSecondParameter", minute="someMinuteParameter",hour="someHourParameter", persistent=false)
public void executeTimer(){
//Code executing something against database using the settingsFacade
}
}
Here, we want the parameters to be got from database, so they are changed every month. Any clean solution for this?
No, there is no solution with @Schedule
, because annotation attributes in general should be compile time constants.
When more flexibility is needed, programmatic timers can be used.
Also then polling database for changed configuration and removing existing and creating new timers must be implemented.
@Singleton
@Startup
public class ScheduleTimerService {
@Resource private TimerService timerService;
public void setTimerService(TimerService timerService) {this.timerService = timerService; }
@PostConstruct
private void postConstruct() {
timerService.createCalendarTimer(createSchedule());
}
@Timeout
public void timerTimeout(Timer timer) {
Add your code here to be called when scheduling is reached...
in this example: 01h:30m every day ;-)
}
private ScheduleExpression createSchedule(){
ScheduleExpression expression = new ScheduleExpression();
expression.dayOfWeek("Sun,Mon,Tue,Wed,Thu,Fri,Sat");
expression.hour("01");
expression.minute("30");
return expression;
}
}
Well You need to created Two Scheduler
One Scheduler will run to update data from Database
Based On that You Can created Other Scheduler.
But for this Need to do it some what programmatic.
You also can see EJB Timers for the same what will help you in this case. which is also annotation based.
There is a simple way of doing this. I wanted to something that called a process every day but, the job itself should be done randomly over the same day. I managed to do that by adding a simple thread worker to run after the EJB timer service has been called. Then I would put it to sleep for a random amount of time during that day.
The following code is an example of a service that wakes up every 1 minute and waits for a thread to finish.
@Schedule(minute = "*/1", hour = "*", persistent = false)
public void runEveryMinute() throws InterruptedException {
log.log(Level.INFO, "Scheduling for every minute .. now it's: " + new Date().toString());
// Delay, in milliseconds before we interrupt adding a follower thread
//we can therefore garantee that it runs every day
long patience = 1000 * 5;
threadMessage("Starting forever alone no more thread");
long startTime = System.currentTimeMillis();
Thread t = new Thread(new MessageLoop());
t.start();
threadMessage("Waiting for new thread to finish");
// loop until MessageLoop thread exits
while (t.isAlive()) {
threadMessage("Still waiting...");
// Wait maximum of 1 second for MessageLoop thread to finish.
t.join(1000);
if (((System.currentTimeMillis() - startTime) > patience)
&& t.isAlive()) {
threadMessage("Tired of waiting! Adding new followers now!");
t.interrupt();
// Shouldn't be long now -- wait indefinitely
t.join();
}
}
threadMessage("Finally! You are not alone anymore!");
}
// Display a message, preceded by
// the name of the current thread
static void threadMessage(String message) {
String threadName = Thread.currentThread().getName();
System.out.format("%s: %s%n", threadName, message);
}
private static class MessageLoop implements Runnable {
public void run() {
String importantInfo[] = {
"A kid will eat ivy too"
};
try {
for (int i = 0;
i < importantInfo.length;
i++) {
// Pause for 4 seconds
int max = 10;
int min = 2;
int randomTimer = 0 + (int) (Math.random() * ((max - min) + 1));
Thread.sleep(randomTimer * 1000);
// Print a message
threadMessage(importantInfo[i]);
}
} catch (InterruptedException e) {
threadMessage("Patience is not a virtue! Thread stopping for now!");
}
}
}