Introduction
Alfresco has great support for cron jobs and allows you to do this with few defined beans. One of the common requests is to create cron job that will execute action with some parameters passed to this action.
Alfresco Cron Job
Lets see the code of bean named cronJobDefinition.
<bean id="cronJobDefinition" class="org.alfresco.repo.action.scheduled.CronScheduledQueryBasedTemplateActionDefinition"> <property name="transactionMode"> <value>ISOLATED_TRANSACTIONS</value> </property> <property name="searchService"> <ref bean="SearchService" /> </property> <property name="templateService"> <ref bean="TemplateService" /> </property> <property name="queryLanguage"> <value>lucene</value> </property> <property name="stores"> <list> <value>workspace://SpacesStore</value> </list> </property> <property name="queryTemplate"> <value> PATH:"/app:company_home" </value> </property> <property name="cronExpression"> <value>0 0-59 * * * ?</value> </property> <property name="jobName"> <value>jobA</value> </property> <property name="jobGroup"> <value>jobGroup_ver</value> </property> <property name="triggerName"> <value>triggerA_ver</value> </property> <property name="triggerGroup"> <value>triggerGroup_ver</value> </property> <property name="scheduler"> <ref bean="schedulerFactory" /> </property> <property name="actionService"> <ref bean="ActionService" /> </property> <property name="templateActionModelFactory"> <ref bean="templateActionModelFactory" /> </property> <property name="templateActionDefinition"> <ref bean="cron-job-runner-template" /> </property> <property name="transactionService"> <ref bean="TransactionService" /> </property> <property name="runAsUser"> <value>System</value> </property> </bean>
Few of the important properties are:
- transactionMode, here we can specify how transactions are managed. Possible values are
- ISOLATED_TRANSACTIONS – for each node the action is run in an isolated transaction. Failures are logged.
- UNTIL_FIRST_FAILURE – for each node the action is run in a isolated transacgtion. The first failure stops this.
- ONE_TRANSACTION- the actions for all nodes are run in one transaction. One failure will roll back all;
- queryTemplate, here we specify what nodes are going to be run with specified action, as we know that actions are run on ONE node.
- cronExpression, is quartz expression that will specify when will cron job fire. About format you can read here. In our case job will run every minute(just saying).
- templateActionDefinition, here we specify template that will be called when our job triggers.
Template Action Definition
<bean id="cron-job-runner-template" class="org.alfresco.repo.action.scheduled.SimpleTemplateActionDefinition"> <property name="actionName"> <value>cron-job-runner</value> </property> <property name="parameterTemplates"> <map> <entry> <key> <value>aspect-name</value> </key> <value>{http://www.alfresco.org/model/content/1.0}versionable</value> </entry> </map> </property> <property name="templateActionModelFactory"> <ref bean="templateActionModelFactory" /> </property> <property name="dictionaryService"> <ref bean="DictionaryService" /> </property> <property name="actionService"> <ref bean="ActionService" /> </property> <property name="templateService"> <ref bean="TemplateService" /> </property> </bean>
Key points in specifying template are:
- actionName, here we specify what action will be executed
- parameterTemplates, here we can pass parameters to action named in actionName parameter
Action Definition
Action is defined like any other action using next xml peace of code, parent must be action-executer.
<bean id="cron-job-runner" class="org.alfresco.demoamp.CustomAction" parent="action-executer"> <property name="nodeService"> <ref bean="nodeService" /> </property> </bean>
Action implementation is simple and goes like this :
import java.util.List; import org.alfresco.repo.action.ParameterDefinitionImpl; import org.alfresco.repo.action.executer.ActionExecuterAbstractBase; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ParameterDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.namespace.QName; public class CustomAction extends ActionExecuterAbstractBase { public static final String NAME = "add-aspect"; public static final String PARAM_ASPECT_NAME = "aspect-name"; /** * the node service */ private NodeService nodeService; /** * Set the node service * * @param nodeService * the node service */ public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } @Override protected void executeImpl(Action action, NodeRef actionedUponNodeRef) { if (this.nodeService.exists(actionedUponNodeRef) == true) { QName aspectQName = (QName) action .getParameterValue(PARAM_ASPECT_NAME); this.nodeService.addAspect(actionedUponNodeRef, aspectQName, null); } } @Override protected void addParameterDefinitions(List<ParameterDefinition> paramList) { paramList.add(new ParameterDefinitionImpl(PARAM_ASPECT_NAME, DataTypeDefinition.QNAME, true, getParamDisplayLabel(PARAM_ASPECT_NAME))); } }
Summary
Working with alfresco cron job is great fun and with ease you can make your job that can send reports, or add missing aspects or anything your action can do.
We hope that this short tutorial was helpful for you.
Can you provide an equivalent example of using a Cron job to execute a javascript webscript located on the file system?
Hi Clif,
are you sure that you want to execute a webscript ?
maybe you can create a script.js that you can execute from cron Job, check this example out :
https://wiki.alfresco.com/wiki/Scheduled_Actions#Script_Action_Example .
But if you want to run script from file system you can easily run action that executes the script that is located on the file system.
Let me know how this goes…
Thank you for instructions of a non javascript triggered action. Where to put this configuration file? What about a bean id=”templateActionModelFactory”?
Hi.
What is the alfresco version you are using?
Alfresco 5.0.a CE. While booting Alfresco there comes an error in the log file, missing templateActionModelFactory. So I have added this bean declaration to your example code in service-context.xml inside a Maven project. Is this correct?
Hi,
here is a similar issue that you have.
And here is the solution:
Did you do it like this?
Maybe I should add it to the example.
Now it works, thank you. It would be nice if you could provide the complete code in your example for people who use the standard service-context.xml file of their amp project.
Thank you for nice article. I have a requirement to run a cron job right after ldap sync job (OOTB ldap subsystem). Is there an option to create this dependency ??.
Thank you!
Cron jobs are depended only on time. If you want to run action after something happens in alfresco then it is not cron job that you are looking for, right ?
I am sure that you can either override existing service or using AOP to add your stuff.
I am unclear what you are doing , but you should check common-ldap-context.xml and beans that are defined in this xml. This would be good starting point for your work.