Schedule an EJB using the "crontab syntax"

I am trying to figure out what possibilities I can solve to solve the following problem.

a) I want to have a database table that uses the "crontab syntax" for scheduling tasks, the structure would be something like this:

  | -Id- | --- Crontab Syntax --- | --------- Task ---------- |
     |  1 |  30 * * * * * |  MyClass.TaskA (args []) |
     |  2 |  0 1 * * 1-5 * |  MyClass.TaskB (args []) |
     |  |  |  |

The table above will be modified at any time by an external application. Tasks added or removed should instantly affect the scheduler.

b) The scheduler itself must be located on the Java application server. It should be constantly synchronized with the active scheduled tasks in the database table. Whenever a schedule event occurs, it should start / call the EJB with the value in the "Task" as an argument.

I am not looking for an answer to the above problem. But rather, some contribution to what framework can be used for parsing crontab and how the EJB representing the scheduler should be deployed.

Thanks in advance.

+6
source share
3 answers

See the EJB 3.1 @Schedule . The API that we selected for specification is a little closer to the syntax of quartz than the tiny deviations between them.

Here is an example annotation:

 package org.superbiz.corn; import javax.ejb.Lock; import javax.ejb.LockType; import javax.ejb.Schedule; import javax.ejb.Schedules; import javax.ejb.Singleton; import java.util.concurrent.atomic.AtomicInteger; /** * This is where we schedule all of Farmer Brown corn jobs */ @Singleton @Lock(LockType.READ) // allows timers to execute in parallel public class FarmerBrown { private final AtomicInteger checks = new AtomicInteger(); @Schedules({ @Schedule(month = "5", dayOfMonth = "20-Last", minute = "0", hour = "8"), @Schedule(month = "6", dayOfMonth = "1-10", minute = "0", hour = "8") }) private void plantTheCorn() { // Dig out the planter!!! } @Schedules({ @Schedule(month = "9", dayOfMonth = "20-Last", minute = "0", hour = "8"), @Schedule(month = "10", dayOfMonth = "1-10", minute = "0", hour = "8") }) private void harvestTheCorn() { // Dig out the combine!!! } @Schedule(second = "*", minute = "*", hour = "*") private void checkOnTheDaughters() { checks.incrementAndGet(); } public int getChecks() { return checks.get(); } } 

The full source for this is here.

You can do the same programmatically using the ScheduleExpression class, which is just a constructive version of the above annotation. Here is what the above example looks like if the schedule was executed in code:

 package org.superbiz.corn; import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.ejb.Lock; import javax.ejb.LockType; import javax.ejb.ScheduleExpression; import javax.ejb.Singleton; import javax.ejb.Startup; import javax.ejb.Timeout; import javax.ejb.Timer; import javax.ejb.TimerConfig; import javax.ejb.TimerService; import java.util.concurrent.atomic.AtomicInteger; /** * This is where we schedule all of Farmer Brown corn jobs * * @version $Revision$ $Date$ */ @Singleton @Lock(LockType.READ) // allows timers to execute in parallel @Startup public class FarmerBrown { private final AtomicInteger checks = new AtomicInteger(); @Resource private TimerService timerService; @PostConstruct private void construct() { final TimerConfig plantTheCorn = new TimerConfig("plantTheCorn", false); timerService.createCalendarTimer(new ScheduleExpression().month(5).dayOfMonth("20-Last").minute(0).hour(8), plantTheCorn); timerService.createCalendarTimer(new ScheduleExpression().month(6).dayOfMonth("1-10").minute(0).hour(8), plantTheCorn); final TimerConfig harvestTheCorn = new TimerConfig("harvestTheCorn", false); timerService.createCalendarTimer(new ScheduleExpression().month(9).dayOfMonth("20-Last").minute(0).hour(8), harvestTheCorn); timerService.createCalendarTimer(new ScheduleExpression().month(10).dayOfMonth("1-10").minute(0).hour(8), harvestTheCorn); final TimerConfig checkOnTheDaughters = new TimerConfig("checkOnTheDaughters", false); timerService.createCalendarTimer(new ScheduleExpression().second("*").minute("*").hour("*"), checkOnTheDaughters); } @Timeout public void timeout(Timer timer) { if ("plantTheCorn".equals(timer.getInfo())) { plantTheCorn(); } else if ("harvestTheCorn".equals(timer.getInfo())) { harvestTheCorn(); } else if ("checkOnTheDaughters".equals(timer.getInfo())) { checkOnTheDaughters(); } } private void plantTheCorn() { // Dig out the planter!!! } private void harvestTheCorn() { // Dig out the combine!!! } private void checkOnTheDaughters() { checks.incrementAndGet(); } public int getChecks() { return checks.get(); } } 

The source for this example is here.

Note that both examples run in a simple IDE and have test cases that use the Embeddable EJBContainer API, also new in EJB 3.1.

@Schedule vs ScheduleExpression

  • @Schedule
    • Statically configured
    • Many scheduling methods are possible.
    • Unable to pass arguments
    • Unable to undo

Everything above is done in the deployment descriptor and therefore is limited only by what can be configured in advance. In a more dynamic version, the following TimerService signature is used:

TimerService.createCalendarTimer (javax.ejb.ScheduleExpression, javax.ejb.TimerConfig)

  • ScheduleExpression
    • Dynamically created
    • Exactly one @Timeout supports all ScheduleExpression
    • The timeout method should take javax.ejb.Timer as a parameter
    • Arguments can be passed
    • Can be canceled by the caller or @Timeout

Also note that there is an interceptor @AroundTimeout annotator that functions identically to @AroundInvoke and allows interceptors to participate in bean timer functions.

+24
source

Take a look at Quartz . If you use Spring, there is very good support. A sophisticated, reliable, well-functioning thing.

0
source

EJB has its own built-in timers , but you will have to write boilerplate code to translate cron parsing. Parsing cron instructions should be trivial.

If you are not afraid to take risks outside the EJB, Quartz, like lexicore, noted a great option.

0
source

Source: https://habr.com/ru/post/896980/


All Articles