我正在使用以下代码安排工作。

@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。有关注册启动操作的一些选项,请参阅我的问题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的意义是什么:它用于执行在服务器关闭时已触发或在服务器关闭时已启动的触发器。

09-03 20:32