Sunday, August 24, 2008

Fixing Process Instance XML

A colleague of mine dropped me an email asking about how to resolve a production issues. He has an InfoPath form where a destination user is selected in it. Then when it got to a point in the process where that field needed was used by the destination rule it failed. The reason was because the destination user had left the company and their Active Directory account has been deleted!

He needed to recover the process instance and did not want to tell the business users to start the ticket over again. We considered modifying the process code that was deployed but it was more of a hack. The only other solution was to modify the data in the database. We looked around the database, and were able to find the tables and fields where the XML was stored. However making any sort of changes in this manner would be unsupported by K2 plus we did not want to mess anything up since this is production.

The solution was to write a little snippet of code in a command line application to make a connection out to the server and modify the XML via the API. We went to the Process Overview report, got the process instance number, open the process instance, modified the XML, set it back into the process instance and updated it. The following is Joe Loftus's solution, nice, simple and supported…


using System;
using System.Collections.Generic;
using System.Text;

using SourceCode.Workflow.Client;
using System.Xml;

namespace FixK2InfoPathData
{
class Program
{
static void Main(string[] args)
{

//TODO: Replace Constants with command line args
//TODO: Add third argument which is a path to a repaired xml file to reset the process instance xmlfields value.

//Set to the correct Server Name
const string SERVER_NAME = "SERVER NAME";

//Set to the correct process instance ID
const int PROCESS_INSTANCE = 7;

//Create connection using current credentials (the creds must have access to the process)
Connection cn = new Connection();
cn.Open(SERVER_NAME);

//Open Process Instance
ProcessInstance pi = cn.OpenProcessInstance(PROCESS_INSTANCE);

//Get InfoPath xml data
string xoldData = pi.XmlFields[0].Value;

//fix InfoPath xml data
XmlDocument doc = new XmlDocument();
XmlNamespaceManager nsMgr;

doc.LoadXml(xoldData);

//configure Namespace manager
nsMgr = new XmlNamespaceManager(doc.NameTable);
nsMgr.AddNamespace("my", doc.DocumentElement.GetNamespaceOfPrefix("my"));

//Fix the offending elements here
doc.SelectSingleNode(
"//my:myFields/my:Approvers/my:ITTFinanceApprover1",
nsMgr).InnerText = "BlackPearlManager";

//Set the repaired InfoPath Xml back to the process instance
pi.XmlFields[0].Value = doc.OuterXml;

//Update the Process Instance
pi.Update();

cn.Close();
}
}
}

No comments: