有一个带有“crontab 语法"的 EJB 调度任务; [英] Have an EJB schedule tasks with "crontab syntax"
问题描述
我正在尝试找出解决以下问题的可能性.
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)
- ScheduleExpression
- 动态创建
- 只有一个@Timeout 支持所有的 ScheduleExpression
- 超时方法必须以
javax.ejb.Timer
为参数 - 可以传递参数
- 调用方将参数包装在 TimerConfig.setInfo(Serializable) 对象
- @Timeout 方法通过 定时器访问它们.getInfo()
- 可以被调用者或者@Timeout方法取消
另请注意,拦截器 @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
- The caller wraps arguments in a TimerConfig.setInfo(Serializable) object
- The @Timeout method accesses them via Timer.getInfo()
- 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屋!