掲示板

Implement Scheduler

thumbnail
13年前 に Marcus Souza によって更新されました。

Implement Scheduler

Junior Member 投稿: 58 参加年月日: 09/03/31 最新の投稿
Hi,

I am following the Article to implement a Portlet X to run every sunday. I am getting a error "Unable to load the Scheduler class with the Portal class loader or the current context class loader" after i add following code in the Portal-ext.properties

##
## 	Scheduling
##
		
scheduler.enabled=true		
scheduler.classes=Scheduler.class
		


could someone point me in the right way to implement a class X with the Quartz Scheduler?
thanks in advance,
Marcus Souza
thumbnail
13年前 に Marcus Souza によって更新されました。

RE: Implement Scheduler

Junior Member 投稿: 58 参加年月日: 09/03/31 最新の投稿
Both Code i am using:


import com.liferay.portal.kernel.job.IntervalJob; 

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

	    public void schedule() {
		        this.schedule(new SyncDataJob());
		    }
		   
		    public void schedule(IntervalJob arg0) {
		        // TODO Auto-generated method stub
		    }

			@Override
			public void unschedule() {
				// TODO Auto-generated method stub
				
			}
		
		
		}


and



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

public class SyncDataJob implements com.liferay.portal.kernel.job.IntervalJob{
	public SyncDataJob() {
		_interval = Time.MINUTE;
	}
	public long getInterval() {
		return _interval;
	}
	public void execute(JobExecutionContext context)
		throws JobExecutionException {
		try {
			ImportUser test = new ImportUser();
			test.doImport();
		}
		catch (Exception e) {
			_log.error(e);
		}
	}
	private static Log _log = LogFactory.getLog(SyncDataJob.class);
	private long _interval;
	@Override
	public void execute(com.liferay.portal.kernel.job.JobExecutionContext arg0)
			throws com.liferay.portal.kernel.job.JobExecutionException {
		// TODO Auto-generated method stub
		
	}
}

thumbnail
13年前 に Shuyang Zhou によって更新されました。

RE: Implement Scheduler

New Member 投稿: 9 参加年月日: 07/12/07 最新の投稿
You should use the new scheduler mechanism. It is introduced in LPS-4752. It works on top of MessageBus, so you need to make your job as a MessageListener and configure it in liferay-portlet.xml.

You can refer to liferay-portlet-app_6_0_0.dtd scheduler-entry, and in liferay-portlet.xml there are several examples you can follow.
thumbnail
13年前 に Marcus Souza によって更新されました。

RE: Implement Scheduler

Junior Member 投稿: 58 参加年月日: 09/03/31 最新の投稿
Shuyang Zhou:
You should use the new scheduler mechanism. It is introduced in LPS-4752. It works on top of MessageBus, so you need to make your job as a MessageListener and configure it in liferay-portlet.xml.

You can refer to liferay-portlet-app_6_0_0.dtd scheduler-entry, and in liferay-portlet.xml there are several examples you can follow.


thankyou for the quick Answer! I will take a look at it.

Marcus Souza
13年前 に Anna Steiglitz によって更新されました。

RE: Implement Scheduler

New Member 投稿: 2 参加年月日: 10/07/07 最新の投稿
Shuyang Zhou:
You should use the new scheduler mechanism. It is introduced in LPS-4752. It works on top of MessageBus, so you need to make your job as a MessageListener and configure it in liferay-portlet.xml.

You can refer to liferay-portlet-app_6_0_0.dtd scheduler-entry, and in liferay-portlet.xml there are several examples you can follow.


I have the same Problem. I have my own Portlet and want it to start every sunday. could you show please a step by step, how to achieve this.

Anna
thumbnail
13年前 に Shuyang Zhou によって更新されました。

RE: Implement Scheduler

New Member 投稿: 9 参加年月日: 07/12/07 最新の投稿
For a complete example, go to plugin-trunk(svn://svn.liferay.com/repos/public/plugins/trunk
), check out test-misc-portlet. This is a very simple portlet, and it has a demo scheduler listener.

So basicly, in liferay-portlet.xml, add this:
<portlet>
		<portlet-name>1</portlet-name>
		<icon>/icon.png</icon>
		<scheduler-entry>
			<scheduler-event-listener-class>com.liferay.testmisc.messaging.TestSchedulerMessageListener</scheduler-event-listener-class>
			<trigger>
				<simple>
					<simple-trigger-value>1</simple-trigger-value>
					<time-unit>hour</time-unit>
				</simple>
			</trigger>
		</scheduler-entry>
		<friendly-url-mapper-class>com.liferay.portal.kernel.portlet.DefaultFriendlyURLMapper</friendly-url-mapper-class>
		<friendly-url-mapping>test_misc</friendly-url-mapping>
		<friendly-url-routes>com/liferay/testmisc/portlet/test-friendly-url-routes.xml</friendly-url-routes>
	</portlet>


This means trigger TestSchedulerMessageListener every hour. You should add the scheduler logic into the MessageListener. Refer to the dtd for more trigger configuration info.
13年前 に Anna Steiglitz によって更新されました。

RE: Implement Scheduler

New Member 投稿: 2 参加年月日: 10/07/07 最新の投稿
Shuyang Zhou:
For a complete example, go to plugin-trunk(svn://svn.liferay.com/repos/public/plugins/trunk
), check out test-misc-portlet. This is a very simple portlet, and it has a demo scheduler listener.

So basicly, in liferay-portlet.xml, add this:
<portlet>
		<portlet-name>1</portlet-name>
		<icon>/icon.png</icon>
		<scheduler-entry>
			<scheduler-event-listener-class>com.liferay.testmisc.messaging.TestSchedulerMessageListener</scheduler-event-listener-class>
			<trigger>
				<simple>
					<simple-trigger-value>1</simple-trigger-value>
					<time-unit>hour</time-unit>
				</simple>
			</trigger>
		</scheduler-entry>
		<friendly-url-mapper-class>com.liferay.portal.kernel.portlet.DefaultFriendlyURLMapper</friendly-url-mapper-class>
		<friendly-url-mapping>test_misc</friendly-url-mapping>
		<friendly-url-routes>com/liferay/testmisc/portlet/test-friendly-url-routes.xml</friendly-url-routes>
	</portlet>


This means trigger TestSchedulerMessageListener every hour. You should add the scheduler logic into the MessageListener. Refer to the dtd for more trigger configuration info.


I tried to deploy the Portlet test-misc-portlet and got the error

08:41:55,059 INFO [PortletHotDeployListener:227] Registering portlets for test-
misc-portlet
08:41:55,512 ERROR [PortletLocalServiceImpl:542] com.liferay.portal.kernel.xml.D
ocumentException: Error on line 8 of document : Element type "scheduler-entry"
must be declared. Nested exception: Element type "scheduler-entry" must be decla
red.
com.liferay.portal.kernel.xml.DocumentException: Error on line 8 of document :
Element type "scheduler-entry" must be declared. Nested exception: Element type
"scheduler-entry" must be declared.
at com.liferay.portal.xml.SAXReaderImpl.read(SAXReaderImpl.java:377)
at com.liferay.portal.xml.SAXReaderImpl.read(SAXReaderImpl.java:388)
at com.liferay.portal.kernel.xml.SAXReaderUtil.read(SAXReaderUtil.java:1
56)


I am using LR 5.2.3 with Tomcat 6.0
thumbnail
13年前 に Shuyang Zhou によって更新されました。

RE: Implement Scheduler

New Member 投稿: 9 参加年月日: 07/12/07 最新の投稿
5.2 does not have this feature. You should either upgrade or go back to use the old scheduler support. You can find example for old scheduler in 5.2's plugins repository
thumbnail
13年前 に kitie vbr によって更新されました。

RE: Implement Scheduler

Junior Member 投稿: 39 参加年月日: 10/08/05 最新の投稿
Please I need help!!

I have to make a scheduler in version liferay 5.2.3

where can I find examples for scheduler for this version??

Some url for examples??

Thanks a lot
thumbnail
13年前 に Marcus Souza によって更新されました。

RE: Implement Scheduler

Junior Member 投稿: 58 参加年月日: 09/03/31 最新の投稿
Shuyang Zhou:
You should use the new scheduler mechanism. It is introduced in LPS-4752. It works on top of MessageBus, so you need to make your job as a MessageListener and configure it in liferay-portlet.xml.

You can refer to liferay-portlet-app_6_0_0.dtd scheduler-entry, and in liferay-portlet.xml there are several examples you can follow.


I Finally was able to test it and it works fine! If i want to Schedule a task like

System.out.println("ok"); every 30 sec is not a Problem,

but if I do a object of my class X and try to use it, I become a ERROR

14:29:04,918 ERROR [TestPortlet:486] PermissionChecker not initialized
com.liferay.portal.security.auth.PrincipalException: PermissionChecker not initi
alized
at com.liferay.portal.service.base.PrincipalBean.getPermissionChecker(Pr
incipalBean.java:77)
at com.liferay.portal.service.impl.UserServiceImpl.getUserByEmailAddress
(UserServiceImpl.java:289)


public class TestIntervalJob implements IntervalJob {
...
...
		if (_log.isInfoEnabled()) {
			_log.info("Execute");
			[b]TestPortlet as = new TestPortlet();[/b]
			try {
				[b]as.doImport();[/b]
			} catch (PortletException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}


I am anyway a step further, thanks to you

Marcus Souza
thumbnail
13年前 に Marcus Souza によって更新されました。

RE: Implement Scheduler

Junior Member 投稿: 58 参加年月日: 09/03/31 最新の投稿
Its done .... that Post helped me with the ERROR, thanks
Marcus Souza
thumbnail
13年前 に Rob van Maris によって更新されました。

RE: Implement Scheduler

New Member 投稿: 5 参加年月日: 10/06/16 最新の投稿
Shuyang Zhou:
You should use the new scheduler mechanism. It is introduced in LPS-4752. It works on top of MessageBus, so you need to make your job as a MessageListener and configure it in liferay-portlet.xml.

You can refer to liferay-portlet-app_6_0_0.dtd scheduler-entry, and in liferay-portlet.xml there are several examples you can follow.


It would help if the DTD at that URL is updated. As it is it seems to be outdated and does not declare a scheduler-entry element.
thumbnail
13年前 に Shuyang Zhou によって更新されました。

RE: Implement Scheduler

New Member 投稿: 9 参加年月日: 07/12/07 最新の投稿
Rob van Maris:
Shuyang Zhou:
You should use the new scheduler mechanism. It is introduced in LPS-4752. It works on top of MessageBus, so you need to make your job as a MessageListener and configure it in liferay-portlet.xml.

You can refer to liferay-portlet-app_6_0_0.dtd scheduler-entry, and in liferay-portlet.xml there are several examples you can follow.


It would help if the DTD at that URL is updated. As it is it seems to be outdated and does not declare a scheduler-entry element.


Our site maintainer will update it asap, for now you can refer the dtd from source code. They are update to date.
thumbnail
13年前 に Rob van Maris によって更新されました。

RE: Implement Scheduler

New Member 投稿: 5 参加年月日: 10/06/16 最新の投稿
Shuyang Zhou:
You should use the new scheduler mechanism. It is introduced in LPS-4752. It works on top of MessageBus, so you need to make your job as a MessageListener and configure it in liferay-portlet.xml.


Can you point me to more comprehensive documentation on the new scheduler mechanism?

I don't get the rationale for this design. Why do jobs need to be configured as part of a portlet (a hook seems more appropriate to me). And why reuse the MessageListener interface for this (the message does not seem to carry any information that is relevant to the job)?

I may be missing the point. Please explain.
thumbnail
13年前 に Shuyang Zhou によって更新されました。

RE: Implement Scheduler

New Member 投稿: 9 参加年月日: 07/12/07 最新の投稿
Rob van Maris:
Shuyang Zhou:
You should use the new scheduler mechanism. It is introduced in LPS-4752. It works on top of MessageBus, so you need to make your job as a MessageListener and configure it in liferay-portlet.xml.


Can you point me to more comprehensive documentation on the new scheduler mechanism?

I don't get the rationale for this design. Why do jobs need to be configured as part of a portlet (a hook seems more appropriate to me). And why reuse the MessageListener interface for this (the message does not seem to carry any information that is relevant to the job)?

I may be missing the point. Please explain.


Sorry, we don't have document for scheduler, but our training covers this topic.
It has to be tied to plugins(portlet, hook, web, etc), since the actual schedule logic may inside the plugin, you won't able to invoke it outside, like from another hook, unless you are doing some compplex classloader switching.

The main reason of using MessageBus for this new scheduler is avoiding classloading issues. And another benefit is, since MB is cluster aware(by using clusterlink bridging), your scheduler can transparently be clustered.
thumbnail
13年前 に Rob van Maris によって更新されました。

RE: Implement Scheduler

New Member 投稿: 5 参加年月日: 10/06/16 最新の投稿
Shuyang Zhou:
Sorry, we don't have document for scheduler, but our training covers this topic.
It has to be tied to plugins(portlet, hook, web, etc), since the actual schedule logic may inside the plugin, you won't able to invoke it outside, like from another hook, unless you are doing some compplex classloader switching.


Hi Shuyang Zhou,

So how can I use the scheduler inside a hook when I need to configure it in a portlet?
thumbnail
13年前 に Shuyang Zhou によって更新されました。

RE: Implement Scheduler

New Member 投稿: 9 参加年月日: 07/12/07 最新の投稿
Rob van Maris:
Shuyang Zhou:
Sorry, we don't have document for scheduler, but our training covers this topic.
It has to be tied to plugins(portlet, hook, web, etc), since the actual schedule logic may inside the plugin, you won't able to invoke it outside, like from another hook, unless you are doing some compplex classloader switching.


Hi Shuyang Zhou,

So how can I use the scheduler inside a hook when I need to configure it in a portlet?


You can not do that easily, it is not supposed to be used that way. The scheduler definition and configuration should be in same plugin. Once you schedule a job, you can not re-configure it, unless you cancel the previous one first, then re-schedule it again with new configuration. And this is not supported by standard xml declaration, you have to programly do it. If you also need to schedule a job from a different plugin, you have to switch the classloader yourself. I can not see why you need to do this, please re-consider your design, you may on the wrong way.
thumbnail
13年前 に Rob van Maris によって更新されました。

RE: Implement Scheduler

New Member 投稿: 5 参加年月日: 10/06/16 最新の投稿
Hi Shuyang Zhou,

Let me restate my question - it looks like you understood it differently from what I meant.

So my question is: how can I use the scheduler inside a hook?
The context of this question is that Liferay allows me to configure a scheduler inside a portlet, but not inside a hook plugin.
thumbnail
13年前 に Shuyang Zhou によって更新されました。

RE: Implement Scheduler

New Member 投稿: 9 参加年月日: 07/12/07 最新の投稿
Rob van Maris:
Hi Shuyang Zhou,

Let me restate my question - it looks like you understood it differently from what I meant.

So my question is: how can I use the scheduler inside a hook?
The context of this question is that Liferay allows me to configure a scheduler inside a portlet, but not inside a hook plugin.


Ok, i see your question now. Sorry for misunderstood it.

In hook, you need to use SchedulerEngineUtil directly, the api is very simple, so you should able to figure out how to use it.

I thinks it will make more sense for adding xml declaration of scheduler in hook too, we probably will add it in future.
thumbnail
13年前 に jelmer kuperus によって更新されました。

RE: Implement Scheduler

Liferay Legend 投稿: 1191 参加年月日: 10/03/10 最新の投稿
This is actually not that trivial

We tried starting the scheduler in a startup action and stopping in in a shutdown action.
But the shutdown action is never called. I created an issue for this

http://issues.liferay.com/browse/LPS-11613

Then we tried scheduling and unscheduling the job from a ServletContextListener however this fails when you restart the server, because it requires the messagebus and it is not available at that time.

com.liferay.portal.events.StartupAction starts it but our hook war is loaded before the ROOT war is loaded

So for now we decided on starting the scheduler in the startup action and shutting it down in a ServletContextListener.

Not very elegant for sure. The only other option i see is subclassing the HookHotDeployListener and adding the functionality to that

Can you suggest a cleaner solution ?
thumbnail
12年前 に amit doshi によって更新されました。

RE: Implement Scheduler

Liferay Master 投稿: 550 参加年月日: 10/12/29 最新の投稿
Hi Shuyang Zhou,

We have to change the existing scheduler of LDAP.

By default in portal.properties they are providing properties ldap.import.interval.

I found that there is an entry in the liferay-portlet.xml

<portlet>
            <portlet-name>9</portlet-name>
            .
            .
            <scheduler-entry>
                  <scheduler-event-listener-class>com.liferay.portlet.admin.messaging.LDAPImportMessageListener</scheduler-event-listener-class>
                  <trigger>
                        <simple>
                              <property-key>ldap.import.interval</property-key>
                              <time-unit>minute</time-unit>
                        </simple>
                  </trigger>
            </scheduler-entry>
            .
            .
      </portlet>


So, I tried to override that entry in the liferay-portlet-ext.xml in EXT Portlet with Cron Triggers.

<portlet>
            <portlet-name>9</portlet-name>
            .
            .
            <scheduler-entry>
                  <scheduler-event-listener-class>com.liferay.portlet.admin.messaging.LDAPImportMessageListener</scheduler-event-listener-class>
                  <trigger>
                        <cron>
                              <cron-trigger-value>0 10 1 ? * *</cron-trigger-value>
                        </cron>
                  </trigger>
            </scheduler-entry>
            .
            .
      </portlet>


The cron Trigger value( 0 10 1 ? * *) means that everday the import should start at 1:10:00 AM.

I checked the database in that it shows me the Entry in quartz_cron_triggers table, not in quartz_simple_triggers.

The problem is that above Cron Expression is working fine but Import is getting started two times (so at 1:10:00 AM two times LDAP import is getting started) instead of one time.

After Debugging code I found that two triggers are getting fired. One is Simple Trigger and other is Cron Trigger.

In one of the blog found that what you have mentioned in liferay-portlet-ext.xml will not override it will extend.
And if it is so then how can I override the entry of liferay-portlet.xml (SIMPLE Trigger to CRON Trigger).

Any help will be great.

Thanks in advance.
thumbnail
12年前 に Shuyang Zhou によって更新されました。

RE: Implement Scheduler

New Member 投稿: 9 参加年月日: 07/12/07 最新の投稿
So far, there is no clean way to swap a scheduler job.
But there are two ways to work around:
1) Comment the <scheduler-entry> tag in portal liferay-portlet.xml, completely switch the scheduler lanuching to your own ext plugin.
2) In your ext plugin, before launching your scheduler job, call SchedulerEngineUtil to explicitly remove default job first, then your scheduler job will be the only one.

1) is easier, but requires to modify portal side code, 2) requires one more line code, but is cleaner.
thumbnail
12年前 に Rendi Januar によって更新されました。

RE: Implement Scheduler

New Member 投稿: 13 参加年月日: 10/12/06 最新の投稿
Hi Shuyang,

I would like to ask you about the scheduler, Can we implement 2 scheduler at the same time?
For example, I want first scheduler to do method A every 10 minutes and the second scheduler to do method B every 1 hour.
I already trying to add 2 scheduler entry taglib on liferay-portlet.xml, but it effect with no scheduler worked.

thanks,
Rendi
thumbnail
12年前 に Shuyang Zhou によって更新されました。

RE: Implement Scheduler

New Member 投稿: 9 参加年月日: 07/12/07 最新の投稿
Of course you can do that. In fact, you can as many as <scheduler-entry> for one portlet. See the portal liferay-portlet.xml for example, portlet 9 has two enties defined.
thumbnail
12年前 に Rendi Januar によって更新されました。

RE: Implement Scheduler

New Member 投稿: 13 参加年月日: 10/12/06 最新の投稿
Shuyang Zhou:
Of course you can do that. In fact, you can as many as <scheduler-entry> for one portlet. See the portal liferay-portlet.xml for example, portlet 9 has two enties defined.


Okay I will try it, thanks a lot Zhou.
thumbnail
12年前 に amit doshi によって更新されました。

RE: Implement Scheduler

Liferay Master 投稿: 550 参加年月日: 10/12/29 最新の投稿
Thanks Shuyang Zhou for the reply...

If I am implementing the first approach then it is working fine.

1) Comment the <scheduler-entry> tag in portal liferay-portlet.xml, completely switch the scheduler lanuching to your own ext plugin.

But the thing is that customer is not satisfied with it, removing the entry from the liferay-portlet.xml directly from the portal source.

They are asking for systematic way..

If I am overriding the liferay-portlet.xml with liferay-portlet-ext.xml and removing Particular LDAP Listener entry in liferay-portlet-ext.xml in EXT then also it is not working as aspecation.

why changing liferay-portlet-ext.xml is not working appropriately ?

And I tried other approach of yours

2) In your ext plugin, before launching your scheduler job, call SchedulerEngineUtil to explicitly remove default job first, then your scheduler job will be the only one.

On that I faced one problem..... Two times LDAP Import is Starting.

And one more thing I like to add is that Even I undeployed full EXT after applying 2nd approach. And trying to run normal functionality of LDAP as liferay is providing .. It was working in different manner.
The Problem i faced is that
1) Even the ldap.import.on.startup=false then also the import is getting started on Server Startup.
2) and if I keep ldap.import.on.startup=true then on Server Startup two times LDAP import is getting started.

Last 3 days I am trying to Identifying the issue what is happening behind the scene so that LDAP is starting two times... Not getting any clue.

I also tried with Fresh Liferay source... In the beginning it is working fine as normal LDAP Behaviour. But when I do some listener related changes in EXT and then deploying and undeploying it starting behaing abnormally(means runs two times LDAP Import ).

I am stuck on to this any help will be great.

Thanks in advance.
Regards,
Amit Doshi
11年前 に Alan Besco によって更新されました。

RE: Implement Scheduler

New Member 投稿: 1 参加年月日: 13/02/25 最新の投稿
that's strange, i tried your cod, with <cron-trigger-value>0 13,18 * * * ? </cron-trigger-value> and i recieve my notification (it's what the cron job trigger) every hour at h:13 min and h:18 min then i tried, <cron-trigger-value>0 0 13,18 * * ? </cron-trigger-value> and now, like wished, the notification are sent every day at 13:00 and 18:00.

Any idea why my first * represent the second ?

thanks