You are on page 1of 49

ecmarchitect.

com

AlfrescoDeveloper:AdvancedWorkflows
November,2007
JeffPotts

ThisworkislicensedundertheCreativeCommonsAttributionShareAlike2.5License.Toviewacopyofthislicense, visithttp://creativecommons.org/licenses/bysa/2.5/orsendalettertoCreativeCommons,543HowardStreet,5thFloor, SanFrancisco,California,94105,USA.

ecmarchitect.com
AlfrescoDeveloper:AdvancedWorkflows
November2007

JeffPotts

TableofContents
Introduction...........................................................................................................................................4 Whatisaworkflow?.............................................................................................................................4 Workflowoptions.............................................................................................................................6 Alfrescoworkflow............................................................................................................................7 jBPMconcepts......................................................................................................................................9 Deployingprocesses............................................................................................................................18 WiringaprocesstotheAlfrescoUI....................................................................................................20 Defineaworkflowspecificcontentmodel....................................................................................21 Updatewebclientconfigcustom.xml...........................................................................................23 Externalizethestrings....................................................................................................................23 Implementationsummary....................................................................................................................24 SomeCoWhitepapersubmissionexample..........................................................................................25 Businessprocessdescription..........................................................................................................25 Highlevelsteps.............................................................................................................................25 Step1:Implementthebasicflowandworkflowuserinterface.....................................................26 Step2:Implementwebscriptsandactions....................................................................................40 Step3:Addatimertothethirdpartytask.....................................................................................47 Step4:Configuretheworkflowsfordeployment..........................................................................48 Conclusion...........................................................................................................................................48 Deployingandtesting..........................................................................................................................49 Wheretofindmoreinformation..........................................................................................................49 Abouttheauthor..................................................................................................................................50

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page2of49

ecmarchitect.com
AlfrescoDeveloper:AdvancedWorkflows
November2007 JeffPotts

Introduction
ThisarticleisabouttheadvancedworkflowfunctionalityavailableinAlfrescothroughitsembedded JBossjBPMworkflowengine.First,becauseworkflowcanmeandifferentthingstodifferentpeople, I'lltalkaboutmydefinitionoftheterm.Then,I'lldiveintofundamentaljBPMconceptsthatwillhelp youunderstandhowprocessesaredefinedandhowtheworkflowengineactuallyworks.(Thosewho usejBPMseparatefromAlfrescomightevenfindthissectionhelpful).Oncethatfoundationisin place,I'llwalkthroughanexamplethatfeaturesmanyofthedifferentconcepts. TheexamplecontinuestheSomeCoexamplescoveredinearlierpapers.Init,we'llimplementa businessprocessthathelpsSomeCoroutewhitepapersforreviewandapprovalbyinternalaswellas externalparties.

Whatisaworkflow?
WhenAlfrescoreleasedversion1.4oftheproduct,theymadeahugeleapforwardinenterprise readiness.ThatwasthereleasewhenAlfrescoembeddedtheJBossjBPMengineintotheproduct whichmeantthatenterprisescouldrouteAlfrescorepositorycontentthroughcomplexbusiness processes.Acontentrepositorywithouttheabilitytofacilitatebusinessprocessesthatproduce, consume,ortransformthecontentwithinitislittlemorethanaglorifiedfileserver,sothiswasa welcomeaddition. Butbeforewegeekoutonthewondersofgraphbasedexecutionlanguageslet'sagreeonwhattheterm workflowmeans.Generically,aworkflowisareliablyrepeatablepatternofactivityenabledbya systematicorganizationofresources...thatcanbedocumentedandlearned1.Thetermhasbeenaround sincepeoplestartedstudyingthenatureofworkintheearly20thcenturyinanefforttostreamline
1 http://en.wikipedia.org/wiki/Workflow

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page3of49

ecmarchitect.com
manufacturingprocesses. Infact,intheworldofECM,itissometimeshelpfultothinkofanassemblylineormanufacturing processwhenthinkingabouthowcontentflowsthroughanorganization.Contentisbornofraw material(data),shapedandmoldedbyoneormorepeople(collaboration)ormachines(systems), reviewedforquality,anddeliveredtoconsumers.Contentmaygothroughasingleprocessormany subprocesses.Contentmaytakedifferentroutesthroughaprocessbasedoncertainaspectsofthat content.Theoutputofanorganizationordepartmentofknowledgeworkersisessentiallythecontent thatcomesrollingofftheassemblyline(thecollectionofworkflowsthatdefinethatorganization's businessprocesses). Althoughnotalwaysformalizedorautomated,almosteveryoneinmodernsocietyhasbeeninvolvedin aworkflowinsomeway:

Whenyousubmitaninsuranceclaim,youareinitiatingaworkflow. Ifyouwitnessdrunkanddisorderlyconductonanairlineflightandareaskedtoprovidea statementtotheairline,youareparticipatinginaworkflow.(Seriously,ithappensmoreoften thanyou'dthink). Whenyoucheckonthestatusofyourloanapplication,youareaskingformetadataabouta runningworkflow. Whensomeonebringsyouacapitalrequestthatrequiresyourapprovalbecauseitisovera certaindollaramount,acharacteristicofthatrequest(thedollaramount)hastriggereda decisionwithintheworkflowthatroutesthecapitalrequesttoyou. Whenyougivethefinalapprovalforapieceofwebcontenttobepublished,itislikelyyouare completingaworkflow.

Asvariedastheseexamplesare,allofthemhaveacoupleofthingsincommonthatmakethem relevanttoECM:(1)Theyareexamplesofhumantohumanand,insomecases,humantomachine interactionand(2)Theyarecontentordocumentcentric. Thesearetwoveryimportantcharacteristicsthathelpclarifythekindofworkflowwe'retalkingabout. Therearestandaloneworkflowengines(infact,jBPMisoneofthem)thatcanbeusedtomodeland executeallsortsofrepeatablepatternsofactivity,withorwithoutcontent,butintheECMspace,the

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page4of49

ecmarchitect.com
patternswecaremostaboutarethosethatinvolvehumansworkingwithcontent.1

Workflowoptions
Someofyouaresaying,You'reright.Workflowsareeverywhere.Icouldreallystreamlinemy organizationbymovingprocessescurrentlyimplementedwithemail,phonecalls,andcubicaldrive bysintoamoreformalizedworkflow.Whataremyoptions?Let'stalkaboutthree:Rollyourown, Standaloneworkflowengines,andEmbeddedworkflowengines. Rollyourown.Peopleareoftentemptedtomeettheirworkflowrequirementswithcustomcode.Very basicsystemsmightbeabletogetbywithasingleflagonarecordoranobjectthatdeclaresthestatus ofthecontentlikeDraftorInRevieworApproved.Butflagsonlycapturethestateofapiece ofcontent.Ifyouwanttoautomatehowcontentmovesfromstatetostate,thecodingandmaintenance becomesmorecomplex.Sure,youcanwritecodeaspartofyourapplicationthatknowsthatonceDraft documentsaresubmittedforreview,theyneedtogotoPurchasingfirstandthentoFinance,ifand onlyiftherequestedcashoutlayismorethan$10mbutdoyoureallywantto? Peopleintentonrollingtheirownworkflowoftenrealizethemaintenanceproblemthiscreates,sothey createanabstractionusedtodescribetheflowfromstatetostatethatkeepsthemfromembeddingthat logicincompiledcode.Oncethey'vedonethat,though,they'veessentiallycreatedtheirown proprietaryworkflowenginethatnooneelseintheworldknowshowtorunormaintain.Andwithall oftheopensourceworkflowenginesavailable,whywouldyouwanttodothat?Sotherollyourown optionisreallynotrecommendedforanybutthemostbasicworkflowrequirements. Standaloneengines.Thereareanumberofstandaloneworkflowenginessometimesmorebroadly referredtoasBPM(BusinessProcessManagement)bothopensourceandproprietary.Theseare oftenextremelyrobustandscalablesolutionsthatcanbeusedtomodel,simulate,andexecuteany processyoucanthinkoffromhighvolumeloanprocessingtocallcenterqueuemanagement.Often, theseworkflowenginesareimplementedinconjunctionwitharulesenginewhichletsbusinessusers havecontrolovercomplicatedifthenelsedecisiontrees. Standaloneenginesaremostappropriateforextremelyhighvolumeorexceedinglycomplexsolutions
1 Ofcoursedocumentcentricworkflowsmayincludefullyautomatedstepsandmachinetomachineinteractionsthe pointisthatdocumentcentricworkflowsinwhichhumansreview,approve,orcollaborateinsomewayareinthescope ofthediscussionwhileprocesseswhichrunlightsoutsystemtosystemorchestrationorintegrationarenot.

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page5of49

ecmarchitect.com
involvingmultiplesystems.Anothergooduseforstandaloneenginesiswhenyouaredevelopinga customapplicationthathasworkflowrequirements.Standaloneenginescanusuallytalktoany databaseorcontentmanagementrepositoryyoumighthaveimplemented,buttheywon'tbeastightly integratedintothecontentmanagementsystem'suserinterfaceastheworkflowenginebuiltintothe CMS.Forthisreason,forcontentcentricsolutionsthatoperatemostlywithinthescopeoftheCMS,it isusuallylesscomplicated(andlesscostly)tousetheworkflowengineembeddedwithintheCMS, providedithasenoughfunctionalitytomeetthebusiness'workflowrequirements. Embeddedworkflowengines.AlmosteveryCMSavailabletoday,whetheropensourceor proprietary,hasaworkflowengineofsomesortembeddedwithinit.However,thecapabilityofeachof thesevarywidely.IfyouareintheprocessofselectingaCMSandyoualreadyknowthekindof workflowrequirementsyou'llface,itisimportanttounderstandthecapabilitiesoftheworkflowengine embeddedwithinthesystemsyouareconsideringbeforemakingafinalselection. Themajorbenefitofleveraginganembeddedworkflowengineisthetightlevelofintegrationforusers aswellasdevelopers.UserscaninitiateandinteractwithworkflowswithoutleavingtheCMSclient. Typically,developerscustomizingorextendingtheCMScanworkwithworkflowsusingthecore CMSAPI.

Alfrescoworkflow
Alfrescohastwooptionsforimplementingworkflowswithintheproduct.Forverysimplistic workflows,nontechnicalenduserscanleverageAlfresco'sBasicWorkflowfunctionality.Formore complexneeds,AlfrescoleveragestheembeddedJBossjBPMenginetoprovideAdvancedWorkflow capability. Basicworkflowsareaniceendusertool.Youshouldknowhowtheyworkandwhatthefeaturesand limitationsaresoyoucanmakegooddecisionsaboutwhentousethem.Basicworkflowsusefolders andaforwardstep/backwardstepmodeltoimplementserialprocesses.Whenapieceofcontentis droppedinafolder,aruleistriggeredthatassociatesaforwardstepandabackwardstep(oneor theotherorboth)withthecontent.ThesestepsaretiedtoAlfrescoactionssuchasSetapropertyor Movethecontenttoaspecifiedfolder.Enduserscanthenclickontheappropriatestepforagiven pieceofcontent. Forexample,supposewehaveasimplesubmitreviewapproveprocessinwhichcontentissubmitted,

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page6of49

ecmarchitect.com
thenreviewed,thenapprovedorrejected.Onewaytoimplementthiswithbasicworkflowsistouse threefolderslet'ssaytheyarecalledDraft,InReview,andApprovedeachofwhichhavea rulesetthatappliesabasicworkflow.TheworkflowforcontentintheDraftfolderwouldhaveasingle forwardsteplabeledSubmitanditsactionwouldmovecontenttotheInReviewfolderandsend anemailtotheapprovergroup.TheInReviewfolderwouldhaveaworkflowinwhichtheforward stepwouldbelabeledApproveanditwouldcopythecontenttoanApprovedfolder.The backwardstepwouldbelabeledRejectanditsactionwouldmovethecontentbacktotheDrafts folder. Youcanseethatbasicworkflowsareuseful,butlimitedwithregardtothecomplexityofthebusiness processestheycanhandle. Althoughwehaven'tyetcoveredthedetailedcapabilitiesofAlfrescoadvancedworkflows,Ithoughtit wouldbeagoodideatocomparebasicandadvancedworkflowsatahighlevelnowsowecanleave thetopicofbasicworkflowsbehindandspendtherestofthearticleonadvancedworkflows: Alfrescobasicworkflows...

Alfrescoadvancedworkflows...

Areconfigurablebynontechnicalend usersviatheAlfrescowebclient Leveragerules,folders,andactions Canonlyhandleprocesseswithsingle step,forwardand/orbackward,serial flows Donotsupportdecisions,splits,joins,or parallelflows Donotmaintainstateormetadataabout theprocessitself

Aredefinedbybusinessanalystsand developersviaagraphicalEclipseplugin orbywritingXML Leveragethepoweroftheembedded JBossjBPMworkflowengine Canmodelanybusinessprocessincluding decisions,splits,joins,parallelflows,sub processes,waitstates,andtimers Canincludebusinesslogicwritteneither inJavaScriptorJava,eitherofwhichcan accesstheAlfrescoAPI Maintainstateandprocessvariables (metadata)abouttheprocessitself)

NowthatyouunderstandthedefinitionofworkflowinthecontextofECM,someoftheoptionsfor implementingworkflowrequirements,andtheoptionswithinAlfrescospecifically,it'stimetodivein AlfrescoDeveloper:AdvancedWorkflows


ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page7of49

ecmarchitect.com
tothegorydetailsofthejBPMengine.

jBPMconcepts
Thissectionisabitlikevegetablessomewhatuglyandunpleasanttastingbutultimatelygoodforyou (nooffensetomyvegetarianfriends).Whileitispossibletomodifytheoutoftheboxworkflowsto suityourneedswithoutunderstandingthedetailsofhowthejBPMengineworks,Irecommendyou pinchyournoseandtakeabite.You'llthankmelaterwhenyouarereadytodosomethingcomplex andcompletelyunlikeanyoftheoutoftheboxexamples. WhatisthejBPMengine? JBossjBPMisanopensource,standaloneworkflowengine1.Itcanruninanyservletcontainerit doesn'trequireJBossApplicationServer.ThejBPMengineisresponsibleformanagingdeployed processes,instantiatingandexecutingprocesses,persistingprocessstateandmetadatatoarelational database(viaHibernate),andtrackingtaskassignmentandtasklists. Processdefinitions jBPMisbuiltontheideathatanyprocesscanbedescribedasagraphorasetofconnectednodes. WorkflowsaredescribedwithprocessdefinitionsusinganXMLbasedlanguagecalledJavaProcess DefinitionLanguage(jPDL).jPDLisoneexampleofagraphbasedexecutionlanguage.Othersinclude BPELforserviceorchestrationandSEAMpageflow. InjPDL,eachnoderepresentsastepinaworkflow.Connectionsbetweennodessignifythetransition fromonesteptoanother.Considerthefigurebelow.Weseearelativelysimpleprocesswith5nodes. BylookingatthetransitionsweseethatthepathofexecutionwillalwaysbefromnodeAtonodeB. NodeBhastwooutgoingpaths.OnepathistonodeCandtheothertonodeD.Thepathsconvergeon nodeE.Notethatfromthediagramitisimpossibletotellwhichpathwillbetaken.It'salsopossible thatbothcouldbefollowedsimultaneously.

1 JBossrightlycallsjBPMaplatformforgraphbasedexecutionlanguages.Workflowasitisdefinedhereisoneof severaldifferentdomainsthatcanbeaddressedwithagraphbasedexecutionlanguage.SojBPMismorethanjusta workflowengine,butforthisarticle,that'sallwecareabout.

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page8of49

ecmarchitect.com

Thenode'stypedetermineshowitbehaves.Soyoumighthaveanodethatsplitsexecutionintoseveral paths(likenodeB)oranodethatjoinsmultiplepathsofexecutionintoasinglepath(likenodeE). Youmighthaveanodethatcallssomeothersystemandwaitstohearbackfromthatsystembefore proceeding.We'llexplorethedifferentnodetypesavailableandbrieflytalkaboutcreatingyourown nodetypesshortly. Tokens AtokenisliketheYouAreHereflagforaprocess.Thetokenmovesfromnodetonodeasthe processisexecuted.Butitdoesn'tmoveonitsown.Tokensonlymovewhentheyaresignaled.Let's lookatanexample.Inthefigurebelow,whenweexecutetheprocess,thetokenisatNodeA.Ifwe signalthetoken,itwilltaketheonlypathavailabletoitwhichistomovetoNodeBwhereitwillwait forasignal.FromNodeBtherearemultiplepathsavailable.Ifwesignalthetokenwithoutspecifying whichpathtotake,itwilltakeadefaultpath.Or,wecouldtellitwhichpathtotakewhenwesendit thesignal.

Tokenscanhavechildren.Forexample,inthefigurewejustlookedat,supposewewantedtofollow bothpaths.Inthatcase,asshowninthefigurebelow,thetokenwouldspawntwochildtokens,onefor thepathfromNodeBtoNodeCandonefromNodeBtoNodeD.Whenthepathsconverge,thechild tokensgoawayandtheparenttokenresumes. AlfrescoDeveloper:AdvancedWorkflows


ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page9of49

ecmarchitect.com

Whyshouldwecareabouttokens?I'msuretherearelotsofreasonsbutafewthatcometomindare (1)whenyouwriteyourownnodetypesyouareresponsibleforhowtokensaresignaled(2)process variables(moreonthoseshortly)arescopedtoatoken,and(3)ifaprocessevergetsstuckyoumay needtosignalthetokenmanually. Nodetypes Imentionedearlierthatthenodetypedeterminesthenode'sbehaviorwhichbegsthequestion:What nodetypesareavailable? NodeType Startstate Fork Join Decision Node State ProcessState Description Onlyoneallowedperprocessdefinition.Onlyoutgoingtransitionsareallowed. Spawnsmultipleconcurrentpathsofexecution. Joinsmultiplepathsintoasinglepath.Becomesawaitstateuntilalltokenshave reachedthejoin. Choicebetweenmultiplepathsofexecution.We'llseeexamplesofhowto implementthelogicforadecisionlaterinthearticle. Plainoldnode.Goodforcontaininganactionwhichmightexecutebusiness logic. Awaitstate.Executiondoesnotproceeduntilthenodeisexplicitlysignaled. Executesasubprocess.Behavesasawaitstatewhilethesubprocessexecutes.

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page10of49

ecmarchitect.com
NodeType TaskNode EndState Description Anodethatcontainsoneormoretasksassignedtohumans. Onlyoneallowedperprocessdefinition.Onlyincomingtransitionsareallowed.

Itisimportanttonotethatifyourapplicationhasarequirementthatisn'taddressedbyoneoftheout oftheboxnodetypesyoucanaddyourown.And,ifthebehaviorofanodetypeisn'texactlywhatyou need,youcanextendit. IfweimplementedthediagramshownpreviouslyinwhichnodeBisaforkandnodeEisajoin,the jPDLwouldlooklikethefollowing:


<?xmlversion="1.0"encoding="UTF8"?> <processdefinitionxmlns=""name="simpleprocess"> <startstatename="start"> <transitionname=""to="NodeA"></transition> </startstate> <nodename="NodeA"> <transitionname=""to="NodeB"></transition> </node> <forkname="NodeB"> <transitionname=""to="NodeC"></transition> <transitionname="tr2"to="NodeD"></transition> </fork> <nodename="NodeC"> <transitionname=""to="NodeE"></transition> </node> <nodename="NodeD"> <transitionname=""to="NodeE"></transition> </node> <joinname="NodeE"> <transitionname=""to="end1"></transition> </join> <endstatename="end1"></endstate> </processdefinition>

Actions Sofarwe'veseenthataprocesscanbemodeledasacollectionofnodesconnectedviapathsor transitions.Acommonrequirementistobeabletoexecutesomecodeorbusinesslogicatcertain AlfrescoDeveloper:AdvancedWorkflows


ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page11of49

ecmarchitect.com
pointswithintheprocess.Forexample,maybeyouwanttosendanemailorperhapsyouwantto incrementacounterthatkeepstrackofhowmanytimesanodehasbeenexecuted.Actionsarethe hooksthatmakethishappen. Whattriggersanaction?Asatokenpropagatesthroughthegraphitfiresevents.Examplesinclude thingslikeenteringanode,leavinganode,orfollowingatransition. ActionscanbeabeanshellexpressionoraJavaclass.InthecontextofAlfresco,actionscanalsobe writtenusingJavaScriptwhichcanmakeuseoftheAlfrescoJavaScriptAPI. Intheexamplebelowweseeatasknodenamedreviewwithataskcalledscwf:reviewTask.The taskhasscriptassociatedwithitstaskcreateevent.Don'tworryaboutwhatthescriptisdoingfor now.Thisisjustanexampleofassociatingbusinesslogicwithanevent.
<tasknodename="review"> <taskname="scwf:reviewTask"swimlane="reviewer"> <eventtype="taskcreate"> <script> if(bpm_workflowDueDate!=void)taskInstance.dueDate= bpm_workflowDueDate; if(bpm_workflowPriority!=void)taskInstance.priority= bpm_workflowPriority; </script> </event> ...

Here'sanexamplethatusestheactiontagtoassociateAlfrescoJavaScriptwithatransition.This particularJavaScriptrunsanactionagainsteverypieceofcontentintheworkflowpackage.
<tasknodename="addAspect"> <transitionname="transToReview"to="review"> <actionclass="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript"> <script> varscAspectQName="{http://www.someco.com/model/content/1.0}webable"; varaddAspect=actions.create("addfeatures"); addAspect.parameters["aspectname"]=scAspectQName; for(vari=0;i&lt;bpm_package.children.length;i++){ if(!bpm_package.children[i].hasAspect(scAspectQName)){ addAspect.execute(bpm_package.children[i]); } }

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page12of49

ecmarchitect.com
</script> </action> </transition> </tasknode>

NotethatintheAlfrescoJavaScriptexample,thejPDLpointstoaJavaclass.Inthiscase,Alfrescohas providedanactionclassthatexecutesAlfrescoJavaScript.Butyoucanwriteyourownactionclasses withJavaaswellasweshallsoonseeintheexample. ProcessVariables Often,thereismetadataaboutaprocessthatneedstobetracked.Aduedateorapriorityflagaretwo examples.Aduedateisn'treallyapropertyofthecontentbeingroutedthroughtheworkflowit'sa propertyoftheprocessitself.jBPMgivesustheabilitytostorethiskindofdataaspartoftherunning processthroughprocessvariables. Processvariablesarenamevaluepairsthatwillgetpersistedwiththerestoftheprocessstate. Variablescanbescopedtoaspecifictoken.Bydefault,theyarescopedtotheroottokensotheyare effectivelyglobal. Intheexamplebelow,weusethescriptelementtosetavariablecalledscwf_tempCntequalto0 whenthetokenentersthenode.
<eventtype="nodeenter"> <script> <variablename="scwf_tempCnt"access="write"/> <expression> scwf_tempCnt=0; </expression> </script> </event>

Elsewhereintheprocesswecouldreadthevalueofthevariablewithanexpressionlike: #{scwf_tempCnt}. Tasks Ataskisastepinaworkflowthatrequireshumaninteraction.jBPMmaintainsalistoftasksassigned toeachparticipant.Howusersinteractwiththetasklistisuptoeachapplication.InAlfresco,adashlet displaysatodolistforthecurrentlyloggedinuser.Asuserscompletetheirtasksthetasksare removedfromthetodolist.Anemptytodolistisshownbelow. AlfrescoDeveloper:AdvancedWorkflows


ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page13of49

ecmarchitect.com

TaskAssignment(Swimlanes,Initiatorswimlane,actors,pooledactors) Iftasksarestepsahumanperforms,howdotasksgetassociatedwiththepeoplewhoneedtoperform them(actors)?Oneofthechildelementsofthetaskelementisassignment.Theassignment elementpointstoaJavaclassthatisaninstanceofAssignmentHandler.Ithandlesassigningthetaskto anactor.AlfrescosavesussomeworkheretheyprovideanAssignmentHandleroutofthebox.We'll seeanexampleofhowitcanbeusedmomentarily. Often,aprocesshasthenotionofaroleinwhichmultipletasksduringtheprocessgetassignedtothe sameactorplayingthatrole.Forexample,supposewearedefiningaprocessthatcontainsmultiple tasksperformedbymarketing.Ratherthanassignthemarketinggrouporindividualrepeatedlyto eachtask,itwouldbeniceifwecouldmaketheassignmentonceandthentelltheothertaskstousethe sameassignment.InjBPMthisisimplementedthroughswimlanes.Anactorcanbeassignedtoa swimlane,andthenalltasksthatneedtobeperformedbythesameactorrefertotheswimlane.The snippetbelowshowswhatthislookslikeinjPDL.
<swimlanename="marketing"> <assignmentclass="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment"> <pooledactors>#{people.getGroup('GROUP_marketing')}</pooledactors> </assignment> </swimlane> <swimlanename="engineering"> <assignmentclass="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment"> <pooledactors>#{people.getGroup('GROUP_engineering')}</pooledactors> </assignment> </swimlane> <tasknodename="marketingReview"> <taskname="scwf:marketingReview"swimlane="marketing"></task> <transitionname="transToLegal"to="engineeringReview"></transition> <transitionname="transToRejected"to="rejected"></transition> </tasknode>

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page14of49

ecmarchitect.com
<tasknodename="engineeringReview"> <taskname="scwf:engineeringReview"swimlane="engineering"></task> <transitionname="transToMarketing"to="finalMarketingReview"></transition> <transitionname="transToRejected"to="rejected"></transition> </tasknode> <tasknodename="finalMarketingReview"> <taskname="scwf:finalMarketingReview"swimlane="marketing"></task> <transitionname="transToApproved"to="approved"></transition> <transitionname="transToRejected"to="rejected"></transition> </tasknode>

Inthisexamplewe'redefiningtwoswimlanes:engineeringandmarketing.Theengineering swimlaneisassignedtotheengineeringgroup.Themarketingswimlaneisassignedtothe marketinggroup.Eachofthethreetasksisassignedtotheappropriateswimlaneusingthe swimlaneattributeofthetaskelement. Aspecialswimlaneexistscalledinitiator.Thisswimlanealwayshastheactorthatstartedthe workflow.Ifyouwanttoassignoneormoretaskstotheinitiator,addtheinitiatorswimlanetothe processdefinitionlikethis: <swimlanename="initiator"/> andthenusetheswimlaneattributetomaketheassignment. IfyouhavealreadyusedAlfrescoAdvancedWorkflowsyouknowthatinthesampleworkflowsthe initiatorassignsthereviewsteptoauserorgroupbyselectingavalueintheuserinterface.We'llsee howthatvaluemakesitswayintothetaskassignmentalittlelater. PooledActors Whendefiningabusinessprocessitisimportanttounderstandhowtheparticipantsintheprocesswill dothework.Onespecificareathatneedstobeconsiderediswhethertousepooledactorsforagiven task.Suppose,forexample,youassignedatasktoagroupoftenpeople.Youcoulditeratethroughthe groupandassignatasktoeachandeverymemberofthegroupandthennotconsiderthetaskcomplete untilallactorshavetakenaction.Analternativeistousepooledactors.Usingapool,allmembersofa grouparenotifiedofthetask,butassoonasoneactortakesownershipofthetask,itisremoved fromeveryoneelse'stodolist.Theownercantheneithercompletethetaskorreturnittothepool.Ifit isreturnedtothepool,allmembersofthegroupseethetaskintheirtodolistuntilanotherperson takesownershiporcompletesthetask.Tousepooledactors,usethepooledactorschildelementof AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page15of49

ecmarchitect.com
theassignmentelementinsteadoftheactorelement. Thedecisiontousepooledactorsornotdependsentirelyonthebusinessprocessthereisnopreferred approach. jBPMProcessDesigner OneofthenicethingsaboutjBPMisthatagraphicaltoolisavailableasanEclipsepluginforcreating anddeployingprocessdefinitionscalledtheGraphicalProcessDesigner(GPD).Marketingguysfor workflowtoolslovetosaythingslike,Usingthegraphicalprocessdesigner,businessanalystscan createadvancedworkflowswithoutwritingcode!.Whileitisahandytool,particularlywhenyouare firstlayingoutaprocess,intherealworld,you'llfindyourselfswitchingtothesourcetabfairly quickly. Here'swhattheDiagramtablookslikeforthefivenodeprocesswedefinedearlier.

TheDiagramtabisusedtolayouttheprocessbyselectingnodetypesfromthepaletteandclickingon thecanvas.TheTransitiontoolisusedtoconnectthenodes.Nodepropertiescanbeeditedinthetree viewoftheprocessornodescanbedoubleclickedtoopenapropertieseditor.Atanytimeyoucan switchtotheSourcetabtoseeandedittheunderlyingXML. AlfrescoDeveloper:AdvancedWorkflows


ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page16of49

ecmarchitect.com
Deployingprocesses
Ifyoulookattheoutoftheboxprocessdefinitionsyou'llnoticethatAlfrescochosetoputallprocess definitionsinthesamedirectory.ThisisabitannoyingtomebecauseitbreakstheGPDdeployment tool.So,whenorganizingyourwork,IrecommendyounotfollowAlfresco'sexampleandinsteadput eachprocessdefinitioninitsowndirectoryandnamethejPDLfileprocessdefinition.xml. Ifyouarewritingcomplexprocessesthatdependonresourcesbeyondjustthedefinitionitself,youcan optionallypackagethosedependenciesalongwithyourprocessdefinitionintoaProcessArchive (PAR)file(LikeaJARfile,aPARfileisjustazip).TheJavaClassesandResourcessectionofthe DeploymenttabisusedtoassociatedependencieswiththeprocesssotheGPDknowstoincludethem withthePAR.IfyouchoosenottocreateaPAR,dependentclassescanresideanywhereonthe Alfrescoclasspath,preferablyrightalongsideyourotherclassesintheextensiondirectory. Onceyou'vedefinedyourprocessanddecidedhowtopackageit,theprocessdefinitionhastobe deployedtothejBPMruntime.Let'slookattwooptionsfordeployingajBPMprocessdefinitionto Alfresco:(1)usethedeploymenttabintheGPDor(2)deploytheprocessdefinitionalongsideyour otherwebclientcustomizationsintheAlfrescoextensiondirectory. Thedeploymenttabistheeasiestoptionandisveryhandywhenyouarestilldevelopingand debuggingtheprocessbecauseyoudon'tneedtorestarttheapplicationserverbetweendeployments. Thegraphicbelowshowsascreenshotofthedeploymenttab. TheDeploymentServerSettingstellthepluginhowtocommunicatewiththejBPMdeployment process.TheTestConnectionbuttonwillverifythepluginisabletocommunicatetothedeployer process.

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page17of49

ecmarchitect.com

WhenyouclickDeployProcessArchive...theprocesswillbeuploadedtothejBPMengine.Ifthe processhasalreadybeendeployeditwillgetversioned.IfeithertheTestConnectionbuttonorthe DeployProcessArchivebuttonresultinanerror,checktheapplicationserverlogforclues. AnotherdeploymentalternativeistouseaSpringbean.Thesnippetbelowshowshowtopointtoa singleprocessdefinition.


<beanid="extension.workflows.workflowBootstrap"parent="workflowDeployer"> <propertyname="workflowDefinitions"> <list> <props> <propkey="engineId">jbpm</prop> <propkey="location">alfresco/extension/workflows/simple process/processdefinition.xml</prop> <propkey="mimetype">text/xml</prop> <propkey="redeploy">true</prop> </props> </list> </property> </bean>

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page18of49

ecmarchitect.com
Ifyouhavemultipleworkflowstodeployusingthisapproachusemultiplepropselements. TheengineIdmustbesettojbpm.Maybeatsomepointotherengineswillbesupportedbutfornow, jBPMistheonlychoice. Thelocationisanylocationontheclasspath,buttobeconsistentwithhowcustomizationsare deployed,IrecommendstandardizingontheAlfrescoextensiondirectoryor,asinthisexample,a directorycalledworkflowswithinthat. Themimetypesettingistext/xmlwhendeployingtheprocessdefinition.xmlfile.Ifyouchooseto deploytheprocessasaPAR,setthelocationtothepathofthePARfileandsetthemimetypeto application/zip. TheredeployflagtellsAlfrescowhetherornotitshouldautomaticallyredeploytheprocessonstartup. Duringdevelopment,ifyouaredeployingyourprocessesviaSpringyouprobablywantthistobesetto true.Onceyougettoproduction,setittofalsetoavoidneedlesslycreatingnewversionsoftheprocess definitioneverytimetheserverisrestarted. Thereareotherdeploymentoptions:jBPMshipswithanAnttaskcalleddeploypar,thejBPM console(moreonthatlater)canbeused,andprocessescanbedeployedprogrammaticallyusingthe jBPMAPI.Thisarticlewon'tcoveranyofthesealternatives,butit'snicetoknowtheyarethereifyou needthem. Youmaybewonderingwhathappenstorunningworkflowinstanceswhenanewversionofthe processdefinitionischeckedin.TheansweristhatjBPMhandlesthatitmakessurethatrunning workflowscontinuetorunwiththeiroriginalprocessdefinition.Allnewworkflowswillusethemost currentprocessdefinition.

WiringaprocesstotheAlfrescoUI
Sofarwe'vetalkedaboutthedefinitionofworkflow,specificsaroundthejBPMengine,andprocess deploymentbutwehaven'taddressedhowtoexposeaprocesstoAlfrescowebclientusers. Forthosefamiliarwithextendingthecontentmodelthestepsforintegratingacustomworkflowwith theAlfrescowebclientUIwillbeveryfamiliar.Theprocessisnearlyidentical.Atahighlevelit consistsofthefollowing:

Defineacontentmodelforyourworkflowinwhichworkflowtasksmaptocontenttypes. AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page19of49

ecmarchitect.com

Updatewebclientconfigcustom.xmltotellAlfrescohowtoexposetheprocessmetadatato thewebclientuserinterface. Externalizethestrings.

Wedon'tneedtorehashthedetailsofcustomcontentmodelshereI'llassumeyoualreadyknowhow toextendAlfresco'scontentmodel.IfthesearenewconceptstoyouIrecommendyoutakealookat someoftheresourcescitedintheMoreInformationsectionattheendofthisarticle.

Defineaworkflowspecificcontentmodel
Theworkflowspecificcontentmodeldefinesthedatastructurefortheprocess.Workflowmodelsuse thesamefundamentalbuildingblockstypes,properties,aspects,andassociationsasnormal Alfrescocontentmodeldefinitions.Infact,ifyoualreadyhaveacustommodel,youcandefineyour workflowspecificmodelinthesamecontentmodelXMLfile,althoughtoreduceconfusion,I recommendyoukeepyourcontenttypesseparatefromyourworkflowtypesbyusingatleasttwo differentmodelfiles. Whatisthepurposeoftheworkflowspecificmodel?Thinkofitlikeanyothercontentmodel.Custom contentmodelsareusedtodefinethemetadatawewanttocaptureaboutapieceofcontent.The metadata(properties)aregroupedintotypesandaspects.Byvirtueofdefiningthesepropertiesaspart ofthecontentmodel,Alfrescotakescareofpersistingthedatatotheunderlyingdatabase. Workflowmodelsfunctioninthesameway.Supposeyouhaveaprocessinwhichthreedifferent departmentsareinvolvedinanapprovalprocess.Maybeyou'dliketheworkflowinitiatortobeableto definewhichofthosedepartmentsarerequiredapproversandwhichareoptionalorFYIreviewers. Aworkflowmodelwoulddefinehowthatinformationisgoingtobestored. Asinothercontentmodels,youdon'thavetostartfromscratch.Alfrescoshipsoutoftheboxwith someworkflowspecifictypesalreadydefined.Therearetwomodeldefinitionfilesrelatedtothis.One iscalledcalledbpmModel.xml.ItresidesinyourAlfrescowebapplicationrootunderWEB INF/classes/alfresco/model.TheotheriscalledworkflowModel.xmlanditresidesunderWEB INF/classes/alfresco/workflow. ThebpmModelfilecontainsthelowestlevelworkflowclassessuchasthebasedefinitionforalltasks andthedefaultstarttask.Italsocontainsimportantaspectssuchasasetofassigneeaspectsthat defineassociationsbetweentasksandusersorgroups. AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page20of49

ecmarchitect.com
TheworkflowModelfilecontainsthecontentmodelfortheoutoftheboxprocessdefinitions.This modelfileoffersalotofpotentialforreuseinyourcustomprocesses.Forexample,ifyourprocess startsbyallowingthesubmittertospecifyalistofseveralpeopletoreceiveatask,youcouldusethe submitParallelReviewTask.Ifyouwanttobaseanapprovalonthepercentageofindividualswho approveatask,youcanusethesubmitConcurrentReviewTask.Ofcoursejustlikeanymodelyouare freetousetheseasis,extendthem,ornotusethematall. Whenusersinteractwiththeworkflowviathewebclient,Alfrescowillusetheworkflowcontent modelandthewebclientconfigcustom.xmlfiletofigureoutwhatmetadatatoexposetotheUIand howtopresentitjustasitdoeswhenviewingcontentproperties.Alfrescousesthenameofthe workflowtasktofigureouttheappropriateworkflowcontenttype.So,alltasksinwhichthereare Alfrescowebclientuserinteractionsmustbegivenanamethatcorrespondstothenameofa workflowcontenttype. Considerthisprocessdefinitionsnippet:
<startstatename="start"> <taskname="scwf:submitGroupReviewTask"swimlane="initiator"/> <transitionname="transToAddAspect"to="addAspect"/> </startstate>

Thesnippetshowsastartstateofaprocesswithataskassignedtotheinitiator.Thetasknamemust matchacorrespondingworkflowcontenttype.Lookinginthecustomworkflowcontentmodelfilewe findthematchingtypedefinition:


<typename="scwf:submitGroupReviewTask"> <parent>bpm:startTask</parent> <mandatoryaspects> <aspect>bpm:groupAssignee</aspect> </mandatoryaspects> </type>

Thetypeisachildofbpm:startTaskanddeclaresamandatoryaspect.Inthisparticularcase,thetype willkeeptrackofthegrouptheinitiatorpickswhensubmittingtheworkflow.Aswimlanewithinthe processdefinitioncanthenreadtheselectedgroupandpassthattotheassignmentclass.


<swimlanename="reviewer"> <assignmentclass="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment"> <pooledactors>#{bpm_groupAssignee}</pooledactors> </assignment>

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page21of49

ecmarchitect.com
</swimlane>

Notetheuseoftheunderscoretoseparatethenamespacefromthepropertyname.

Updatewebclientconfigcustom.xml
ThenextstepistotellAlfrescohowtodisplaytheprocessmetadata.Thisworksexactlylikecustom contenttypes.Continuingtheexamplewejustlookedat,weneedtoexposethegrouppickertothe webclientsotheinitiatorcanfindandselectagroup.Thesnippetbelowshowshow.
<configevaluator="nodetype"condition="scwf:submitGroupReviewTask" replace="true"> <propertysheet> <separatorname="sep2"displaylabelid="users_and_roles"component generator="HeaderSeparatorGenerator"/> <showassociationname="bpm:groupAssignee"/> </propertysheet> </config>

Externalizethestrings
Thefinalstepistoexternalizethestringsusedtodisplaythingsliketheworkflowtitleanddescription thatshowupintheStartAdvancedWorkflowdialog,andtitlesanddescriptionsforindividualtasks. Theformatoftheidentifiersforthesestringsfollowaspecificformat.Lookatthesnippetbelowasan example:
#scWorkflowModelrelatedstrings scwf_workflowmodel.type.scwf_submitGroupReviewTask.title=StartSCWebReview scwf_workflowmodel.type.scwf_submitGroupReviewTask.description=SubmitSCWeb documentsforreview&approvaltoagroupofpeople scwf_workflowmodel.type.scwf_reviewTask.title=SCWebReview scwf_workflowmodel.type.scwf_reviewTask.description=Reviewdocumentsfor publicationtotheSCWeb scwf_workflowmodel.type.scwf_approvedTask.title=ContentApproved scwf_workflowmodel.type.scwf_approvedTask.description=ContentApprovedfor publicationtotheSCWeb scwf_workflowmodel.type.scwf_rejectedTask.title=ContentRejected scwf_workflowmodel.type.scwf_rejectedTask.description=Contentmustberevised beforebeingpublishedtotheSCWeb

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page22of49

ecmarchitect.com
#processdefinitionrelatedstrings scwf_submittoscweb.workflow.title=SubmittoSCWeb scwf_submittoscweb.workflow.description=ReviewandapproveSCWebcontent scwf_submittoscweb.node.start.transition.transToAddAspect.title=SetSCWeb properties scwf_submittoscweb.node.start.transition.transToAddAspect.description=Systemsets SCWebproperties scwf_submittoscweb.node.addAspect.transition.transToReview.title=Review scwf_submittoscweb.node.addAspect.transition.transToReview.description=Review priortopublish

Itendtothinkofthesepropertiesasbelongingtotwogroups.Onegroupisthesetofmodelrelated properties.Thesepropertiesexternalizethestringsintheworkflowcontentmodel.Theotheristheset ofprocessrelatedproperties.Thesepropertiesexternalizethestringsusersseewhentheyareworking withtheprocess(theworkflowtitle,theworkflowhistory,etc.).

Implementationsummary
We'vecoveredalotofgroundsofar.Thefollowingsummarizestheadvancedworkflow implementationsteps: 1. ModeltheprocessusingthejBPMProcessDesigner.Justgettheprocessrightdon'tworry aboutnodenames,events,oractionsjustyet. 2. AddlogicusingBeanshellexpressions,AlfrescoJavaScript,orJavaclasses. 3. Defineaworkflowcontentmodel.Ifyouuseanewcontentmodelfile,remembertoupdatethe custommodelcontext.xmlfiletopointtothenewcontentmodeldefinitionXMLfile. 4. Updatewebclientconfigcustom.xmltoexposeworkflowtaskstotheAlfrescowebclient. 5. Create/updateaworkflowspecificpropertiesfiletoexternalizethestringsinboththeworkflow modelandtheprocessdefinition. 6. Deploytheprocessdefinitionusingeitherthedeploymenttaboraspringbeanconfigfile. Atthispointyouknowenoughaboutadvancedworkflowstobedangerous.Let'sworkthroughan exampletoputsomeofthisnewknowledgetowork.

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page23of49

ecmarchitect.com
SomeCoWhitepapersubmissionexample
ThisexamplecontinuestheSomeCoexamplethatwe'velookedatduringthepastseveralAlfresco Developerarticles.SomeCoisgoingtouseAdvancedWorkflowstorouteWhitepapersforapproval beforebeingflaggedforpublicationonthewebsite.Thenextsectiondescribestheprocess.

Businessprocessdescription
AnyonethatcanlogintoAlfrescocansubmitawhitepaperforpublicationonthewebsite.Theonly informationthesubmitterneedstospecifyistheemailaddressofanexternalthirdpartyreviewer,if applicable.Moreonthatshortly. ThewhitepaperneedstobereviewedbytheEngineeringteamaswellastheMarketingteam.Itdoesn't matterwhoontheteamdoesthereviewSomeCowantstonotifyeachteamandthenletone representativefromeachteamownthereviewtask.Eitherteamcanrejectthewhitepaper.Ifrejected, thepersonwhosubmittedthewhitepapercanmakerevisionsandresubmit.Ifbothteamsapprove,the whitepapermovesontothenextstep. Somewhitepapersneedtobereviewedbyanexternalthirdparty.Thethirdpartywon'tactuallylogin toAlfrescothey'llgetanemailandclickalinktoapproveorrejectthewhitepaper.Ifthethirdparty doesn'tdoanythinginacertainamountoftime,thewhitepapershouldbeautomaticallyapproved.

Highlevelsteps
Alright.We'regoingtoimplementthisprocessinfourmajorsteps.Here'salookatthemajorstepsand therespectivesubsteps: 1. Implementthebasicflowandworkflowuserinterface 1. LayouttheprocessusingtheJBossjBPMGraphicalProcessDesigner. 2. Configureswimlanesandaddtasknodeswithappropriateassignments. 3. Adddecisionlogic. 4. Implementtheworkflowcontentmodel,theworkflowclientconfiguration,andthe workflowproperties. AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page24of49

ecmarchitect.com
5. Deployandtest. 2. Implementwebscriptsandactionsforexternalthirdpartyintegrationandotherbusinesslogic 1. Executeanactiontoaddthesc:webableaspecttothewhitepaperandsettheproperties appropriately. 2. Writeawebscripttohandleapproval/rejectionviaHTTP.Thelogicneedstograbthe workflowIDandthensignalthenodewiththeappropriatetransition. 3. WriteajBPMactionclassthatsendsanotificationtothethirdpartyemailaddress. 4. Deployandtest. 3. Addatimertothethirdpartytask 1. AddatimertotheThirdPartyReviewtasksothatifthethirdpartydoesn'trespondina timelyfashionthetaskwillautomaticallyapprove. 2. Deployandtest. 4. ConfiguretheworkflowsfordeploymentuponstartupviaSpring. Nowthatyouknowwherewe'reheadedatahighlevel,let'sgetintothedetails.

Step1:Implementthebasicflowandworkflowuserinterface
Layouttheprocess I'mgoingtofollowtheextensionconventionandplacemyworkflowinafilecalled processdefinition.xmlinafoldercalledalfresco/extension/workflows/publishwhitepaper.It definitelyhelpstheGPDifeachworkflowresidesinitsownfolder. Speakingofwhich,I'mgoingtoassumeyouarealsousingtheGPD.Ifyoudon'twantto,that'sfine. JustcreatethefolderstructureImentionedaboveandcreatetheemptyXMLfile.Ifyouaren'tusing theGPD,skiptherestoftheLayouttheprocessstepandmoveontoSwimlanes. UsingtheGPDDiagramtabandthedescriptionofthebusinessprocess,layouttheprocessasfollows:

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page25of49

ecmarchitect.com

Hereareacoupleofthingstonoteaboutthediagram.First,thereasonthetransitionlabelsbetweenthe EngineeringReviewandMarketingReviewtasknodesandtheJoinarehardtoreadisbecausethere aretwotransitionsforeachandtheGPDoverlaysthem.SoeachReviewtasknodehastwoleaving transitionsoneforapproveandoneforreject. Next,noticeI'venamedmost,butnotall,ofmytransitions.Anytransitionleavingatasknodeshould belabeledbecauseahumanisgoingtoseethat(oritsexternalizedequivalent)intheUI.Everywhere elseitisconvenientifthetransitionshavenamesbutitisn'trequired. Finally,don'tspendtoomuchtimemakingthediagrampretty.GPDhasanannoyinghabitof scramblingthediagramfromtimetotime. Swimlanes Noweditthesourceofprocessdefinition.xml.First,let'sfixtheprocessdefinitionelement.Bydefault, thexmlnsattributeisblankandthenamewillcontainwhateveryouspecifiedwhenyoucreatedthe process(ifyouusedNewJBossjBPMProcessDefinitioninEclipse).Theseneedspecificvaluesto workwithAlfresco.Updatethemasfollows:
<processdefinitionxmlns="urn:jbpm.org:jpdl3.1"name="scwf:publishwhitepaper">

Thenamehasanamespaceonitbecausewe'regoingtoexternalizeitandwedon'twantittoclashwith otherworkflownames.I'musingthenamespaceoftheworkflowcontentmodelwewillcreatealittle AlfrescoDeveloper:AdvancedWorkflows


ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page26of49

ecmarchitect.com
later. Nowdropintheswimlanes.Weneedthebuiltininitiatorswimlanewetalkedaboutearlierplusone forMarketingandoneforEngineering.Theoutoftheboxprocessesshowyouhowtouseapickerto lettheinitiatorspecifyauseroragroup.We'regoingtohardcodeAlfrescogroupsbecauseweknow whichgroupsneedtobeassignedtotheswimlanesthere'snoreasontomaketheinitiatorpickinthis case. Also,we'regoingtousepooledactorsbecausethebusinessprocessisthattheentireteamneedstoget ataskwithonepersontakingownershipofandcompletingthattask. Addtheswimlanestothestartoftheprocessdefinition.
<swimlanename="initiator"/> <swimlanename="marketing"> <assignmentclass="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment"> <pooledactors>#{people.getGroup('GROUP_marketing')}</pooledactors> </assignment> </swimlane> <swimlanename="engineering"> <assignmentclass="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment"> <pooledactors>#{people.getGroup('GROUP_engineering')}</pooledactors> </assignment> </swimlane>

TheswimlanesusetheAlfrescoAssignmentclasstoassigntheactor.Inthiscasewe'reusingan expressionthatleveragestheAlfrescopeopleobjectbecauseweneedtheactortobeareferencetothe groupobject,notjustastringcontainingthegroupname. Addtaskstotasknodes Ourprocesshasfourtasknodesandastartstatenode.Eachoftheseneedatask.Itisthetaskthatgets assignedtoaswimlane.Asmentionedearlier,tasknameswilleventuallymatchuptonamesoftypesin ourworkflowcontentmodelsotheyareprefixedwiththenamespacewe'regoingtouseforthe workflowcontentmodel.Thetablebelowshowsthetasknodes,tasks,andassignments. Node start TaskName scwf:submitReviewTask SwimlaneAssignment initiator

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page27of49

ecmarchitect.com
MarketingReview EngineeringReview ThirdPartyReview Revise scwf:marketingReview scwf:engineeringReview scwf:thirdPartyReview scwf:revise marketing engineering initiator initiator

TheresultingjPDLforeachofthenodesabovelookslikethis:
<startstatename="start"> <taskname="scwf:submitReviewTask"swimlane="initiator"/> <transitionname=""to="Submit"></transition> </startstate> <tasknodename="MarketingReview"> <taskname="scwf:marketingReview"swimlane="marketing"/> <transitionname="approve"to="join1"></transition> <transitionname="reject"to="join1"></transition> </tasknode> <tasknodename="EngineeringReview"> <taskname="scwf:engineeringReview"swimlane="engineering"/> <transitionname="approve"to="join1"></transition> <transitionname="reject"to="join1"></transition> </tasknode> <tasknodename="ThirdPartyReview"> <taskname="scwf:thirdPartyReview"swimlane="initiator"/> <transitionname="approve"to="Approved"></transition> <transitionname="reject"to="Revise"></transition> </tasknode> <tasknodename="Revise"> <taskname="scwf:revise"swimlane="initiator"></task> <transitionname="submit"to="Submit"></transition> <transitionname="done"to="end1"></transition> </tasknode>

YoumaybewonderingwhytheThirdPartyReviewisatasknode.TheThirdPartyReviewisgoingto beassignedtosomeoneexternaltothesystemwhowillapproveorrejectthetaskviaemail.So, technically,thisshouldbeastatenodeinsteadofatasknode.Infact,that'showIoriginally AlfrescoDeveloper:AdvancedWorkflows


ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page28of49

ecmarchitect.com
implementedit,but,unfortunately,Alfresco'simplementationofjBPMtimersonlyworksfortasksin thecurrentrelease1.Thebrightsideisthatiftheinitiatorgetstiredofwaitingforthethirdpartybefore thetimerrunsout,theycanapprovethetaskonbehalfofthethirdparty. Decisionlogic Theprocessdefinitionhastwodecisions.Onedecisionfiguresoutifallrequiredapprovalshavebeen obtained.Ifso,theprocesscontinues.Ifnot,theinitiatorgetsachancetomakerevisions.Theother decisionisusedtodetermineifathirdpartyreviewisrequiredbasedonwhetherornottheinitiator providedanemailaddress. Theseareprettyeasydecisionstomakebasedonprocessvariables.FortheAllApproveddecision, wecanincrementacounterwhentheprocessfollowsanapprovetransition.Ifthecounterisequalto 2,weknowwereceivedbothapprovals. Weneedtobecarefulthatweinitializethecounterto0becauseit'spossiblethatawhitepapermaygo throughseveralreviewcycles.TheSubmitnodegivesusaconvenientplacetodothat:
<nodename="Submit"> <eventtype="nodeenter"> <script> <variablename="approveCount"access="read,write"/> <expression> approveCount=0; </expression> </script> </event> <transitionname=""to="fork1"></transition> </node>

Nowweneedtoincrementthecounterwhentheapprovetransitionistaken.Let'slookatthe EngineeringReviewasanexample.Wecanmodifytheapprovetransitionwithalittlescriptthat incrementsthecounter:


<tasknodename="EngineeringReview"> <taskname="scwf:engineeringReview"swimlane="engineering"/> <transitionname="approve"to="join1"> <script> <variablename="approveCount"access="read,write"/> <expression> approveCount=approveCount+1; 1 http://issues.alfresco.com/browse/AR1879

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page29of49

ecmarchitect.com
</expression> </script> </transition> <transitionname="reject"to="join1"></transition> </tasknode>

IfweaddthesamescripttotheapprovetransitionforMarketingReviewaswell(notshown),our decisioncanconditionallytransitionbasedonthecounter:
<decisionname="AllApproved"> <transitionname="reject"to="Revise"></transition> <transitionname=""to="ThirdParty"> <condition>#{approveCount==2}</condition> </transition> </decision>

Notethatthefirsttransitiondoesn'thaveacondition.Itwillbeusedasthedefaultiftheconditionis notmet. FortheThirdPartydecisionwe'lldosomethingsimilar.Inthiscasewe'regoingtocheckauser providedvalue.Becausethispropertywillbedefinedaspartoftheworkflowcontentmodel,it includesthescwfnamespace,justlikethetasknameswesetearlier.


<decisionname="ThirdParty"> <transitionname="tr2"to="Approved"></transition> <transitionname=""to="ThirdPartyReview"> <condition>#{scwf_reviewerEmail!=""}</condition> </transition> </decision>

Wedidn'tneedit,butifourdecisionwasmorecomplex,wecouldhaveusedaJavaclasstoimplement thedecisionlogic.Todothat,wewouldhaveusedahandlertagthatpointedtoaJavaclassthat implementedtheDecisionHandlerinterface.


<handlerclass="com.someco.bpm.SomeDecisionHandler"/>

Thehandlerclass'decide()methodwouldreturnthetransitiontotake.Forourneeds,though, expressionswereenough. Thefork,join,approved,andendnodesareallfineastheyarefornow.Ifyouelectednottousethe GPD,youcangetthemfromtheaccompanyingsourceifyouarefollowingalong. Workflowcontentmodel,UI,andprops

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page30of49

ecmarchitect.com
Nowlet'sintegratetheprocesswithAlfrescobydefiningthecontentmodelandupdatingtheclient configuration. Irecommendkeepingyournormalcontentmodelsseparatefromyourworkflowmodels.Sothefirst stepisupdatingsomecomodelcontext.xmlwithapointertothenewworkflowcontentmodelfile:
<beanid="extension.dictionaryBootstrap"parent="dictionaryModelBootstrap" dependson="dictionaryBootstrap"> <propertyname="models"> <list> <value>alfresco/extension/scModel.xml</value> <value>alfresco/extension/scWorkflowModel.xml</value> </list> </property> </bean>

Whileyou'reinthatfile,youmightaswellgoaheadandaddtheconfigfortheworkflowpropertiesfile we'regoingtocreateshortly:
<beanid="extension.workflowBootstrap"parent="workflowDeployer"> <propertyname="labels"> <list> <value>alfresco.extension.scWorkflow</value> </list> </property> </bean>

Next,createanewmodelfilethatmatchesthenameinthecontextXML(scWorkflowModel.xml).I'm goingtoleaveoutthenamespacedeclarationandimportsandjustshowthetypesandaspects.Check thesourceforthefullfile.


<modelname="scwf:workflowmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0"> <!namespacesandimportsomittedfromlisting> <types> <typename="scwf:submitReviewTask"> <parent>bpm:startTask</parent> <mandatoryaspects> <aspect>scwf:thirdPartyReviewable</aspect> </mandatoryaspects> </type>

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page31of49

ecmarchitect.com
<typename="scwf:marketingReview"> <parent>bpm:workflowTask</parent> <overrides> <propertyname="bpm:packageItemActionGroup"> <default>read_package_item_actions</default> </property> </overrides> </type> <typename="scwf:engineeringReview"> <parent>bpm:workflowTask</parent> <overrides> <propertyname="bpm:packageItemActionGroup"> <default>read_package_item_actions</default> </property> </overrides> </type> <typename="scwf:thirdPartyReview"> <parent>bpm:workflowTask</parent> <overrides> <propertyname="bpm:packageItemActionGroup"> <default>read_package_item_actions</default> </property> </overrides> </type> <typename="scwf:revise"> <parent>bpm:workflowTask</parent> <overrides> <propertyname="bpm:packageItemActionGroup"> <default>edit_package_item_actions</default> </property> </overrides> </type> </types>

There'sonetypeforeachtask.Thenameofeachtypematchesthenameofthecorrespondingtask. You'llnoticethateachtypeinheritsfromatypedefinedintheBPMcontentmodel.Ifyoulookatthe bpmModel.xmlfileyou'llseethatthebpm:startTaskhashelpfulpropertiessuchastheworkflow description,duedate,andpriority.

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page32of49

ecmarchitect.com
Thebpm:workflowTaskhasanassociationcalledbpm:package.Thebpm:packagepointstoa bpm:workflowPackagewhichistheaspectappliedtoacontainer(likeafolder)thatholdsthe documentsbeingroutedthroughaworkflow.Whenyouwritecodethatneedstoaccessthecontent beingroutedinaworkflowyoucangettoitthroughthebpm:packageassociation. Thebpm:packageItemActionGroupdefineswhatactionsareavailableforworkingwiththecontent intheworkflowatthatparticularstepintheprocess.Inourcase,wewanttheinitiatortobeableto changethecontentsoftheworkflowwhentheworkflowisstartedandwhenmakingrevisions,butwe don'twantthereviewerstobeabletoaddorremoveanythingtoorfromtheworkflow. Thestarttaskhasamandatoryaspectcalledscwf:thirdPartyReviewable.We'lldefinethataspectto containapropertywecanusetostorethethirdpartyreviewer'semailaddress:
<aspects> <aspectname="scwf:thirdPartyReviewable"> <title>SomecoThirdPartyReviewable</title> <properties> <propertyname="scwf:reviewerEmail"> <type>d:text</type> <mandatory>true</mandatory> <multiple>false</multiple> </property> </properties> </aspect> </aspects>

NowweneedtotellAlfrescohowtorenderthepropertiesintheworkflowmodel.Justlikeextending regularcontentmodels,wedothatthroughthewebclientconfigcustom.xmlfile.Iliketoputallof myworkflowrelatedconfigentriesatthebottomofthisfiletokeepthemseparate.


<!workflowpropertysheets> <configevaluator="nodetype"condition="scwf:submitReviewTask"replace="true"> <propertysheet> <separatorname="sep1"displaylabelid="general"component generator="HeaderSeparatorGenerator"/> <showpropertyname="bpm:workflowDescription"component generator="TextAreaGenerator"/> </propertysheet> </config> <configevaluator="nodetype"condition="scwf:marketingReview"replace="true">

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page33of49

ecmarchitect.com
<propertysheet> <separatorname="sep1"displaylabelid="general"component generator="HeaderSeparatorGenerator"/> <showpropertyname="bpm:description"component generator="TextAreaGenerator"readonly="true"/> <showpropertyname="bpm:comment"componentgenerator="TextAreaGenerator" /> </propertysheet> </config> <configevaluator="nodetype"condition="scwf:engineeringReview"replace="true"> <propertysheet> <separatorname="sep1"displaylabelid="general"component generator="HeaderSeparatorGenerator"/> <showpropertyname="bpm:description"component generator="TextAreaGenerator"readonly="true"/> <showpropertyname="bpm:comment"componentgenerator="TextAreaGenerator" /> </propertysheet> </config> <configevaluator="nodetype"condition="scwf:revise"replace="true"> <propertysheet> <separatorname="sep1"displaylabelid="general"component generator="HeaderSeparatorGenerator"/> <showpropertyname="bpm:description"component generator="TextAreaGenerator"readonly="false"/> <showpropertyname="bpm:comment"componentgenerator="TextAreaGenerator" /> </propertysheet> </config> <!addthirdpartyreviewablerelatedaspectpropertiestopropertysheet> <configevaluator="aspectname"condition="scwf:thirdPartyReviewable"> <propertysheet> <showpropertyname="scwf:reviewerEmail"displaylabelid="email"/> </propertysheet> </config>

YoucanseethatalthoughtheBPMmodeldefinesseveralproperties,I'monlychoosingtoexposethe workflowdescriptionandcommentpropertiesforthisparticularprocess.Thedescriptioniseditable onlywhensubmittingtheworkflowordoingarevisionandisreadonlyeverywhereelse. Thelaststepistoexternalizethestringsinourmodelandourprocess.Rememberthatearlierwe AlfrescoDeveloper:AdvancedWorkflows


ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page34of49

ecmarchitect.com
registeredaresourcebundlecalledscWorkflow.CreateafilecalledscWorkflow.propertiesandaddthe strings.Thefirstsetofstringstoaddhavetodowiththemodel:
#scWorkflowModelrelatedstrings scwf_workflowmodel.type.scwf_submitReviewTask.title=StartSCWebReview scwf_workflowmodel.type.scwf_submitReviewTask.description=SubmitSCWebdocuments forreview&approvaltoagroupofpeople scwf_workflowmodel.type.scwf_marketingReview.title=MarketingReview scwf_workflowmodel.type.scwf_marketingReview.description=Reviewdocumentsfor impactonSomeComarketingmessage scwf_workflowmodel.type.scwf_engineeringReview.title=EngineeringReview scwf_workflowmodel.type.scwf_engineeringReview.description=Reviewdocumentsfor technicalaccuracyandbestpractices scwf_workflowmodel.type.scwf_thirdPartyReview.title=ThirdPartyReview scwf_workflowmodel.type.scwf_thirdPartyReview.description=Thirdpartyreviews documentsasnecessary scwf_workflowmodel.property.scwf_reviewerEmail.title=Revieweremail scwf_workflowmodel.property.scwf_reviewerEmail.description=Thirdpartyreviewer emailaddress

Thefirstpartofeachkeymatchesthenameoftheworkflowcontentmodel.There'satitleanda descriptionentryforeachtypeandpropertyinourworkflowmodel. Next,tothesamefile,weaddtheprocessrelatedstrings:


#processdefinitionrelatedstrings scwf_publishwhitepaper.workflow.title=PublishWhitepapertoSCWeb scwf_publishwhitepaper.workflow.description=ReviewandapproveSCWhitepaper content scwf_publishwhitepaper.node.Marketing\Review.transition.approve.title=Approve scwf_publishwhitepaper.node.Marketing\ Review.transition.approve.description=Approvethischange scwf_publishwhitepaper.node.Marketing\Review.transition.reject.title=Reject scwf_publishwhitepaper.node.Marketing\Review.transition.reject.description=Reject thischange

Thisfileisfairlyredundantsoit'struncatedhere.Notethatthefirstpartofthepropertykeymatches thenamewegaveourprocessdefinition.Thevaluesfortheworkflow.titleandworkflow.description keyswillbewhattheuserseeswhensheclicksStartAdvancedWorkflowintheAlfrescowebclient. Theremainingtitlesanddescriptionsarethestringsshownwhensomeonemanagesatask. Deployandtest AlfrescoDeveloper:AdvancedWorkflows


ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page35of49

ecmarchitect.com
Whilewe'restilltweakingtheworkflow,it'shandytousetheGPDdeploymenttoolbecausewecan changetheprocessdefinitionwithoutarestart.Theexceptioniswhenthemodelchanges.Soforthis firsttest,wehavetorestartAlfrescotopickupthenewmodel,thenwecandeployusingGPD. Ifyouhaven'tdonesoalready,createagroupcalledengineeringandonecalledmarketing.Create acoupleoftestusersforeachgroup. DeploythecustomizationsandrestartAlfresco(SeeHowtodeployneartheendofthisarticleifyou needhelp).Ifeverythingstartscleanly,usetheDeploymenttabontheGPDtodeploytheprocess definition.Youdon'tneedtodoanythingotherthanmakesuretheDeploymentServerSettingsare correct(ServerDeployershouldbe/alfresco/jbpm/deployprocess). Tip:ChangethedefaultjBPMServerDeployerURLintheEclipsepreferencestoavoidhavingtore settheServerDeployerURLvalueeverytimeyouwanttodeploytheprocess. Createapieceoftestcontent.Makesureyou'veconfiguredpermissionssuchthatthemarketingand engineeringgroupshaveEditoraccessorhigher1.Then,clickStartAdvancedWorkflow.

1 Wehaven'tsetitupyet,butthelaststepintheprocessisgoingtobetorunanactionthataddsanaspectandsetsa property.Thereappearstobeabug(JiraTBD)inwhichAlfrescoJavaScriptexecutesusingthecredentialsofthelast assignedtasknode.IftheworkflowpathdoesnotgototheThirdPartyReviewandinsteadgoesdirectlytoApproved fromthejoin,thecredentialsofeithertheEngineeringorMarketinguserwillbeusedtoaddtheaspect.Thus,those groupsneedEditoraccessorhigher.

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page36of49

ecmarchitect.com

Youshouldseethenewlydeployedworkflowinthelistofavailableworkflows.

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page37of49

ecmarchitect.com
Provideadescription.Totestthethirdpartyreviewpath,specifyanemailaddress.Becausewehaven't setupthenotificationyetyoudon'thavetoworryaboutittryingtosendanemail.ClickFinishto launchtheworkflow. Loginasoneofyourtestusers.Becausewe'reusingpooledtasks,you'llneedtoaddadashlettoyour MyAlfrescodashboard.AfterconfiguringthedashboardtoincludetheMyPooledTasksdashlet, youshouldthenseethetask.

EithertakeownershipofthetasksothatyoucanseehowthetaskmovestoyourToDolistandgets removedoutoftheotherusers'inboxes(iftheusersaremembersofthesamegroup)orsimply Approvethetask. Intherealworld,you'drunseveraltestsyouhavetomakesureyoutesteverypossiblepaththrough theworkflow. Usingtheworkflowconsole Ifsomethinggoeswrongoryoujustwanttogetupcloseandpersonalwiththeexecutionofthe process,you'llneedtousetheworkflowconsole.Unfortunately,there'snotalinkintheUIforitjust yet,buttheURLishttp://localhost:8080/alfresco/faces/jsp/admin/workflowconsole.jsp.Thetable belowshowssomecommoncommandsandwhattheydo. Command
showworkflowsall useworkflow<workflowid>

Whatitdoes Showsallrunningworkflows. Makesallsubsequentcommandshappeninthe Page38of49

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

ecmarchitect.com
where<workflowid>issomethinglikejbpm$71 contextofthespecifiedworkflow.
showtransitions signal<pathid><transition>

Showsallleavingtransitions.

Signalsthetoken.Goodwhenyourworkflowis where<pathid>issomethinglikejbpm$71@ stuckonanodeorwhenyouwanttotakea andtransitionisthenameoftheleavingtransition transitionwithoutfoolingwiththetask youwanttotake.Leaveoffthetransitiontotake managementUI. thedefault.


descpath<pathid>

where<pathid>issomethinglikejbpm$71@
endworkflow<workflowid> showdefinitionsall undeploydefinition<workflowid>or

Dumpsthecurrentcontext.Greatfordebugging processvariables. Cancelsthespecifiedworkflow. Showsthecurrentdeployedworkflow

Undeploysthespecifiedworkflowandstopsany undeploydefinitionname<workflowname> workflowsrunningwiththatdefinition.The <workflowid>variantundeploysaspecific versionofaworkflow. Theseareasubsetofthecommandsavailable.TypehelpandclickSubmittoseethefulllistof commands. Otherdebugaidsincludeusinglogger.logstatementsinAlfrescoJavaScriptactions(with log4j.logger.org.alfresco.repo.jscriptsettoDEBUG)andusingSystem.outstatementsinnonAlfresco scriptblocks.WhenyoustartwritingJavaactionclassesanddecisionhandlersyoumayfindithandy tohookuptheEclipseremotedebuggeraswell. Ifallgoeswell,yourworkflowshouldcompletesuccessfully.Aftereachtestrunyoushouldseeno activeworkflowswhenyoudoashowworkflowsallontheworkflowconsole.

Step2:Implementwebscriptsandactions
Nowthatthebaseprocessisrunningandit'shookedintotheAlfrescoUI,it'stimetopimpitoutwith AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page39of49

ecmarchitect.com
somebusinesslogic. CallthesetwebactionintheApprovednode Let'sworkontheApprovednodefirstbecauseit'seasy.Whenawhitepaperisapprovedwewantto addthesc:webableaspecttoitandsettheisActiveandpublishedproperties.Youmayrecall fromthewebscriptarticlethatthesegetusedbythefrontendtodetermineifthewhitepapershouldbe shownonthewebsite.Ihappentohavearuleactionlyingaroundthataddstheaspectandsetsthe properties1,soallwehavetodoistellourprocesstoexecuteitviaAlfrescoJavaScript.Updatethe Approvednodeasfollows:
<nodename="Approved"> <transitionname=""to="end1"> <actionclass="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript"> <script> <variablename="bpm_package"access="read"/> <expression> varsetWebFlagAction=actions.create("setwebflag"); setWebFlagAction.parameters["active"]=true; for(vari=0;i&lt;bpm_package.children.length;i++){ setWebFlagAction.execute(bpm_package.children[i]); } </expression> </script> </action> </transition> </node>

ThisisastraightforwardpieceofAlfrescoJavaScriptthatexecutesthecustomactioncalledsetweb flagforeverypieceofcontentintheworkflowpackage.Theactionaddstheaspectandsetsthe propertiesappropriately. NoticeI'veplacedtheactiononthetransitioninsteadofasachildoftheApprovednodeitself.It's syntacticallycorrecttomovetheactionoutsideofthetransition(itthenbehaveslikeanodeenter event),butIfoundthattheactionwasgettingexecutedandthennotsignalingthenode.Withtheaction onthetransition,thenodeimmediatelytakesthedefaulttransitionandperformstheactionaspartof


1 I'vecoveredactionsinanotherpaper.Unfortunately,itwasbeforetheSomeCoexamplewasbornsoitdoesn'tflow wellwiththerestoftheAlfrescoDeveloperarticles.I'llfixthatsomeday.Ifyouwanttoseehowtheactionisdefined, takealookinthesourceatsomecoactionscontext.xml,somecoactions.properties,and com.someco.action.executer.SetWebFlag.java

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page40of49

ecmarchitect.com
thatstepwhichisexactlywhatIneededittodo. PotentialGotcha!NoticethatI'mdeclaringthebpm_packagevariablepriortoaccessingitinmy expression.Thisisn'talwaysrequired,butIhaven'tbeenabletoreliablypredictwhenitisandwhenit isn't.ThisexactsamecodeworkedwithoutavariabledeclarationinpriorversionsofAlfresco,butas of2.1,thevariabletagdeclaringbpm_packageseemstoberequired.With2.1,Alfrescoupgradedto version3.2ofjBPMsothatmaybethecauseofthechangeinbehavior.Regardless,it'sprobably alwaysbesttomakethedeclaration. That'sallweneedtodofortheApprovednode.Nowlet'sworkontheThirdPartyReview. Implementtheexternalthirdpartyreview Somedaytherewillbeanoutoftheboxmechanismforexposingbusinessprocessestoexternal parties.Untilthen,wecanrollourownusingtheoutoftheboxmailactionandwebscripts.Thereare twopiecesrequiredtomakethiswork.ThefirstpartisthatwhenthetokenarrivesintheThirdParty Reviewnode,wewanttosendanemailtothethirdpartywithapproveandrejectlinks.The recipientwillopentheiremailandclickoneithertheapprovelinkortherejectlink.Thesecondpartis thatthoselinkswillinvokeanAlfrescowebscriptthatsignalstheappropriatenode. Thismayseembackwards,butlet'sbuildthewebscriptthathandlesthelinksfirst,thenbuildthe assignmentclassthatsendstheemailnotification. We'vecoveredtheWebScriptframeworkinapreviousarticle(SeeMoreInformation)solet'sjust lookattheJavaclassthatactsasthewebscriptcontroller.Here'stheexecuteImpl()method:
protectedMap<String,Object>executeImpl(WebScriptRequestreq,WebScriptStatus status){ Stringid=req.getParameter("id"); Stringaction=req.getParameter("action"); if(id==null||action==null){ status.jsSet_code(400); status.jsSet_message("Requireddatahasnotbeenprovided"); status.jsSet_redirect(true); } workflowService.signal(id,action); Map<String,Object>model=newHashMap<String,Object>();

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page41of49

ecmarchitect.com
model.put("response",Success); return model; }

TheclassgrabstheworkflowIDandtheactiontotake(whichisreallyjustatransitionname)andthen usestheworkflowservicetosignalthenode.So,forexample,ifsomeoneweretopostthisURL: http://localhost:8080/alfresco/service/someco/bpm/review?id=jbpm$89@&action=approve theJavaclasswouldsignalthenodeidentifiedbyjbpm$89@withtheapprovetransition1. ThesecondpiecetotheThirdPartyReviewissendingtheemailtothethirdparty.Thereisanoutof theboxmailaction,andyou'vealreadyseenhowtocallanactionfromaworkflowusingAlfresco JavaScript,butwe'vegotafewthingstotakecareofotherthansimplysendinganemail,solet'swrite acustomactionclass. Createanewclasscalledcom.someco.bpm.ExternalReviewNotificationthatextends JBPMSpringActionHandler.Weneedtobuildanemailthathastwolinksoneforapproveandone forrejectthatrepresentthetwopossibletransitionsoutoftheThirdPartyReviewnode. TheURLfortheBPMwebscriptwejustimplementedcontainsthepathIDthatneedstogetsignaled. ThepathIDisanAlfrescoconceptthatIequatetojBPM'stoken.Itisastringcreatedby concatenatingtheworkflowengineidentifier(jbpm)withthejBPMprocessinstanceIDwhichwe cangetfromthejBPMAPI. Withthatinformation,wecanimplementtheexecute()methodoftheExternalReviewNotification actionclassasfollows:
publicvoid execute(ExecutionContextexecutionContext)throwsException{ Stringrecipient=(String)executionContext.getVariable( ExternalReviewNotification.RECIP_PROCESS_VARIABLE); StringBuffersb=newStringBuffer(); sb.append("Youhavebeenassignedtoatasknamed"); sb.append(executionContext.getToken().getNode().getName()); sb.append(".Taketheappropriateactionbyclickingoneofthelinks below:\r\n\r\n"); 1 ThewebscriptconfigurationthatmapstheURLtothecontrollerandviewresidesin alfresco/extension/templates/webscripts/com/someco/bpm.Thecontrollerclassiscom.someco.scripts.GetReview.

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page42of49

ecmarchitect.com
ListtransitionList=executionContext.getNode().getLeavingTransitions(); for(Iteratorit=transitionList.iterator();it.hasNext();){ Transitiontransition=(Transition)it.next(); sb.append(transition.getName()); sb.append("\r\n"); sb.append("http://localhost:8080/alfresco/service/someco/bpm/review?id=jbpm $"); sb.append(executionContext.getProcessInstance().getId()); sb.append("@"); sb.append("&action="); sb.append(transition.getName()); sb.append("\r\n\r\n"); } ActionmailAction=this.actionService.createAction(MailActionExecuter.NAME); mailAction.setParameterValue( MailActionExecuter.PARAM_SUBJECT, ExternalReviewNotification.SUBJECT); mailAction.setParameterValue(MailActionExecuter.PARAM_TO,recipient); mailAction.setParameterValue( MailActionExecuter.PARAM_FROM, ExternalReviewNotification.FROM_ADDRESS); mailAction.setParameterValue(MailActionExecuter.PARAM_TEXT,sb.toString()); this.actionService.executeAction(mailAction,null); return ; }

Thefirstthingthemethoddoesisgrabtherecipientfromaprocessvariable.Iusedadifferentprocess variablethantheoneinourscwfnamespacebecauseIdidn'twanttocouplethisactionclasswitha specificworkflowmodel. Next,Istartbuildingthemessagebodywithastringbuffer.The executionContext.getToken().getNode().getName()callgrabsthenodename(ThirdParty Review). Ratherthanhardcodeapproveandreject,Iiterateovertheleavingtransitionstospitouttheir namesfollowedbytheappropriatewebscriptURL.Thatway,iftheprocesseverchanges,there'sa chancetheactionclasswon'tneedtobetouched. ThelastmajorblockofcodeusestheactionservicetoexecutetheAlfrescomailaction.Sure,you AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page43of49

ecmarchitect.com
couldusetheJavamailAPItodoityourself,butwhynotleveragethemailaction?Thatwayyoucan leveragethesameSMTPconfigurationsettingsasAlfresco. Thelastthingwehavetodoiscallthenewactionclassfromtheprocess.We'llusethenodeenter eventtotriggertheaction.UpdatetheThirdPartyReviewnodeasfollows:
<tasknodename="ThirdPartyReview"> <eventtype="nodeenter"> <script> <variablename="notificationRecipient"access="read,write"/> <variablename="scwf_reviewerEmail"access="read"/> <expression> notificationRecipient=scwf_reviewerEmail; </expression> </script> <actionclass="com.someco.bpm.ExternalReviewNotification"/> </event> ...

Inthefirstpartoftheevent,I'mreadingthereviewer'semailaddressfromthepropertypopulatedby theworkflowinitiatorintoavariablenamedastheactionclassexpects.Then,Icalltheaction. Deployandtest We'veaddedanewruleaction,awebscript,andajBPMactionclass.It'stimetodeployandtest.If youwanttotryoutthenotificationpiece,you'llneedaccesstoanSMTPserver.Fordevelopingand testinglocally,ApacheJamesworksgreat.IftheSMTPserveryouuseisrunningsomewhereother thanlocalhost,you'llhavetotellAlfrescoaboutitviathemail.hostsettingincustom repository.properties. Ifallgoeswell,youshouldgetanemailthatlookslikethis:

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page44of49

ecmarchitect.com

Ifyouclickonalink,itshouldsignalthetasknode.Youshouldseetheworkflowcontinueonthe appropriatepath. Warning:TheThirdPartyexampleisnotproductionready Iincludedthethirdpartyexampletoshowonetypeofwaitstate/asynchronousbehaviorinaprocess. It'sgotalongwaytogobeforeitcanbeusedinproduction.Ashortlistlistofobviousissuesincludes:

Theemailrecipientdoesn'tgetacopyofthedocumentsbeingreviewed.Onewaytoaddress thiswouldbetohavethenotificationactionsendazipofthedocumentsintheworkflow package.Anotherwaywouldbetowriteadditionalwebscriptsorsendthemadownloadlink.I simplydidn'thavetimetoimplementthisandfigureditwasabitofftopicanyway. Thepersonclickingtheemaillinkdoesn'tneedtoauthenticatebecauseitusesthesession alreadyestablishedbythewebbrowserwhenyouloggedinasoneofyourtestusersto completethereviewstep.(Ahorriblehack,Iknow.SeepreviousTimeexcuse.)Inreallife, theJavacontrollerwouldhavetocreateitsownsessionasadminorsomeotheruserinorderto signalthenode.There'sanexampleofhowtodothisintheIntrotoWebScriptsarticle. It'dbereallyeasyforanunauthorizedpersontosignalanynodeinthesystembecausemy controllerclassdoesn'tdoanyvalidationwhatsoeverandthepathID'saresequential.Inreal life,you'dwanttocheckthat(1)thepersonmakingtherequestisthepersonassignedtothe task,(2)thatthetaskisstillactive,and(3)possiblyuseanadditionalsecuritymechanismlikea sharedsecretofsomekind.

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page45of49

ecmarchitect.com

TheemailbodyshouldprobablycomefromaFreemarkertemplate.Thatwayyoucouldreuse thenotificationclassinanynumberofprocessesanditsimplifiesemailbodymaintenance.

So,longstoryshort,feelfreetousethisidea,butrealizethatI'vecutcornersforbrevity'ssake.

Step3:Addatimertothethirdpartytask
Whatifyousentanemailtothethirdpartyandtheynevertookaction?Onewaytohandlethat problemiswithatimer.AlthoughjBPMhasbeenapartofAlfrescosincerelease1.4,timersdidn't startworkinguntil2.1theyhadtobetherefortheprepublishfunctionalityinWCM. Timersgetsetonanodeeitherusingthecreatetimertagorviathetimertag.Whenatimer expires,theprocesscantakeatransition,executeascript,orcallanaction.Inourcase,wejustwantto taketheapprovetransitionwhenthetimerexpiresandwriteamessagetothelog.Updatethe scwf:thirdPartyReviewtaskintheThirdPartyReviewnodeasfollows:
<taskname="scwf:thirdPartyReview"swimlane="initiator"> <timername="thirdPartyTimer"duedate="10minutes"transition="approve"> <actionclass="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript"> <script> logger.log("Thirdpartytimerexpired...approving"); </script> </action> </timer> </task>

I'vegotthetimersetfor10minutesbutyoucouldobviouslysetitforaslongorasshortasyouwish. Youcanalsoaddabusinessmodifierifyouwanttousebusinessdaysinsteadofcalendardays,for example.Settinganabsolutedateworksaswell.Theduedatecouldalsobetheresultofanexpression. TakealookattheoutoftheboxWCMworkflowforanexample. Deployandtest Addingatimerdoesn'trequirearestart.JustredeploytheprocessusingtheGPDthenstartanew workflow.Whenthetimerexpires,theprocessshouldcontinueasifsomeonesignaledtheapprove transition.

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page46of49

ecmarchitect.com
Step4:Configuretheworkflowsfordeployment
ThefinalstepintheexampleistoconfiguretheworkflowforautomaticdeploymentonAlfresco startup.Openthesomecomodelcontextfile.Thebeanthatweusedtoregistertheworkflowlabelscan beusedtodeployworkflows.Updateitwiththefollowing:
<propertyname="workflowDefinitions"> <list> <props> <propkey="engineId">jbpm</prop> <propkey="location">alfresco/extension/workflows/publish whitepaper/processdefinition.xml</prop> <propkey="mimetype">text/xml</prop> <propkey="redeploy">true</prop> </props> </list> </property>

Thedetailsonthepropelementshavealreadybeendiscussed.Thekeyisthatthelocationmatches thepathtotheprocessdefinitionfile.

Conclusion
YoushouldnowknowtheinsandoutsofimplementingadvancedworkflowsusingthejBPMengine embeddedwithinAlfresco.YouknowwhenAlfresco'sbasicworkflowswillsufficeandwhen advancedworkflowsaremoreappropriate.Wetalkedaboutprocessdefinitionsbeingacollectionof nodesconnectedbytransitions.Althoughyoudidn'tseeanexampleofthis,youknowthatyoucould createacustomnodetypeifyouhadto.And,younowknowhowtoaddbusinesslogictoworkflows usingexpressions,AlfrescoJavaScriptandJava. Wealsolookedtheoverallprocessaroundimplementingadvancedworkflows.Thenwedivedintothe detailsbywalkingthroughanexamplethatusedmanyofthedifferentnodetypesandbusinesslogic options.WeevenspicedthingsupabitbyexposingthebusinessprocesstoathirdpartyviaSMTPand HTTPwiththehelpofthewebscriptframework. Hopefully,thishassparkedsomeideasabouthowyoucanleverageAlfrescoandJBossjBPMinyour ownprojectsandhasgivenyousomeconcreteexamplesyoucanleverageinyourownprojectsgoing forward. AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page47of49

ecmarchitect.com
Deployingandtesting
Todeploythesamplecodeincludedwiththisarticle,allyouhavetodois: 1. Importtheadvancedworklfowarticleproject.zipfileintoEclipse.(Orjustexpanditonyour filesystem). 2. Changebuild.propertiestomatchyourenvironment. 3. RunthedefaultAnttask. ThedefaultAnttaskwillcompileallnecessarycode,JARitup,zipuptheJARandtheextensionsinto theappropriatefolderstructure,andthenunzipontopoftheAlfrescowebrootwhichdeploysthe custommodel,Springconfigfiles,webclientcustomizations,scripts,webscripts,andallotherassets totheappropriatedirectories. Incaseyouarecurious,myenvironmentis:

UbuntuGutsyGibbon MySQL5(withversion5.1.5oftheJDBCdriver) Java1.5.0_13 Tomcat5.5.17 Alfresco2.1.1Enterprise,WARonlydistribution JBossjBPMGraphicalProcessDesignerPlugin3.0.12 ApacheJames2.3.1(fortestingthirdpartynotificationviaSMTP)

Obviously,otheroperatingsystems,databases,andapplicationserverswillworkaswell.WebScripts andjBPMtimers,however,onlybecameavailablestartingwithAlfresco2.1.

Wheretofindmoreinformation

Thecompletesourcecodethataccompaniesthisarticleisavailableherefrom ecmarchitect.com. YoumayalsoenjoypreviousarticlesintheAlfrescoDeveloperseriesatecmarchitect.com: "IntrototheWebScriptFramework" ,October,2007. AlfrescoDeveloper:AdvancedWorkflows


ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page48of49

ecmarchitect.com
Implementingcustombehaviors ,September,2007. WorkingwithCustomContentTypes,June,2007. Developingcustomactions ,January,2007. Alfrescowikipagesrelatedtothistopic: WorkflowAdministration wikipage AlfrescoJavaScriptAPI wikipage Fordeploymenthelp,seetheClientConfigurationGuideandPackagingandDeploying ExtensionsintheAlfrescowiki. Forgeneraldevelopmenthelp,seetheDeveloperGuide. Forhelpcustomizingthedatadictionary,seetheDataDictionarywikipage. JBossjBPM TheJBossjBPMStarterKithasastandalonejBPMinstance,examples,and documentation.Ifyou'redoinganythingseriouswithadvancedworkflows,youshould checkitout. TheJBossGraphicalProcessDesignerisanEclipsepluginthatcanbeusedtocreate processdefinitionsgraphicallyandtodeployprocessestothejBPMinstancein Alfresco. TheStateofWorkflow isatechnicalarticlebyTomBaeyens,thefounderandleadof theJBossjBPMproject,aboutBPM,workflow,andtechnicalconsiderationsthatwent intothecreationofjBPM.

Abouttheauthor
JeffPottsistheEnterpriseContentManagementPracticeLeadatOptaros,a leadingOpenSourceandNextGenerationInternetconsultancy.Jeffhasfifteen yearsofexperienceimplementingcontentmanagement,collaboration,andother knowledgemanagementtechnologiesforavarietyofFortune500companies.Jeff livesinDallas,Texaswithhiswifeandtwokids.Readmoreatecmarchitect.com.

AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License

Page49of49

You might also like