Professional Documents
Culture Documents
com
AlfrescoDeveloper:AdvancedWorkflows
November,2007
JeffPotts
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.
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)
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.
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.
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.
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<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>
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.
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
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
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>
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
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">
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>
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>
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>
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>
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>
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>
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>
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
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.
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>
AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License
ecmarchitect.com
where<workflowid>issomethinglikejbpm$71 contextofthespecifiedworkflow.
showtransitions signal<pathid><transition>
Showsallleavingtransitions.
where<pathid>issomethinglikejbpm$71@
endworkflow<workflowid> showdefinitionsall undeploydefinition<workflowid>or
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<bpm_package.children.length;i++){ setWebFlagAction.execute(bpm_package.children[i]); } </expression> </script> </action> </transition> </node>
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> ...
AlfrescoDeveloper:AdvancedWorkflows
ThisworkislicensedundertheCreativeCommonsAttributionShare Alike2.5License
Page44of49
ecmarchitect.com
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>
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:
Obviously,otheroperatingsystems,databases,andapplicationserverswillworkaswell.WebScripts andjBPMtimers,however,onlybecameavailablestartingwithAlfresco2.1.
Wheretofindmoreinformation
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