How to create scheduler in portlet

Sometimes you have a need to create a task that is being executed periodically. You can use scheduler (based on Quartz API ) that is integrated with Liferay. There are 3 steps to do this.

1. Write a class the implements the com.liferay.portal.job.Scheduler interface

2. Write a class that contains actual task that needs to be executed. This class must implements com.liferay.portal.job.IntervalJob interface

3. Register your scheduler in liferay-portlet-ext.xml ( if you use ext environment )

Now let’s go to the details.

1. Write a class that implements Scheduler interface.

package com.ext.portlet.onlineproject.job;

import com.liferay.portal.job.JobScheduler;
import org.quartz.SchedulerException;

public class Scheduler implements com.liferay.portal.job.Scheduler {

	public void schedule() throws SchedulerException {
	JobScheduler.schedule(new SyncDataJob());
	}
}

2. Write the class that contains actual task. On this example, our actual task would be only to write ‘THIS IS THE ACTUAL TASK!” to console. This task would be executed every minute.

package com.ext.portlet.onlineproject.job;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import com.liferay.portal.job.IntervalJob;
import com.liferay.util.Time; 

public class SyncDataJob implements IntervalJob{
	public SyncDataJob() {
		_interval = Time.MINUTE;
	}
	public long getInterval() {
		return _interval;
	}
	public void execute(JobExecutionContext context)
		throws JobExecutionException {
		try {
			System.out.println("THIS IS THE ACTUAL TASK!");
		}
		catch (Exception e) {
			_log.error(e);
		}
	}
	private static Log _log = LogFactory.getLog(SyncDataJob.class);
	private long _interval;
}


If you want to change the interval, you can just change this line :

public SyncDataJob() {
_interval = Time.MINUTE;
}

Change Time.MINUTE to Time.HOUR or Time.DAY.

3. Register in liferay-portlet-ext.xml.

<portlet>
<portlet-name>Online_Project</portlet-name>
<struts-path>ext/onlineproject</struts-path>
<scheduler-class>com.ext.portlet.onlineproject.job.Scheduler</scheduler-class>
<use-default-template>false</use-default-template>
</portlet>

Done. ( This article tested on Liferay 4.3.3 )

9 comments so far

  1. Mickaël on

    Hi,

    I read your post, but, i have some problem to implement Scheduler on my portlet.

    Could you help me ?

    http://www.liferay.com/web/guest/community/forums/-/message_boards/message/935043

    Thank’s.

    Mickaël.

  2. portaldevelopment on

    Hi Mickaël,
    Have you registered the scheduler on liferay-portlet-ext.xml ( see step no. 3 ) ? And please check portal-ext.properties in case one of your team member disable the scheduler.
    scheduler.enabled=true

  3. Leonardo on

    Hi Mick!

    I need to create a process that past a while updating the information of a portlet connecting to a database! I thought for this use quartz!
    I wanted to know if it is also possible that starting a process that attends an incoming message and update the info into a portlet.

    How can I do that?

    Thanks .-

  4. Neil on

    Hi –

    I’ve done as you suggested for 5.1.2, and had to make some modifications to implement the latest interface refactoring.

    For now, I’m just trying to get liferay to acknowledge, thru quartz, the existence of my portlet, and I’m close. The error I get is:

    04:26:42,781 WARN [PortletLocalServiceImpl:283] Portlet with the name Importer is described in liferay-portlet.xml but does not have a matching entry in portlet.xml

    I tried updated portlet-ext.xml, but it just threw more NPE’s. It could be that I didn’t have the correct tags and entries?

    Thoughts and suggestions are appreciated.

    -Neil

  5. portaldevelopment on

    Hi Neil,

    I think you should register your scheduler in liferay-portlet-ext.xml. And don’t forget to use the same portlet name for your portlet on liferay-portlet-ext.xml and on portlet-ext.xml. Please check the content of liferay-portlet-ext.xml on my writing, and this is the coresponding entry on portlet-ext.xml :

    	<portlet>
    		<portlet-name>Online_Project</portlet-name>
    		<display-name>Online Project</display-name>
    		<portlet-class>com.ext.portlet.onlineproject.OnlineProjectPortlet</portlet-class>
    		<init-param>
    			<name>view-action</name>
    			<value>/ext/onlineproject/view</value>
    		</init-param>
    		<expiration-cache>0</expiration-cache>
    		<supports>
    			<mime-type>text/html</mime-type>
    		</supports>
    		<resource-bundle>com.liferay.portlet.StrutsResourceBundle</resource-bundle>
    		<security-role-ref>
    			<role-name>power-user</role-name>
    		</security-role-ref>
    		<security-role-ref>
    			<role-name>user</role-name>
    		</security-role-ref>
    	</portlet>	
    
  6. Neil on

    Thanks, much – it worked!

    One interesting refactoring to your implementation for 5.1.2: the schedule method needs to invoke the JobSchedulerUtil to get an instance of the jobScheduler, instead of invoking the static method.

    public void schedule() {

    JobScheduler jobScheduler = JobSchedulerUtil.getJobScheduler();

    jobScheduler.schedule(new SyncDataJob());
    }

    I appreciate the timely help.

    -Neil

  7. Ayaz on

    Hello,

    Thanks for the information on Scheduler in Liferay.

    I tried the same & I am facing an issue.

    I am using EXT environment (Liferay-5.2.2). I have a portlet by name ‘Registration’ and I followed the steps described below to test the same.

    This is the entry I gave in liferay-portal-ext.xml

    Registration
    ext/registration
    com.ext.portlet.registration.job.Scheduler

    false

    And did everything described above but when I start my server I get the following ClassCastException

    Starting Liferay Portal Standard Edition 5.2.2 (Augustine / Build 5202 / February 20, 2009)
    16:49:06,377 ERROR [MainServlet:336] java.lang.ClassCastException: com.ext.portlet.registration.job.Scheduler
    java.lang.ClassCastException: com.ext.portlet.registration.job.Scheduler
    at com.liferay.portal.servlet.MainServlet.init(MainServlet.java:328)
    at javax.servlet.GenericServlet.init(GenericServlet.java:212)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1172)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:992)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4058)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4371)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:627)
    at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:553)
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:488)
    at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1149)
    at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
    at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
    at org.apache.catalina.core.StandardService.start(StandardService.java:516)
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)

  8. Luke on

    Schedule works fine, but I want it to fire on a date/time, not on an interval. How do I do that?

  9. Nagendra Kumar Busam on

    I have written a simple scheduler by following the blog @

    Is there any way i can change the scheduler job interval time afer server startup.

    Through configuration section in my custom portlet i tried to change the schedule job interval BUT i was not able to see reflected time in my scheduled job execution


Leave a reply