Skip to main content

Set up a MessageListener with Liferay

In a previous post, I briefly mentioned about Liferay's MessageListener interface. This interface is part of Liferay's Message Bus framework which can be used to send messages between Liferay and other web applications.

This interface can also be used to schedule jobs within Liferay. In order to use this interface and create a scheduled Job, you can


  1. Create a basic portlet: I usually stick to the GenericPortlet interface unless I have a really good reason to use some of the other interfaces specific to Liferay. 
  2. Once you created this interface, go ahead and create a class that implements the MessageListener interface. Following code snippet is an example of such an object.
     public class DemoListener implements MessageListener, ApplicationContextAware {  
          private ApplicationContext appContext;  
          private final static String SOME_ID = "someId";  
          private final Logger log = LoggerFactory.getLogger(DemoListener.class);  
          @Override  
          public void receive(Message message) throws MessageListenerException {  
               loadContext("classpath*:spring/bootstrapContext.xml");  
               long someId = 1L;  
               if (message.contains(SOME_ID)) {  
                    someId = (Long) message.get(SOME_ID);  
               }  
               DemoService service = appContext.getBean(DemoService.class);  
               try {  
                    log.debug("Demo Started: " + Calendar.getInstance().getTimeInMillis());  
                    service.executeDemo(demoId);  
               } catch (DemoException e) {  
                    throw new MessageListenerException(e.getMessage(), e);  
               }  
               log.debug("Demo Ended: " + Calendar.getInstance().getTimeInMillis());  
          }  
          /**  
           * @param configLocation  
           *      the location of the configuration  
           */  
          private void loadContext(final String configLocation) {  
               if (appContext == null) {  
                    try {  
                         appContext = new ClassPathXmlApplicationContext(configLocation);  
                    } catch (BeansException e) {  
                         log.error("unable to load spring context", e);  
                    }  
               }  
          }  
          @Override  
          public void setApplicationContext(ApplicationContext appContext) throws BeansException {  
               this.appContext = appContext;  
          }  
     }  

    As you can see from the above implementation, receive method is what is implemented. It relies on the frame work so that Message payload is provided. In this case, to show a value, I provided a basic long value as a payload called "SOME_ID". I then used the value of this id in the example and use my Spring beans to query the underlying database through a service interface. As you can see, I am using the ApplicationContextAware interface from the Spring framework to get access to my Spring Beans as I could not figure out a less invasive way to inject my beans into this Message Listener. If you know a less invasive way to achieve it, please share it with me. 
  3. Once this is done,  you need to create a scheduler-entry in your liferay-portlet.xml class to create a basic trigger for this MessageListener.
     <scheduler-entry>  
                    <scheduler-event-listener-class>com.demo.DemoListener</scheduler-event-listener-class>  
                    <trigger>  
                         <simple>  
                              <simple-trigger-value>  
                                   30  
                              </simple-trigger-value>  
                              <time-unit>minute</time-unit>  
                         </simple>  
                    </trigger>  
               </scheduler-entry>  
    

    In this scheduler-entry, I decided to use a simple trigger that its going to trigger this job every 30 minutes. The first time this will start is when the portlet is deployed to Liferay. 
Once the portlet is deployed, you can look at the logs to see if your MessageListener is getting executed. As an alternative, you can install a plug-in called Scheduled Job Manager from Liferay's Market place to view this job, stop, start and execute on - demand. 

Here is the link to this application. 

Comments