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

4

8

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?

Missile answered 12/4, 2013 at 14:14 Comment(2)
see also #2599212 don't know about glassfish but maybe expression language + bean property worksKemme
Dear @Missile ,Do you find any solution for parametric scheduler? If you find, could you please have a look at my question: #42242537Crupper
C
4

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.

Carrasco answered 12/4, 2013 at 18:18 Comment(0)
P
7
@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;
    }
}
Pneumatic answered 21/11, 2016 at 20:17 Comment(3)
Thank you @Sólon Soares , I have two questions: 1-How to set this scheduler to be called on startup ? , 2- What is equivalent of @Schedule(second="1", minute="*/5", hour="*", persistent=false) , Please edit your code to run at start up.Crupper
Hi @ H.Aqjn, 1) Startup happens when jboss or another application server is starting. See the annotation "@Startup" above the name class declaration. The server application creates "@PostContruct" programming timer. So when timer is reached it triggers the method annotated by "@Timeout" Therefore, whenever there is a timer change, it should be reloaded the packet in the application server (ear or war or other packet format ..). Expression class accept the same parameters of annotation.Salicin
Dear @Sólon Soares , please have a look at my question: #42242537Crupper
C
4

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.

Carrasco answered 12/4, 2013 at 18:18 Comment(0)
M
0

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.

Masao answered 16/4, 2013 at 9:59 Comment(0)
T
-1

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!");
        }
    }
}
Tica answered 11/6, 2014 at 15:3 Comment(1)
It is a very bad idea to spawn your own threads within a EE container. Do not do this. Use an injected ThreadExecutor at least if you really must so at least they are container managed..Rivera

© 2022 - 2024 — McMap. All rights reserved.