简体   繁体   中英

Dynamic parameters for @Schedule method in an EJB 3.x

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?

@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;
    }
}

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.

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!");
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM