I have a schema with a workflow assigned. I need that if the Performer belongs to a certain group it finishes the process and bypasses the workflow (ending with the Approval Status we have as the latest one: Live). I do this with the Event System (code below).
When I use a user that belongs to the group, then I go to the CMS create a component with a schema that has a workflow, then I click on "Save and Continue" it works and the component ends up in Live Approval status, and it's not in the workflow (if I click "Save" it still in the workflow.
My problem is that if I use Save and Checkin from CoreService from Java code it doesn't work and says item is in workflow. I added logs and when running it from the code it seems it's not entering into the event as it does when doing it from the CMS.
I have already read here but it didn't work. Restarted IIS, all SDL Services and shutdown COM+ too). I put this dll in a separate folder inside bin folder and only 1 time.
Any ideas?
public class WorkflowBypasser : TcmExtension
{
static readonly IList<string> WorkflowBypassingGroupNames = LibraryHelper.Helper.GetAppSetting(LibraryHelper.Helper.GetRunningFolder(Assembly.GetExecutingAssembly().CodeBase), "WorkflowBypassingGroupNames").Split(',').ToList();
static readonly string LiveApprovalStatusTcmUri = LibraryHelper.Helper.GetAppSetting(LibraryHelper.Helper.GetRunningFolder(Assembly.GetExecutingAssembly().CodeBase), "LiveApprovalStatusTcmUri");
public WorkflowBypasser()
{
this.Subscribe();
}
private void Subscribe()
{
this.EventSystem.Subscribe<Component, CheckInEventArgs>(OnComponentCheckIn, EventPhases.TransactionCommitted);
}
#endregion
private void OnComponentCheckIn(Component component, CheckInEventArgs args, EventPhases phases)
{
var xmlElement = component.ToXml();
var xmlNamespaceManager = new XmlNamespaceManager(new NameTable());
xmlNamespaceManager.AddNamespace("tcm", "http://www.tridion.com/ContentManager/5.0");
var activityInstanceNode = xmlElement.SelectSingleNode("//*[local-name()='ActivityInstance']", xmlNamespaceManager);
if (activityInstanceNode != null)
{
try
{
var activityInstanceId = activityInstanceNode.Attributes["xlink:href"].Value;
if (!IsValidActivityInstanceId(activityInstanceId))
{
return;
}
var activityInstance = new Tridion.ContentManager.Workflow.ActivityInstance(new Tridion.ContentManager.TcmUri(activityInstanceId), component.Session);
foreach (var performer in activityInstance.Performers)
{
foreach (var groupMembership in performer.GroupMemberships)
{
if (WorkflowBypassingGroupNames.Contains(groupMembership.Group.Title))
{
ProcessInstance wfProcess = activityInstance.Process.Session.GetObject(activityInstance.Process.Id.ToString()) as ProcessInstance;
ApprovalStatus status = new ApprovalStatus(new TcmUri(LiveApprovalStatusTcmUri), activityInstance.Process.Session);
var finishedProcess = wfProcess.ForceFinish(status);
return;
}
}
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
}
private bool IsValidActivityInstanceId(string activityInstanceId)
{
return !activityInstanceId.Equals("tcm:0-0-0");
}
}
UPDATE
I few things I noticed
1) If you click Save the workflow remains as Undefined 2) If you click Save checkin event is not fired 3) If you click Save and Close, checkin is fired 4) If you click Save and Close, checkin is fired but if you open the item without refreshing you don't see yet the Live Approval Status the component is in. 5) If you open the component after clicking Save and Close it doesn't show any workflow activity into it, but if you click on the refresh button on the containing folder and then refresh the component window, the workflow can be seen correctly as Live.
So it's like the refresh on the containing folder creates or launches the creation of the workflow activities, but I tried to call Reload on the component, on the OrganizationalItem of the component but none worked.
Java Code
path = componentPath(folder, name);
localizeIfShared(folder, schema, name, path);
sdl.checkOut(path, true, new ReadOptions());
IdentifiableObjectData iod = sdl.read(path, new ReadOptions());
if (iod instanceof ComponentData) {
if (StringUtils.isNotBlank(data)) ((ComponentData) iod).setContent(data);
if (StringUtils.isNotBlank(meta)) ((ComponentData) iod).setMetadata(meta);
}
sdl.save(iod, new ReadOptions());
sdl.checkIn(iod.getId(), true, StringUtils.joinIfNotBlank(" : ", "Updated", comment, new Date()), new ReadOptions());
result = SdlObject.asQualified(iod.getId(), SdlObjectType.Component);
UPDATE
As @RickPannekoek mentioned there was no need to call .XML().
This is the final version
var currentActivity = component.CurrentActivity;
if (currentActivity != null)
{
try
{
if (!IsValidActivityInstanceId(currentActivity.Id))
{
return;
}
foreach (var performer in currentActivity.Performers)
{
foreach (var groupMembership in performer.GroupMemberships)
{
if (WorkflowBypassingGroupNames.Contains(groupMembership.Group.Title))
{
ProcessInstance wfProcess = currentActivity.Process.Session.GetObject(currentActivity.Process.Id.ToString()) as ProcessInstance;
ApprovalStatus status = new ApprovalStatus(new TcmUri(LiveApprovalStatusTcmUri), currentActivity.Process.Session);
wfProcess.ForceFinish(status);
return;
}
}
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
component.ToXml()
and then obtaining data from the XML representation instead of getting it directly from the Component object?