有一个带有“crontab 语法"的 EJB 调度任务; [英] Have an EJB schedule tasks with "crontab syntax"

查看:23
本文介绍了有一个带有“crontab 语法"的 EJB 调度任务;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找出解决以下问题的可能性.

a) 我想要一个使用crontab 语法"来安排任务的数据库表,结构如下:

<前>|-Id-|---Crontab 语法---|---------任务---------||1 |30 * * * * * |MyClass.TaskA(args[]) ||2 |0 1 * * 1-5 * |MyClass.TaskB(args[]) |||||

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

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

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

提前致谢.

解决方案

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

这是一个注释示例:

package org.superbiz.corn;导入 javax.ejb.Lock;导入 javax.ejb.LockType;导入 javax.ejb.Schedule;导入 javax.ejb.Schedules;导入 javax.ejb.Singleton;导入 java.util.concurrent.atomic.AtomicInteger;/*** 这是我们安排 Farmer Brown 的所有玉米工作的地方*/@单身人士@Lock(LockType.READ)//允许定时器并行执行公共课 FarmerBrown {私有最终 AtomicInteger 检查 = new AtomicInteger();@时间表({@Schedule(month = "5", dayOfMonth = "20-Last", minute = "0", hour = "8"),@Schedule(month = "6", dayOfMonth = "1-10", minute = "0", hour = "8")})私人无效的植物玉米(){//挖出播种机!!!}@时间表({@Schedule(month = "9", dayOfMonth = "20-Last", minute = "0", hour = "8"),@Schedule(month = "10", dayOfMonth = "1-10", minute = "0", hour = "8")})私人无效收获玉米(){//挖出联合收割机!!!}@Schedule(秒 = "*", 分钟 = "*", 小时 = "*")私人无效 checkOnTheDaughters() {检查.incrementAndGet();}公共 int getChecks() {返回checks.get();}}

完整源代码这里

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

package org.superbiz.corn;导入 javax.annotation.PostConstruct;导入 javax.annotation.Resource;导入 javax.ejb.Lock;导入 javax.ejb.LockType;导入 javax.ejb.ScheduleExpression;导入 javax.ejb.Singleton;导入 javax.ejb.Startup;导入 javax.ejb.Timeout;导入 javax.ejb.Timer;导入 javax.ejb.TimerConfig;导入 javax.ejb.TimerService;导入 java.util.concurrent.atomic.AtomicInteger;/*** 这是我们安排 Farmer Brown 的所有玉米工作的地方** @version $Revision$ $Date$*/@单身人士@Lock(LockType.READ)//允许定时器并行执行@启动公共课 FarmerBrown {私有最终 AtomicInteger 检查 = new AtomicInteger();@资源私人 TimerService timerService;@PostConstruct私有无效构造(){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);最终 TimerConfig HarvestTheCorn = new TimerConfig("harvestTheCorn", false);timerService.createCalendarTimer(new ScheduleExpression().month(9).dayOfMonth("20-Last").minute(0).hour(8), gainTheCorn);timerService.createCalendarTimer(new ScheduleExpression().month(10).dayOfMonth("1-10").minute(0).hour(8), gainTheCorn);final TimerConfig checkOnTheDaughters = new TimerConfig("checkOnTheDaughters", false);timerService.createCalendarTimer(new ScheduleExpression().second("*").minute("*").hour("*"), checkOnTheDaughters);}@暂停公共无效超时(定时器定时器){if ("plantTheCorn".equals(timer.getInfo())) {植物玉米();} else if ("harvestTheCorn".equals(timer.getInfo())) {收获玉米();} else if ("checkOnTheDaughters".equals(timer.getInfo())) {checkOnTheDaughters();}}私人无效的植物玉米(){//挖出播种机!!!}私人无效收获玉米(){//挖出联合收割机!!!}私人无效 checkOnTheDaughters() {检查.incrementAndGet();}公共 int getChecks() {返回checks.get();}}

这个例子的来源是这里

旁注,这两个示例都可以在普通 IDE 中运行,并且具有使用 Embeddable 的测试用例 EJBContainer API 在 EJB 3.1 中也是新的.

@Schedule 与 ScheduleExpression

  • @Schedule
    • 静态配置
    • 可以使用多种调度方法
    • 无法传递参数
    • 无法取消

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

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

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

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:

    |-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.

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.

Thanks in advance.

解决方案

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

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 ScheduleExpression class 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:

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

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

@Schedule vs 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.createCalendarTimer(javax.ejb.ScheduleExpression, javax.ejb.TimerConfig)

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

Also note that there is an interceptor @AroundTimeout annotation that functions identically to @AroundInvoke and allows interceptors to participate in the bean's timer functionality.

这篇关于有一个带有“crontab 语法"的 EJB 调度任务;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆