Stumbling Through

Join me as I stumble, bumble and fumble my way through some new developer technologies. We'll laugh, we'll cry, there may be a mouse tossed through a monitor, but in the end we will all hopefully learn something.
in

February 2008 - Posts

Stumbling Through: K2 [blackpearl] - Infopath Integration (Part II)

Previously, I identified a couple of specific technical problems that I'd like to stumble through solutions for.  One of the technical problems I described like this:

'Submitting one order form may spawn multiple processes that can be acted on simultaneously by different users to accomplish one final result.  How will we have one process split into many, passing along the common information necessary to the child processes?'

I suppose I will clarify this description a little bit before I jump into the solution.  One InfoPath form containing some common user-entered data starts the master process.  Submitting this form starts three other processes that have their own InfoPath forms that need the common information pre-populated from the first InfoPath form.  So, to do a proof of concept for this issue, we'll need a total of four InfoPath forms and four processes defined in a K2 workflow project (Master, Child1, Child2, Child3).  Let's start out with the InfoPath forms:

Create an InfoPath form named 'Master', and add two text fields that will represent the common data.  We can just call them 'Id' and 'Name':

image

Create the next three InfoPath forms named 'Child1', 'Child2' and 'Child3'.  You can put any other information you want in them, as long as you include the 'CommonFields' section as it was defined in the Master form:

image

Now that we have our InfoPath templates defined, we need to consume them in K2 Processes.  Start Visual Studio and create a new empty K2 project:

image

Add four processes to the project named 'Master', 'Child1', 'Child2' and 'Child3':

image

image

Let's start with defining each child process.  They will simply create a task list item pointing to their corresponding InfoPath form which will have the header somehow pre-populated with data entered in the Master form.  First things first, though, we need to integrate the process with its InfoPath form.  Drag out an InfoPath Integration process wizard and follow the steps necessary to integrate the InfoPath form and create a simple client event (I've blogged this process before if you get stuck, you can read it here, though that was blogged long before I semi-knew what I was doing).  Duplicate the process for all three child processes so that they look as simple as this:

image

Note that we did nothing with pre-populating the data in the InfoPath form yet, we'll tackle that later.  For now, we can move on to our Master process.  We'll need to integrate the Master InfoPath form with this process similarly to how we did it with the Child processes, the only difference being that we need to ensure that the Master form starts the process, by filling in this portion of the integration wizard:

image

This will make it so that any time this specific form is submitted, it will automatically start this Master process.  So now we come to the heart of the matter - how do we invoke the child processes all at once?  Thankfully, the developers of this product anticipated this very need and supplies a wizard that will make this challenge a breeze.  Drag out the 'IPC Event' wizard:

image

In the wizard, we'll need to specify which process to invoke.  Let's start out invoking our Child1 process.  It also asks us if it is Synchronous or Asynchronous - basically whether or not we need a response from this child process before we can continue.  In our case, we just want to kick off the process and we don't care what it does so we will chose Asynchronous:

image

We also have the ability here to specify a new folio, if we want the child folio to match something that we are gathering in the parent process.  Be warned, though, that this folio definition will be overridden by any folio definition in the Child process (defined in the InfoPath Integration wizard).  Clicking next brings us to a simple security question - who to call the process as.  Now normally, I would expect to use 'Integrated Windows' here so that the process is invoked by whomever invoked the Master process.  However, for reasons I don't yet understand, this never worked successfully for me and I've had to use the 'Impersonate Originator' option:

image

Clicking next again brings us to a screen that is very interesting to us, given the challenge we are trying to overcome.  It is asking us what data we want to pass to the child from the parent!  That is perfect!  Or is it... Let's see how it handles our specific request of passing the 'CommonFields' data from the Master form to the 'CommonFields' data of the child.  Add a new process field mapping:

image

Use the object browser to drill into our Master infopath form XML representation and select the 'CommonFields' section:

image

And drag it onto the Field Mapping form:

image

Now use the object browser via ellipsis next to the Child process field name to browse to the 'CommonFields' data in the Child InfoPath form:

image

And drag it onto the Field Mapping form... uh oh, it won't let us!  Looks like we are asking it to do something a little more complex than what it was designed for, which is understandable as moving one piece of xml between documents might not always be very straight forward, particularly when namespaces are involved.  Looks like we'll have to do some of this ourselves via code.  Bring up the Child Process object browser again, and add a new xml field called 'ParentCommonFields'.  We'll use that as the temporary container for the common field data:

image

Drag it onto the Field Mapping form:

image

Something else I learned the hard way about this process is that if you specify a portion of an xml document, as we did when we specified 'CommonFields' in the Master document, it will send the data as a list of field values as opposed to the XML.  As such, we'll just send the whole XML over and parse out the CommonFields section in the Child process logic.  So revisit the Parent field value and browse to the Master xml document:

image

Drag it onto the Field Mapping form:

image

Repeat this IPC event process for all three Child processes so your Master process looks like this in the end:

image

Now we need to revisit each Child process and add some logic to copy the parent common fields into the child common fields InfoPath xml.  The only way to do this is with some server side code, so drag out a new 'Default Server Event (Code)' wizard:

image

And connect it up before the InfoPath client event:

image

View the code of this Server Event (Right-Click - View Code - Event Item) and add a 'using System.Xml' to the top to make our XML references cleaner.  Now, what we need to do is load up a DOM with the Child InfoPath form XML so we can navigate to its 'CommonFields' section and replace it with the 'ParentCommonFields' value.  The caveat here is that the Parent Common Fields XML may have a different namespace associated with it, so we'll need to load that up in a DOM too so we can identify and replace any occurrences of an incorrect namespace:

XmlDocument docChild = new XmlDocument();

docChild.LoadXml(K2.ProcessInstance.XmlFields["Child1"].Value);

XmlNamespaceManager nsMgrChild = new XmlNamespaceManager(docChild.NameTable);

nsMgrChild.AddNamespace("my", docChild.DocumentElement.GetNamespaceOfPrefix("my"));

XmlDocument docParent = new XmlDocument();

docParent.LoadXml(K2.ProcessInstance.XmlFields["ParentCommonFields"].Value);

XmlNamespaceManager nsMgrParent = new XmlNamespaceManager(docParent.NameTable);

nsMgrParent.AddNamespace("my", docParent.DocumentElement.GetNamespaceOfPrefix("my"));

docChild.SelectSingleNode("//my:CommonFields", nsMgrChild).InnerXml = docParent.SelectSingleNode("//my:CommonFields", nsMgrParent).InnerXml;

K2.ProcessInstance.XmlFields["Child1"].Value = docChild.InnerXml.Replace(nsMgrParent.LookupNamespace("my"), nsMgrChild.LookupNamespace("my"));

Let's deploy this thing, and when it is done, we will visit the SharePoint list associated with our 'Master' form, add an item, and see if we get tasks generated for each 'Child' form.  Opening up those tasks should show the Master Common Field data in the header.  Don't forget to give yourself process start rights for the master and child processes via the Workspace!  If it doesn't work as expected or I glossed over an important detail, please leave me a comment and I'll try to help as best i can.

Posted: Feb 29 2008, 10:12 AM by tbyrne | with 2 comment(s)
Filed under:
Stumbling Through: K2 [blackpearl] - InfoPath Integration (Part I)

The K2 [blackpearl] product integrates very well with InfoPath, as any sales-pitch and pre-made tutorial will inform you.  I was very impressed with how easily I was able to use InfoPath as the user interface to my simple workflow processes, but I feel that every new technology looks good when you take it through its expected scenarios.  As such, what I am going to try and do for you in the next series of posts is describe my experiences implementing K2 [blackpear] InfoPath integration in the real-world, where the business requirements don't always exactly match the InfoPath integration tutorials.  What I hope for you to get out of this series is the scenarios where InfoPath integration may be more complex than it would seem on the surface, where it will be a quick-win, and some tricks I stumble through along the way to get over some of the hurdles that present themselves.

Here is some background on the project:

Users will be interfacing with SharePoint 2007 to create service request orders, which are sent to a service provider team for processing.  There are four distinct services with their own order forms, and each of these order forms can be either filled out from scratch and submitted ad-hoc, or submitted through an automated process where most of the order form data is pre-filled.

Here are some of the key business requirements that I am going to cover in detail:

There are multiple ways to start the same process.  That is, it is possible for a user to submit an order at any time (ad-hoc) or to approve and submit an order that is automatically generated for them (outside of this system).  This might be tricky because from what I've seen, a process can be tied to only one view of one InfoPath form for process initiation.  The ad-hoc and automated order forms will be different views at the least, maybe even completely different InfoPath forms... how will we get one process to start off of the submission of either one of these forms?

Submitting one order form may spawn multiple processes that can be acted on simultaneously by different users to accomplish one final result.  How will we have one process split into many, passing along the common information necessary to the child processes?

Since there are a number of activities related to one request, the requestor would like to see the progress being made on each activity.  The default task list webpart in SharePoint only shows tasks assigned to the user that is currently logged in.  How will we change this so that it shows all tasks associated with the process that they initiated?

All of the various order forms share a certain subset of data, lending themselves to a hierarchical use of content types to represent a base order form and then each specific order form derived from it.  I did not see any options in my InfoPath integration experimentation to indicate that the integrated form can be turned into a content type that is based on another content type.  How will we get our InfoPath form data to be tied to a base content type?

The task list needs to show various information that exists within the InfoPath form data (such as client name, due date, etc.).  The default task list can only show a static set of data, and the InfoPath integration wizard didn't seem to have a screen to promote fields to columns (a feature available when publishing InfoPath forms via InfoPath 2007).  How (and where) will I be able to show InfoPath form data as columns associated with a task?

Users want to have buttons or links to click in the InfoPath forms to submit their actions with one click.  The InfoPath Integration tutorials all use a drop down list of actions that the user selects from and then clicks a submit button.  How will I get the actions related to the task into buttons or links that know what to do when they are clicked?

If you are interested in seeing the solutions to any of the above problems, keep an eye on this blog as I will be posting solutions as I stumble through them over the next few days.

Posted: Feb 18 2008, 12:48 PM by tbyrne | with 1 comment(s)
Filed under: ,
Stumbling Through - Coding Challenges

While this is a bit of a departure from the theme of my blog, the Coding Challenge recently held by Clarity Consulting for its employees is an event that I feel is worth blogging about.  The reason it is of particular interest to me is that behind my calm, mild-mannered demeanor I am a fiercely competitive person - not from the standpoint that I must win everything I compete in but in that I simply love the thrill of the competition itself.  There is also the fact that on any given work day, I could go home thinking I must be the greatest developer in the world or go home thinking that I must have chosen the wrong profession; outside of my grades in college (which mean absolutely nothing in the real world) I have no way to judge or rank my developer skills.  Thusly, I was very excited to hear about an opportunity to test my abilities against a number of other Clarity consultants, and proceeded to completely ignore preparing in any way, preferring to 'stumble through' it as I do everything in my life (not that there was much to prepare for, really, as you'll see).

Come time for the challenge, I learned that there were going to be just three questions - an 'easy' one, a 'medium' one and a 'hard' one and we would gain points according to how quickly we submitted a working solution to the problem.  Nobody knew what the questions would be until the challenge started, and the timer for the question would begin right when you read it.  The solution would consist of only one class file (either VB or C#) with a pre-determined public method signature that can accept a number of different parameters and return results in a pre-determined format for testing.  After submission, the class would be subjected to a number of tests consisting of various parameter values and the results would be validated (I am assuming an exception would count as failing the test as well).  If any one test failed, you would score a big fat zero for that solution.  This brings me to my one gripe with the challenge:  you could have written the greatest algorithm in the world faster than anybody else but forgot to handle one outside test case (such as null parameter) and you'd get no credit at all!  I had hoped you'd get points per test case that succeeded, but such was not the case.  Turns out, though, that the test cases weren't as hard-core as I thought, as I built my method without any error handling, bounds checking or null handling and manage to score full points so I guess I shouldn't gripe too much.  I would, however, still submit that the test cases should've been tougher as a 'good' developer wouldn't have forgotten to check for null parameter values like I forgot to do.

While I won't post my results here, I will say that I was both humbled by what the other Clarity consultants were capable of and emboldened by my own moderate success.  My experience was somewhat tainted by the fact that I had a specific time I needed to leave by and since we started the challenge very late I was severely handicapped by time.  Not that I am making excuses here, mind you, I have no confidence that I would've done any more had I another 50 hours much less another 50 minutes, but I was very disappointed to leave the challenge in progress.  I am very much looking forward to stumbling through the next tech challenge, I'll make sure I have no responsibilities afterwards this time and therefore, no more pathetic excuses!

All in all, it was a very fun event and is a good example of one of the many things Clarity does to keep a level of excitement and interest in the workplace.

Posted: Feb 15 2008, 12:39 PM by tbyrne | with 3 comment(s)
Filed under: