java – Liferay Scheduler在服务器重启后无法正常工作

我正在使用下面的代码安排工作.

@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";
    }
}

上述代码的问题在于调度程序仅在服务器会话之前有效.一旦执行了这个方法,我想在服务器重启后在上述时间触发调度程序.有没有办法在liferay中实现这个?

最佳答案 这似乎是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的重点是什么:它用于执行在服务器关闭时或在服务器停机时刚刚启动时触发的触发器.

点赞