Auto Publish a Page Upon Workflow Completion

I came across a requirement recently that needed a page to be published automatically when any component on it completed workflow. Here are some pointers if you need to do this as well.  Note, this tip is based on Tridion 2009, however, the lessons provided here may also apply to Tridion 2011.

Publishing From an Automatic Workflow Activity Won’t Help

Sending your page to the publishing queue from within an Automatic Activity won’t do any good since your item is still in workflow, and only the major version (i.e. the last approved version) gets published.  This makes perfect sense.  You don’t want to publish to your Live site items that are still in draft status.  

Although there is a way to publish using the latest version of the item.  You can set the activateWorkflow flag = true to take the latest minor version (including the one inside the workflow).  However, if you have other components in a page also going through workflow in their early draft states, you definitely don’t want them considered. So the activateWorkflow flag won’t be of help here.

  • Use the activateWorkflow=true to publish to Staging/Preview environment. Don’t use it for publishing to Live.
So, the component should be out of workflow when publishing is triggered, so naturally we turn to the Event System to do the auto-publishing, but which event?

Publishing From the Event System

The Tridion 2009 Event System has 2 event triggers that may suit us:
  1. OnProcessInstanceFinishPost
  2. OnActivityInstanceFinishPost

OnProcessInstanceFinishPost

You see the first one and you think “Bingo! this is going to be easy”.  Not so fast soldier.  This event only gets triggered when the system administrator explicitly kills the workflow process instance from the Workflow Management Process Instances window.  Upon normal completion of the workflow process instance it does not get fired.  I was extremely disappointed when I learned this.
Workflow administrator explicitly finishing process instance

The good thing is that it’s not the end of the world.  So we look upon the next available event.

OnActivityInstanceFinishPost

This event fires upon completion of each activity.  So we simply check that the activity instance this is being triggered for is the last activity in the flow.  So far so good…

The input parameter into this event is the ActivityInstance that just finished.  So now all we need to do is get the workflow item, i.e. the component that just finished being edited, and send it off to the publishing queue (assuming you have the default cascading publishing enabled that will trigger the publishing of the page(s) on which the component is included, and the actual page has been previously published [because the cascade publishing of a component only publishes a page if the page has been explicitly published]).  Well, you can hold your horses right there…

The way you would normally get the WorkItem object from the ActivityInstance is something like this:

<br />
Component comp = (Component)activityInstance.ProcessInstance.Item;<br />

This is works great for all activities, except… wait for it… the last one.  Upon completing the last activity the process instance is done, meaning that activityInstance.ProcessInstance.Item will throw a big fat Null Reference exception.

So how do you get the WorkItem of a process instance that no longer exists?  Here is how…

Turns out that the ProcessInstance in this case isn’t null, and one of the few properties we still have access to is its TCM ID.  However, other property that gets lazy loaded isn’t available.  Another interesting thing to know is that when a ProcessInstance completes it becomes a ProcessHistory item.

And the TCM ID of a ProcessInstance is the same as the TCM ID the ProcessHistory, with the exception of the type.  Here is what I mean:

ProcessInstance TCM ID:  tcm:XX-YY-131076
ProcessHistory TCM ID:    tcm:XX-YY-131080

The only difference is the type, 131076 for ProcessInstance and 131080 for ProcessHistory.

So in our OnActivityInstanceFinishPost event, we derive the ProcessHistory based on the ProcessInstance ID and then get our component workitem.

string processHistoryId =
  activityInstance.ProcessInstance.ID.Replace("131076", "131080");
ProcessHistory hist = (ProcessHistory)tdse.GetObject(processHistoryId, EnumOpenMode.OpenModeView);
Component comp = hist.Item as Component;

So now we can happily trigger publishing of the component: comp.Publish(…)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>