java 有一个带有“crontab 语法”的 EJB 调度任务

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7361889/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 19:40:25  来源:igfitidea点击:

Have an EJB schedule tasks with "crontab syntax"

javajakarta-eeejbcrontabschedule

提问by aksamit

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

我试图找出解决以下问题的可能性。

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

a) 我想要一个使用“crontab 语法”来调度任务的数据库表,结构将是这样的:

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

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

上表将随时被外部应用程序修改。添加或删除的任务应立即影响调度程序。

b) The scheduler itself should reside on a Java application server. It should constantly be synched with the active scheduled tasks in the database table. Whenever a schedule event occurs it should trigger/call an EJB with the value in 'Task' as argument.

b) 调度器本身应该驻留在 Java 应用服务器上。它应该不断与数据库表中的活动计划任务同步。每当调度事件发生时,它应该以“Task”中的值作为参数触发/调用 EJB。

I am not looking for an answer to the above problem. But rather some input in what frameworks can be used for the crontab parsing and in what manner the EJB representing the scheduler should be deployed.

我不是在寻找上述问题的答案。而是关于哪些框架可用于 crontab 解析以及代表调度程序的 EJB 应以何种方式部署的一些输入。

Thanks in advance.

提前致谢。

回答by David Blevins

See the EJB 3.1 @ScheduleAPI. The API we chose for the spec is a little closer to Quartz syntax than cron -- tiny variances between the two.

请参阅 EJB 3.1 @ScheduleAPI。我们为规范选择的 API 比 cron 更接近 Quartz 语法——两者之间的差异很小。

Here's an annotation example:

这是一个注释示例:

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's 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();
    }
}

Full source for this here

这里的完整来源

You can do the same thing programmatically via the ScheduleExpressionclass which is just a constructable version of the above annotation. Here's what the above example would look like if the schedule was done in code:

您可以通过ScheduleExpression类以编程方式执行相同的操作,该类只是上述注释的可构造版本。如果计划是在代码中完成的,那么上面的示例将如下所示:

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's 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

这个例子的来源是here

Side note, both examples are runnable in a plain IDE and have test cases that use the Embeddable EJBContainerAPI also new in EJB 3.1.

旁注,这两个示例都可以在普通 IDE 中运行,并且具有使用EJB 3.1 中的新功能Embeddable EJBContainerAPI 的测试用例。

@Schedule vs ScheduleExpression

@Schedule 与 ScheduleExpression

  • @Schedule
    • Statically configured
    • Many schedule methods are possible
    • Not possible to pass arguments
    • Cannot be cancelled
  • @日程
    • 静态配置
    • 许多调度方法是可能的
    • 无法传递参数
    • 不能取消

The above is all done in the deployment descriptor and is therefore limited to only things that can be configured in advance. The more dynamic version uses the following signature of the TimerService:

以上都是在部署描述符中完成的,因此仅限于可以提前配置的内容。更动态的版本使用 TimerService 的以下签名:

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

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

  • ScheduleExpression
    • Dynamically created
    • Exactly one @Timeout supports all ScheduleExpression
    • The timeout method must take javax.ejb.Timeras a parameter
    • Arguments can be passed
    • Can be cancelled by the caller or the @Timeout method
  • 调度表达式
    • 动态创建
    • 正好一个@Timeout 支持所有的 ScheduleExpression
    • 超时方法必须javax.ejb.Timer作为参数
    • 可以传递参数
    • 可以由调用者或@Timeout 方法取消

Also note that there is an interceptor @AroundTimeoutannotation that functions identically to @AroundInvokeand allows interceptors to participate in the bean's timer functionality.

另请注意,有一个拦截器@AroundTimeout注释,其功能与拦截器的功能相同,@AroundInvoke并允许拦截器参与 bean 的计时器功能。

回答by mikek

EJB has its own built in timers, but you'll have to write the boilerplate code to translate cron parsing. The parsing of the cron instructions themselves should be trivial.

EJB 有自己内置的timers,但是您必须编写样板代码来转换 cron 解析。cron 指令本身的解析应该是微不足道的。

If you're not afraid of venturing outside of EJB, Quartz is as lexicore mentioned an excellent option.

如果您不害怕在 EJB 之外冒险,那么 Quartz 就像 lexicore 提到的那样是一个很好的选择。

回答by lexicore

Take a look at Quartz. If you use Spring there's very good support there. A neat, reliable good-working thing.

看看石英。如果你使用 Spring,那里有很好的支持。一个整洁、可靠的好工作。