【问题标题】:Liferay Scheduler not working after server restartLiferay 调度程序在服务器重启后不工作
【发布时间】:2015-12-04 11:39:24
【问题描述】:

我正在使用下面的代码安排作业。

@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 中实现这一点?

【问题讨论】:

  • 当您使用 StorageType.PERSISTED 时,我猜,该作业已保存在您的数据库中。您能否检查一下您的 QUARTZ_... 表是否存在并包含该作业?
  • @TobiasLiefke 是的.. 重新启动服务器后,石英表仍然包含该作业。但仍然没有触发工作
  • Liferay 论坛上的这个答案建议创建一个自定义目的地。你能试一下吗? liferay.com/community/forums/-/message_boards/message/…
  • @TomasPinos 在这种情况下,我不知道在哪里可以找到 init() method 以便将自定义目标添加到 MessageBusUtil
  • 他们的意思是com.liferay.util.bridges.mvc.MVCPortlet#init。这就是 Liferay MVC 框架。在您的情况下,它可以是任何“init”方法。就像使用javax.annotation.PostConstruct 注释的方法,甚至是控制器的渲染方法。

标签: java liferay scheduling


【解决方案1】:

这似乎是 Liferay 调度实现的一个问题。 Quartz 正在正确存储和恢复您的触发器和作业。但是 Liferay 并没有使用您的MessageListener 作为工作。相反,它会将您的MessageListener 包装在MessageSenderJob 中,并注册您的MessageListener

MessageSenderJob 重启后仍会被触发,并将你的消息发送到消息总线。但是,如果您在那之前没有注册您的MessageListener,他们将不会收到该消息。

解决方案:您必须在每次启动时注册您的MessageListener。再次调用调度SchedulerEngineHelperUtil.schedule,或调用MessageBusUtil.registerMessageListener。有关注册启动操作的一些选项,请参阅我的问题 here

如果您想动态创建触发器(由于 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 的意义是什么:它用于执行在服务器关闭时触发的触发器,或者在服务器关闭时刚刚启动的触发器。

【讨论】:

  • 我应该在 portlet 或 hook 中添加这个 Listener 类吗?添加后,如果我部署插件,它会自动执行这个类代码吗?
  • Portlet 和 Hook 正在工作。重要的是您在message.put(SchedulerEngine.PORTLET_ID, "...") 中输入的内容。这必须是完全限定的 portlet id(包括 ..._WAR_...)或插件的 servlet 上下文名称(请参阅 QuartzSchedulerEngine.registerMessageListeners)。对于钩子,后者适用。我不明白您的第二个问题 - 您需要使用我在答案中链接的选项之一来自动执行某些操作。您想从 UI 动态打开/关闭调度程序,还是想要一个固定的触发器和计划的操作?
  • 嗯..这行得通:-) PortalLifecycleUtil.register(this, PortalLifecycle.METHOD_INIT); 做什么?这里有必要吗?
  • 它确保在 Liferay 启动并运行之前不会调用您的侦听器。否则可能会发生一些您注册所需的东西仍然丢失的情况。我不知道MessageBusUtil.registerMessageListener 是否真的需要一个正在运行的 Liferay,但SchedulerEngineHelperUtil.schedule 肯定需要一个。
猜你喜欢
  • 1970-01-01
  • 2020-11-27
  • 1970-01-01
  • 2012-04-21
  • 2021-11-15
  • 2017-10-23
  • 2011-05-17
  • 1970-01-01
  • 2013-05-15
相关资源
最近更新 更多