Saturday 27 March 2010

Mystery behind Failed on Start (Retrying)

Few days back i wanted to check the behavior of a out of the box (OOTB) document approval when there are multiple approvers in MOSS 2007. I thought the task is simple enough and was all geared up. I started one of my MOSS 2007 VPC’s and opened up a site which i had created earlier. I configured the OOTB approval workflow for a document library which was already available there. The approval workflow was configured to start on creation/updation of any item.
I wanted to test out the workflow. I uploaded a document into the library and hoping for the workflow to kick start. Little that i knew, i was in for a shock!!!
The workflow failed with the status Failed to Start (Retrying). (Refer the below picture)
mossworkflowfailedtostartstatus
This got me wondering what has gone wrong. I am using a OOTB workflow without any modifications, why does it give this error. The workflow log doesn’t help much to understand the problem. (Refer the below picture)
mossworkflowfailedtostartworkflowhistory
The next obvious place to check for diagnosing the issue was the SharePoint logs in 12 hive folder. On checking the logs, i found there where a few entries for Workflow Infrastructure category in the log. The error read like this…
Load Workflow Class: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: The requested Performance Counter is not a custom counter, it has to be initialized as ReadOnly.     at System.Diagnostics.PerformanceCounter.Initialize()     at System.Diagnostics.PerformanceCounter..ctor(String categoryName, String counterName, String instanceName, Boolean readOnly)     at System.Workflow.Runtime.PerformanceCounterManager.CreateCounters(String name)     at System.Workflow.Runtime.Hosting.DefaultWorkflowSchedulerService.OnStarted()     at System.Workflow.Runtime.Hosting.WorkflowRuntimeService.HandleStarted(Object source, WorkflowRuntimeEventArgs e)     at System.EventHandler`1.Invoke(Object sender, TEventArgs e) at System.Workflow.Runtime.WorkflowRuntime.StartRuntime()     at Microsoft.SharePoint.Workflow.SPWinOeHostServices..ctor(SPSite site, SPWeb web, SPWorkflowManager manager, SPWorkflowEngine engine)     --- End of inner exception stack trace …..
This error was quite interesting to me. It looks like the OOTB workflow is creating some performance counters when the workflow starts and it is having some problems to create one thus giving an error Failed on Start.
When i was wondering why it was not able to find the performance counters, thanks to the blog post by Kiran really helped to figure out what’s going wrong. As pointed out in the blog post, there was some issue with the environment and for some reason Windows Workflow Foundation related performance counters were missing. This was basically creating the problem.
As directed in the blog post, I reinstalled .NET Framework 3.0 and associating performance counters with WF instances… Now the workflow was working properly… Wow!!!
However, I have absolutely no idea why those Performance counters went missing!!!
Technorati Tags: ,

Wednesday 24 March 2010

Assigning a task to multiple users in MOSS Workflow

I have been thinking of writing about this for quite a while now!!! Finally managed to sit down to write about the peculiar issue which we faced few weeks back in a Project.

Scenario

Business documents are created and shared using a document library in MOSS. The documents go through the approval process on creation/updating. A list of approvers is assigned. Document can be approved by any one of the approver.

Problem

The out of the box (OOTB) Approval workflow available in MOSS has the capability to add multiple approvers to an item added to document library or list. However it changes only the routing process of the approval workflow i.e. the approval task is to be sent to all the approvers (parallel) or task sent to one approver at a time (serial). (Refer the below picture)

MOSSworkflowApprovers

If we configure our workflow as parallel, then when a document or list item is created/updated, a separate task will be created for all the approvers. (Refer the below picture)

mossworkflowtasksootb

All the approvers have to approve the task for the document/list item to be approved.

However, in our scenario there should be only one task created irrespective of the number of approvers. Any one of the approvers can approve the task. This warranted a custom workflow solution to be built.

In a custom workflow we need to create a task which is assigned to multiple approvers. WF has the CreateTask activity which helps to create the task.

mosscustomworkflowpic1

MethodInvoking event of CreateTask activity is used to assign properties like assignedTo to the task which is created. (Refer the MethodInvoking event of CreateTask activity)

   1: private void createTaskAct_MethodInvoking(object sender, EventArgs e)
   2: {
   3:     try
   4:     {
   5:         using (SPSite site = new SPSite("http://madhu-win2k3:5000/Docs"))
   6:         {
   7:             using (SPWeb web = site.OpenWeb())
   8:             {
   9:                 TaskID = Guid.NewGuid();
  10:                 TaskProps = new SPWorkflowTaskProperties();
  11:                 TaskProps.Title = "Demo Task";
  12:                 TaskProps.AssignedTo = @"1;#MADHU-WIN2K3\Administrator;#15;#MADHU-WIN2K3\sharepointuser";
  13:                 //TaskProps.AssignedTo = web.SiteUsers[0].ID.ToString();
  14:                 TaskProps.Description = "test";
  15:                 TaskProps.ExtendedProperties["comments"] = comments;
  16:                 TaskProps.ExtendedProperties["instructions"] = instructions;
  17:             }
  18:         }
  19:  
  20:     }
  21:     catch (Exception ex)
  22:     {
  23:         Debug.WriteLine(ex);
  24:     }
  25: }

However, the CreateTask activity doesn’t support assigning the task to multiple users even though AssignedTo field of the Workflow Tasks list is changed to allow multiple selection (Refer the below Pic).

mossworkflowtasksassignedTo

Solution

One of the solution to the above problem was to have some other way to assign the task to multiple users since the CreateTask activity was not doing the job.

OnTaskCreated Activity to the rescue. OnTaskCreated activity provides a great way to tap into the task which has been been created and assign properties. The invoked event of the OnTaskCreated activity is used to assign the above said properties. (Refer the sample code for invoked event)

   1: private void onTaskCreated1_Invoked(object sender, ExternalDataEventArgs e)
   2: {
   3:     try
   4:     {
   5:         using (SPSite site = new SPSite("http://madhu-win2k3:5000/Docs"))
   6:         {
   7:             using (SPWeb web = site.OpenWeb())
   8:             {
   9:                 web.AllowUnsafeUpdates = true;
  10:                 SPList list = web.GetList("http://madhu-win2k3:5000/Docs/Lists/Tasks/AllItems.aspx");
  11:                 SPListItem item = list.Items.GetItemById(onTaskCreated1.AfterProperties.TaskItemId);
  12:                 item["Assigned To"] = @"1;#MADHU-WIN2K3\Administrator;#15;#MADHU-WIN2K3\sharepointuser";
  13:                 item.Update();
  14:             }
  15:         }
  16:     }
  17:     catch (Exception ex)
  18:     {
  19:         Debug.WriteLine(ex);
  20:     }
  21: }

With the above code it is now possible to assign the same task to multiple approvers. Thus any one of the approver can approve the task to make the corresponding document/list item approved.

However, for the above code to work it is necessary that the version settings for workflow tasks be disabled. Otherwise, we will get the following error “This task is currently locked by a running workflow and cannot be edited” when the task is approved or rejected.

Caveat

Caveat of the above approach is the version of the Workflow Tasks list has be disabled. This might not be possible in all scenarios.

Other Solutions

One of the other possible solution will be to create another column in the Workflow Tasks list which can allow multiple select to store “assigned to” users.

Another solution might be to create a field control to assign multiple users and use the field control to create a custom column in the Workflow Tasks list.

Technorati Tags: ,