服务器重启后 Liferay Scheduler 不工作
Liferay Scheduler not working after server restart
我正在使用以下代码安排工作。
@Controller
@RequestMapping("VIEW")
public class MyController {
@RenderMapping
public String defaultView() {
try {
String cronText = "0 30 12 1/1 * ? *";
String description = "Message Scheduler Description";
String destinationName = DestinationNames.SCHEDULER_DISPATCH;
int exceptionsMaxSize = 0;
String portletId = "portletId";
Message message = new Message();
message.put(SchedulerEngine.MESSAGE_LISTENER_CLASS_NAME,SchedulerListener.class.getName());
message.put(SchedulerEngine.PORTLET_ID, portletId);
Trigger trigger = new CronTrigger(SchedulerListener.class.getName(), SchedulerListener.class.getName(), cronText);
SchedulerEngineHelperUtil.schedule(trigger,StorageType.PERSISTED, description, destinationName, message, exceptionsMaxSize);
}catch (SchedulerException e) {
e.printStackTrace();
}
return "view";
}
}
上述代码的问题在于调度程序仅在服务器会话之前有效。执行此方法后,即使在服务器重新启动后,我也想在上述时间触发 schedulerjob。有没有办法在 liferay 中实现这个?
这似乎是 Liferay 调度实施的问题。 Quartz 正确地存储和恢复了你的触发器和工作。但是 Liferay 并没有将您的 MessageListener
用作工作。相反,它会将您的 MessageListener
包裹在 MessageSenderJob
中,并注册您的 MessageListener
。
重启后MessageSenderJob
仍然会被触发,它会将你的消息发送到消息总线。但是,如果您在那之前没有注册 MessageListener
,他们将不会收到该消息。
解决方案:您必须在每次启动时注册您的MessageListener
。再次调用调度 SchedulerEngineHelperUtil.schedule
,或调用 MessageBusUtil.registerMessageListener
。请参阅我的问题 ,了解一些用于注册启动操作的选项。
如果您想动态创建触发器(由于 UI 中的某些操作),这里有一个示例:
@WebListener
public class SchedulerListener implements ServletContextListener, PortalLifecycle, MessageListener {
private SchedulerEventMessageListenerWrapper listenerWrapper;
public void contextInitialized(final ServletContextEvent sce) {
// Wait until the portal is ready
PortalLifecycleUtil.register(this, PortalLifecycle.METHOD_INIT);
}
public void portalInit() {
// Register our listener
listenerWrapper = new SchedulerEventMessageListenerWrapper();
listenerWrapper.setGroupName(getClass().getName());
listenerWrapper.setJobName(getClass().getName());
listenerWrapper.setMessageListener(this);
listenerWrapper.afterPropertiesSet();
MessageBusUtil.registerMessageListener(DestinationNames.SCHEDULER_DISPATCH, listenerWrapper);
}
public void contextDestroyed(final ServletContextEvent event) {
// Unregister
if (listenerWrapper != null) {
MessageBusUtil.unregisterMessageListener(DestinationNames.SCHEDULER_DISPATCH, listenerWrapper);
}
}
public void portalDestroy() {
// Ignore
}
public void receive(final Message message) {
// ... your job code here ...
}
}
如果您想要一个固定的触发器,您可以删除 listenerWrapper
并将问题中的 SchedulerEngineHelperUtil.schedule(...)
代码放入 portalInit()
。
如果您想知道,StorageType.PERSISTED
的意义是什么:它用于执行在服务器关闭时触发的触发器或在服务器关闭时刚刚启动的触发器。
我正在使用以下代码安排工作。
@Controller
@RequestMapping("VIEW")
public class MyController {
@RenderMapping
public String defaultView() {
try {
String cronText = "0 30 12 1/1 * ? *";
String description = "Message Scheduler Description";
String destinationName = DestinationNames.SCHEDULER_DISPATCH;
int exceptionsMaxSize = 0;
String portletId = "portletId";
Message message = new Message();
message.put(SchedulerEngine.MESSAGE_LISTENER_CLASS_NAME,SchedulerListener.class.getName());
message.put(SchedulerEngine.PORTLET_ID, portletId);
Trigger trigger = new CronTrigger(SchedulerListener.class.getName(), SchedulerListener.class.getName(), cronText);
SchedulerEngineHelperUtil.schedule(trigger,StorageType.PERSISTED, description, destinationName, message, exceptionsMaxSize);
}catch (SchedulerException e) {
e.printStackTrace();
}
return "view";
}
}
上述代码的问题在于调度程序仅在服务器会话之前有效。执行此方法后,即使在服务器重新启动后,我也想在上述时间触发 schedulerjob。有没有办法在 liferay 中实现这个?
这似乎是 Liferay 调度实施的问题。 Quartz 正确地存储和恢复了你的触发器和工作。但是 Liferay 并没有将您的 MessageListener
用作工作。相反,它会将您的 MessageListener
包裹在 MessageSenderJob
中,并注册您的 MessageListener
。
重启后MessageSenderJob
仍然会被触发,它会将你的消息发送到消息总线。但是,如果您在那之前没有注册 MessageListener
,他们将不会收到该消息。
解决方案:您必须在每次启动时注册您的MessageListener
。再次调用调度 SchedulerEngineHelperUtil.schedule
,或调用 MessageBusUtil.registerMessageListener
。请参阅我的问题
如果您想动态创建触发器(由于 UI 中的某些操作),这里有一个示例:
@WebListener
public class SchedulerListener implements ServletContextListener, PortalLifecycle, MessageListener {
private SchedulerEventMessageListenerWrapper listenerWrapper;
public void contextInitialized(final ServletContextEvent sce) {
// Wait until the portal is ready
PortalLifecycleUtil.register(this, PortalLifecycle.METHOD_INIT);
}
public void portalInit() {
// Register our listener
listenerWrapper = new SchedulerEventMessageListenerWrapper();
listenerWrapper.setGroupName(getClass().getName());
listenerWrapper.setJobName(getClass().getName());
listenerWrapper.setMessageListener(this);
listenerWrapper.afterPropertiesSet();
MessageBusUtil.registerMessageListener(DestinationNames.SCHEDULER_DISPATCH, listenerWrapper);
}
public void contextDestroyed(final ServletContextEvent event) {
// Unregister
if (listenerWrapper != null) {
MessageBusUtil.unregisterMessageListener(DestinationNames.SCHEDULER_DISPATCH, listenerWrapper);
}
}
public void portalDestroy() {
// Ignore
}
public void receive(final Message message) {
// ... your job code here ...
}
}
如果您想要一个固定的触发器,您可以删除 listenerWrapper
并将问题中的 SchedulerEngineHelperUtil.schedule(...)
代码放入 portalInit()
。
如果您想知道,StorageType.PERSISTED
的意义是什么:它用于执行在服务器关闭时触发的触发器或在服务器关闭时刚刚启动的触发器。