Alfresco本身非常適合非同步的資料處理,藉由存放區(Space)、規則引擎(Rule Engine)、排程作業(Scheduled Action)以及自動流程引擎(Workflow Engine)等機制,讓企業的日常工作變得井然有序。本篇就來介紹如何定義一個新的排程。延續前幾篇文章的費用申請場景;員工將費用申請憑證以及相關屬性存入『費用申請』檔案夾後,Alfresco每隔五分鐘來巡視是否有申請單進來,申請單如果符合必要條件;以本例來說:就是檔案內含ExpenseDetails這個屬性集,則將申請單移至『費用審核』檔案夾等待審核。
一個排程作業是由三個部分組成:
- 排程引擎Cron的描述
- 處理對象的檢索樣板(Query Template)
- 動作的樣板(Action Template)
- 在<beans>標籤內定義第一個Bean叫做templateActionModelFactory,是用來產出樣板引擎FreeMarker可以存取的資料模型,內文為:
<bean id="templateActionModelFactory" class="org.alfresco.repo.action.scheduled.FreeMarkerWithLuceneExtensionsModelFactory">
<property name="serviceRegistry">
<ref bean="ServiceRegistry"/>
</property>
</bean> - 定義動作(Action)的執行程式,本範例以Alfresco後端Script定義動作的內容。因Alfresco內嵌完整存取Repository資源的JavaScript API,以Script實作動作邏輯既彈性(不必重啟系統)又快速。請在<beans>標籤內繼續輸入以下字串:
<bean id="expenseVoucherMoveScriptAction" class="org.alfresco.repo.action.scheduled.SimpleTemplateActionDefinition">
<property name="actionName">
<value>script</value>
</property>
<property name="parameterTemplates">
<map>
<entry>
<key>
<value>script-ref</value>
</key>
<value>${selectSingleNode('workspace://SpacesStore', 'lucene', 'PATH:"/app:company_home/app:dictionary/app:scripts/cm:expenseVoucherMove.js"' )}</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>
以上是定義一個名叫expenseVoucherMoveScriptAction的執行物件,這個物件會透過Lucene搜尋位於Company Home/Data Dictionary/Scripts路徑下名叫expenseVoucherMove.js的檔案。這個後端JavaScript檔案是實際將費用憑證檔案由『費用申請』檔案夾移到『費用審核』檔案夾的執行者。 - 定義被動作的標的物件(檔案或檔案夾)以及Cron的執行排程。在<beans>標籤內繼續輸入以下字串:
<bean id="expenseVoucherMoveScriptRun" class="org.alfresco.repo.action.scheduled.CronScheduledQueryBasedTemplateActionDefinition">
<property name="transactionMode">
<value>UNTIL_FIRST_FAILURE</value>
</property>
<property name="compensatingActionMode">
<value>IGNORE</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>
<!-- Find nodes with ExpenseDetails aspect -->
<property name="queryTemplate">
<value>+PATH:"/app:company_home/cm:費用申報/*" +ASPECT:"custom:ExpenseDetails"</value>
</property> <property name="cronExpression">
<value>0 0/5 * * * ?</value>
</property> <property name="jobName">
<value>jobD</value>
</property>
<property name="jobGroup">
<value>jobGroup</value>
</property>
<property name="triggerName">
<value>triggerA</value>
</property>
<property name="triggerGroup">
<value>triggerGroup</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="expenseVoucherMoveScriptAction"/>
</property>
<property name="transactionService">
<ref bean="TransactionService"/>
</property>
<property name="runAsUser">
<value>System</value>
</property></bean>
以上是定義一個名叫expenseVoucherMoveScriptRun的執行物件,這個物件會每隔五分鐘(Cron語法 0 0/5 * * * ?)搜尋Company Home底下的『費用申報』檔案夾內(PATH前面的加號表示只搜尋這個目錄)是否存有貼有ExpenseDetails屬性集的檔案,如果存在的話,則執行expenseVoucherMoveScriptAction執行物件。 - 撰寫自動搬檔Script: expenseVoucherMove.js。請在Company Home/Data Dictionary/Scripts目錄下建立expenseVoucherMove.js檔案,搬移邏輯可以自由發揮。以下是參考範例:
var verifyFolder = companyhome.childByNamePath("費用審核");
if(verifyFolder != null && verifyFolder.hasPermission("CreateChildren")){
//change the name with time stamp
var dt = new Date();
var y = dt.getFullYear();
var m = dt.getMonth() + 1;
if(m < 10){
m = "0" + m;
}else{
m = "" + m;
}
var d = dt.getDate();
if(d < 10){
d = "0" + d;
}else{
d = "" + d;
}
var h = dt.getHours();
if(h < 10){
h = "0" + h;
}else{
h = "" + h;
}
var mm = dt.getMinutes();
if(mm < 10){
mm = "0" + mm;
}else{
mm = "" + mm;
}
var s = dt.getSeconds();
if(s < 10){
s = "0" + s;
}else{
s = "" + s;
}
var stamp = "T" + y + m + d + h + mm + s;
//
document.name = stamp + "_" + document.name;
document.save();
//
document.move(verifyFolder);
}
以上程式碼的意思是:找到費用審核的檔案夾,接著在檔名前冠上時間戳記,為避免相容性問題,建議檔名不要以數字開頭,再來就是將檔案搬移到『費用審核』檔案夾。