Liferay is providing scheduler API to create schedule job in Liferay Portal Applications. Liferay internally uses the Quartz scheduler engine. Liferay also uses the Message Bus implementation with scheduler API.
Liferay-ce-portal-7.4.1-ga2
|
Below Article will provide more details on Liferay
Scheduler
http://www.liferaysavvy.com/2021/07/working-with-liferay-scheduler.html
Liferay API is using Message Bus for every scheduler job
and following article will provide more detail about Liferay Message Bus.
http://www.liferaysavvy.com/2021/07/working-with-liferay-message-bus.html
http://www.liferaysavvy.com/2021/07/liferay-message-bus-implementation.html
Following are the steps to implement Dynamic schedule
jobs in Liferay
- Create Message Bus Destination
- Register Listener with Destination
- Create Scheduler job and tag to Destination
Create Message Bus Destination
Create destination have following steps in OSGi module
- Create Destination Configuration
- Create Destination
- Manage the Destination Object
Create Destination Configuration
Message Bus API is providing DestinationConfiguration
class to create destination configuration. We can create different types of
destination as it specified as below.
Parallel Destination Configuration
DestinationConfiguration destinationConfiguration = new DestinationConfiguration( DestinationConfiguration.DESTINATION_TYPE_PARALLEL,LiferayMessageBusPortletKeys.DESTINATION_PARALLEL); |
Serial Destination Configuration
DestinationConfiguration destinationConfiguration = new DestinationConfiguration( DestinationConfiguration.DESTINATION_TYPE_SERIAL,LiferayMessageBusPortletKeys.DESTINATION_SERIAL); |
Synchronous Destination Configuration
DestinationConfiguration destinationConfiguration = new DestinationConfiguration( DestinationConfiguration.DESTINATION_TYPE_SYNCHRONOUS,LiferayMessageBusPortletKeys.DESTINATION_SYNCHRONOUS); |
Create Destination
DestinationFactory
will create destination based on configuration
Destination destination = _destinationFactory.createDestination( destinationConfiguration); |
Register Destination as OSGi Service
ServiceRegistration<Destination>
is used to register destination as OSGi service.
_destinationServiceRegistration = _bundleContext.registerService( Destination.class, destination, destinationProperties); _log.info("Destination is registred with Service Regisration
.."); |
Manage the Destination Object
We have to manage destination object so that it can
deregister when bundle is deactivated.
Dictionary<String, Object> destinationProperties = HashMapDictionaryBuilder.<String,
Object>put( "destination.name", destination.getName()).build(); |
Destroy Destination
@Deactivate protected void deactivate() { if (_destinationServiceRegistration != null) { Destination
destination = _bundleContext.getService( _destinationServiceRegistration.getReference()); _destinationServiceRegistration.unregister(); destination.destroy(); } |
Setting Thread Pool for destination
destinationConfiguration.setMaximumQueueSize(_MAXIMUM_QUEUE_SIZE); destinationConfiguration.setWorkersCoreSize(_CORE_SIZE); destinationConfiguration.setWorkersMaxSize(_MAX_SIZE); |
Rejection Handler to Handle Failed Messages
RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.CallerRunsPolicy()
{ @Override public void rejectedExecution( Runnable
runnable,
ThreadPoolExecutor threadPoolExecutor) { if (_log.isWarnEnabled()) { _log.warn("The current thread will handle the request " + "because the
rules engine's task queue is at " +"its maximum capacity"); } super.rejectedExecution(runnable, threadPoolExecutor); } }; destinationConfiguration.setRejectedExecutionHandler(rejectedExecutionHandler); |
Register Listener with Destination
Listener should implement MessageListener
interface. We have to implement receive(..) method and there we implement our
business logic. Listeners are registered with destination to received messages
from senders.
There are different ways to register listener below is
the one of the ways.
Automatic Registration
Create MessageListener component and pass destination
name as property so that it will be register with destination automatically
when component is create.
@Component ( immediate = true, property = {"destination.name=liferaysavvy/synchronous-destination"}, service = MessageListener.class ) public class AutomaticRegisteredSynchronousMessageListener implements MessageListener { @Override public void receive(Message
message) { try { _log.info("Message::"+message); } catch (Exception e) { e.printStackTrace(); } } private static final Log _log = LogFactoryUtil.getLog( AutomaticRegisteredSynchronousMessageListener.class); } |
Create Scheduler job and tag to Destination
SchedulerEngineHelperUtil is
class will provide methods to create schedule Jobs. We can also use “SchedulerEngineHelper”
OSGi reference to create same schedule jobs.
Following are API method to schedule Job in Liferay
public static void schedule(
Trigger trigger, StorageType storageType, String description,
String destinationName, Message message, int exceptionsMaxSize)
throws SchedulerException
public
static void schedule(
Trigger trigger, StorageType storageType, String description,
String destinationName, Object payload, int exceptionsMaxSize)
throws SchedulerException
Following are the important Parameters
Trigger
Its cron trigger Object. Trigger factory will be used to
create trigger object. It is required CRON expression and it should be valid
quartz cron expression.
http://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html
Storage Type
Its scheduler storage type like Memory or Persisted.
Destination Name
Its message bus destination where scheduler engine
will send messages.
Message
It's JSON object to carry required data from Message
Bus to Listener.
Liferay 7.x onwards Liferay scheduler API is providing
the Timezone while creating Trigger and it will resolve the Daylight time
zone issue for scheduled jobs.
public Trigger createTrigger( String jobName,
String groupName, Date startDate,
Date endDate, String cronExpression, TimeZone
timeZone); |
Example
//Trigger trigger =
TriggerFactoryUtil.createTrigger(jobName,groupName,cronExpression); Trigger trigger = _triggerFactory.createTrigger(jobName,groupName,null,null,cron,TimeZone.getDefault()); @Reference private TriggerFactory _triggerFactory; |
Creating Schedule
//SchedulerEngineHelperUtil.schedule(trigger,
StorageType.PERSISTED, description,destinationName, message,
exceptionsMaxSize) _schedulerEngineHelper.schedule(trigger, StorageType.PERSISTED, description,destinationName, message, exceptionsMaxSize); @Reference private SchedulerEngineHelper _schedulerEngineHelper; |
Deploy and Run Example OSGi Module
Find OSGi module from the below Git repository and
it will demonstrate, create dynamic schedule jobs.
https://github.com/LiferaySavvy/liferay-scheduler-example
Clone the project and import into your Liferay workspace.
Build and Deploy OSGi module with Gradle tasks.
Add Widget to Liferay Page
Access “Create Dynamic Schedule Jobs” UI screen
and create job
Once job is created, Job details will be stored in
Quartz Database tables.
In the console logs, every 2 min Scheduler engine
will trigger the job and send message to Message Bus. Other end listener will
be receiving the message and print in the console logs.
2021-08-01 15:02:00.026 INFO [liferaysavvy/parallel-destination-10][AutomaticRegisteredParellelMessageListener:34]
Message::{destinationName=liferaysavvy/parallel-destination,
response=null, responseDestinationName=null, responseId=null, payload=null,
values={GROUP_NAME=Dynamic, companyId=20100, data=TwoMinJob:Dynamic,
groupId=0, DESTINATION_NAME=liferaysavvy/parallel-destination,
EXCEPTIONS_MAX_SIZE=10,
JOB_STATE=com.liferay.portal.kernel.scheduler.JobState@31b87667,
STORAGE_TYPE=PERSISTED, JOB_NAME=TwoMinJob}} 2021-08-01 15:04:00.025 INFO
[liferaysavvy/parallel-destination-11][AutomaticRegisteredParellelMessageListener:34]
Message::{destinationName=liferaysavvy/parallel-destination, response=null,
responseDestinationName=null, responseId=null, payload=null,
values={GROUP_NAME=Dynamic, companyId=20100, data=TwoMinJob:Dynamic,
groupId=0, DESTINATION_NAME=liferaysavvy/parallel-destination,
EXCEPTIONS_MAX_SIZE=10, JOB_STATE=com.liferay.portal.kernel.scheduler.JobState@2dd02e8e,
STORAGE_TYPE=PERSISTED, JOB_NAME=TwoMinJob}} |
This is how we can create dynamic schedule job and
every schedule job must be tagged with destination.
Destinations are not persisted so it must be created
when server startup or bundle is activated. That’s reason we implemented destination
creation as part of bundle activation. Schedule jobs are persisted as we are
selected Persisted storage type.
This article content is really unique and amazing. This article really helpful and explained very well. So I am really thankful to you for sharing keep it up..
ReplyDeleteThanks for sharing such a useful blog. Really! This Blog is very informative for us which contains a lot of information about the Writing. I like this post.
ReplyDeleteVery informative post! There is a lot of information here that can help any business get started with a successful social networking campaign.
ReplyDeleteThanks for the post. I think as a business owner, I think about the best WordPress form plugin
ReplyDeleteMobile phone is the great invention of modern science. With help of it the communication system developed much more. Handy Zubehör(mobile phone shop) can assist you for give you the best experience of gadgets and also with their services.
ReplyDeleteThis is a wonderful post, I am very happy to read this article. Thanks for giving us this useful information. RJtalents, Best Modeling and Talents Management Agency In Mumbai, India.
ReplyDeleteTalent management agency in Mumbai
Talent management agency in Bangalore
Thanks for sharing such a useful blog. Really! This Blog is very informative for us which contains a lot of information about the Writing. I like this post.
ReplyDeleteyou can buy watches for girls here:
https://leyjao.pk/fashion/best-womens-fashion/classic-watches/
This comment has been removed by a blog administrator.
ReplyDeleteAll information you wish to understand about digital marketing must be researched on a computer. When you are having a computer or laptop problem, the experts are here to help. Register to take advantage of their Laptop reparatur Frankfurt service and receive a first-time discount of up to 15%.
ReplyDeleteIn Bangladesh, a variety of engine oil brands, along with mineral, semi-synthetic, and synthetic oils, are to be had in exceptional grades to healthy the particular wishes of motors and riding conditions. Here at Bike Engine Oil in BD.
ReplyDeleteDitch the complexities of cron jobs! This blog delves into Liferay's dynamic scheduling capabilities, empowering you to automate tasks with ease. Discover how to create, manage, and execute jobs seamlessly within your Liferay portal, freeing you to focus on what matters most.
ReplyDeleteThe PVC resin and additives are thoroughly mixed in a high-speed mixer to create a homogeneous blend. This upvc pipe manufacturing companies that the final product has uniform properties. The mixed material is fed into an extruder, where it is heated and melted. The extruder consists of a heated barrel with a rotating screw that pushes the material forward.
ReplyDelete