Category: Work > K2 API

K2 Insider Conference 2009

K2 Insider Conference

K2 Insider Conference

Last weekend was the K2 insider Conference in Las Vegas. They neatly planned it just before the SharePoint Conference to make it more easy for us to come over. This post will not cover a lot of info that’s been said at the conference, some of it is even under NDA, so I’m simply not allowed to blog about, which is a shame, as I can’t wait to get all those new bits!

Start of the conference

Chris Geier kicked of the conference by an introduction round and checking what everybody wants to get out of this conference, most of the insiders want to see the new bits and talk about issues that they had in their projects.

After that it was Adriaan van Wyk to explain how they are handling the economical situation in the world. In general K2 is doing very well and handling the situation as they should be, which reassures me in the future of K2.
After this all, Adriaan gave us a overview of how they set out to build K2 blackpearl and how a lot of functionality is in the platform but not exposed via UI since they simply didn’t have the time and resource to do so, a good example of that is the Event Bus. It also shows why SmartObjects are so important and why they re-engineered a lot of the SmartObject code to make it perform better and really start using it as a way to surface and manage data around the processes.

Other good news is that K2 blackpoint and K2 blackpearl are now based on the same code-base and upgrades will be released at the same day.

Next K2 release

In the next release there’s been loads of work done to make installation easier. A lot of support tickets within K2 are based around infrastructure problems like Kerberos. With the new installer (which merges installation and configuration wizards), there’s an environment checker that checks your settings and sometimes automatically repairs them. The new installer also allows for unattended installations. Together this allows for super easy installation and checking if the Kerberos environment is configured correctly.

K2 designer for SharePoint

Also in the next release is a the new K2 designer of SharePoint. This basically is the Silverlight designer but is redesigned and made better, with one of the key features being inline functions and SmartObject filtering. Next to that, there’s new wizards available to allow you to do more with the designer.
The K2 designer for SharePoint has also been enhanced, concepts as loops are available, this might seem a simple item, but you’ll be amazed on how many workflow products do not support a loop/loopback.

Again, people will wonder it a Silverlight designer can bring enough functionality. If it does not, you can simply export the process and continue working on it in K2 blackpoint, and if that’s not enough, you can go to K2 blackpearl.

Inline Functions

Another new feature in the next release is Inline functions. It might not say a lot by the name, but it basically means that on every entry-field on a K2 wizard you’re able to use functions – all without code. What kind of functions? A lot. Think about math functions, expressions, string functions (like left, right, padding, etc), and much, much more. Now if you do think you can find a function that’s not available, you can simply create it yourself.
Inline Functions allow for less use of code within K2 processes, which is important for the K2 designer for SharePoint and K2 blackpoint, as there’s no code available.
To make it a bit more clear, here’s a screenshot:

Screenshot of an inline function (complex)

Screenshot of an inline function (complex)

I’ll also try to create another blogpost on InLine functions to explain them better.

Performance and stability enhancements

Apart from new functionality, Koos Du Preez also had a talk on the performance enhancements made to the K2 server. In the past, there have been some problems with the Worklist performance, I can assure you, those days are over.

The performance of SmartObjects and the ADO.net provider has also been reviewed and improved. Some service brokers are now able to directly call the backend, eliminating a lot of overhead. Aside from that, a double buffer system is made so the SmartObject readers are way faster, sometimes even faster than calling the SQL Table directly.

Conclusion

The days flew by and where packed with info, the above article is just the tip of the K2 mountain. Can’t wait to go ahead and work with those new bits and see the product improve and improve.

K2’s Custom Event Notification – Twitter

The K2 BlackPearl platform as it stands today is a large platform with a lot of out of the box functionality. When using out of the box products, I always fear that it might be too limited. When doing K2 projects I sometimes hit those boundaries, but I’m always able to use one of K2’s extension options to help me out. A custom action for the Event Bus (what this blog post is about) is just one of the possibilities.

The Event Bus/Scheduler itself is an impressive piece of architecture. You can read about it in chapter 21 of the Professional K2 BlackPearl book. The event bus is used to perform an action when a specific event occurs within K2. With the K2 workspace you’re able to subscribe to those events. This extension provides you the ability to add your own assembly with static method and call that based on the event that occurred within K2.

Example code

To make a small example, I’ve written a class with two static functions that use the Twitterizer API to communicate with Twitter. Although Jonathan King has got some more integration with Twitter, this seems to be a simple/good example for the Event Bus:

using System;
using System.Collections.Generic;
using System.Text;
using Twitterizer.Framework;
using System.Configuration;
using SourceCode.EventBus.Utils;
 
namespace TwitterCustomActionEvent
{
    public class SendTweets
    {
        private static Twitter CreateTwitter()
        {
            AssemblySettings settings = new AssemblySettings();
 
            string proxyUrl = settings["ProxyUri"] as string;
            string username = settings["TwitterUsername"] as string;
            string password = settings["TwitterPassword"] as string;
 
            if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) {
                throw new ArgumentException("The username and password should be supplied by the Application Configuration file.");
            }
 
            Twitter twit;
 
            if (string.IsNullOrEmpty(proxyUrl)) {
                twit = new Twitter(username, password, "K2 Notifications");
            } else {
                twit = new Twitter(username, password, "K2 Notifications", proxyUrl);
            }
 
            return twit;
        }
 
        public static void SendTweet(string text)
        {
            Twitter twit = CreateTwitter();
            twit.Status.Update(text);
        }
 
        public static void DirectMessage(string toUser, string text)
        {
            Twitter twit = CreateTwitter();
            twit.DirectMessages.New(toUser, text);
        }
    }
}

As you can see, there are 3 methods. Only the Public static methods are seen by the K2 Custom Event Wizard. The private method instantiates the Twitter API and uses the AssemblySettings class to get some configuration settings. The two public methods simply send a Direct Message to a twitter user or send out a simple tweet (status update).

In the CreateTwitter() method, a AssemblySettings object gets initialized. This object can be found in the SourceCode.EventBus.Utils namespace and allows simple configuration files to be loaded. A sample of that config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<appsettings>
		<TwitterUsername>username</TwitterUsername>
		<TwitterPassword>password</TwitterPassword>
		<ProxyUri/>
	</appsettings>
</configuration>

Although it might look like a normal application configuration file (.config), it is not! Normally you would see ‘<add>’ nodes in the appSettings list. The AssemblySettings class reads the the XML and parses it. Be sure to use ‘appsettings’ in lowercase, as the xml parsing is case sensitive.

The SendTweet and DirectMessage methods simply send calls the Twitterizer API.
The above class is put into a signed class library project.

Installing the Custom Event

After you have build this class, create a folder in C:\Program Files\K2 BlackPearl\Host Server\Bin, or whatever directory you’ve installed K2 into.
In my case, I’ve named the directory ‘twitter’ and placed 3 files:

  • TwitterCustomActionEvent.DLL
  • TwitterCustomActionEvent.DLL.config
  • Twitterizer.Framework.dll

As you can see, also placed the referenced assemblies in the same folder, and create a config file that’s the same name as the DLL, with .config after it.

Now, open up the SourceCode.EventBus.Assemblies.config file located in the Host Server\bin folder. This file is a simple configuration file so the K2 server knows which assemblies it can use for Actions in the Event Notification. Simply add a assembly line, give it a Displayname and locate the Assemly that it sould use. Mine looks like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
	<appsettings>
		<assemblies>
			<assembly displayname="EventAssemblies" fullname="c:\program files\k2 blackpearl\Host Server\Bin\SourceCode.EventBus.EventAssemblies.dll" />
			<assembly displayname="TweetAssembly" fullname="c:\program files\k2 blackpearl\Host Server\Bin\twitter\TwitterCustomActionEvent.dll" />
		</assemblies>
	</appsettings>
</configuration>

Configure the Action Subscription

After this, restart the K2 hostserver and go to the K2 workspace. Open up the Notification events menu and select. On the screen that opens,click New event in the bottom right hand corner.

select-custom-event-designer

Enter a name and description, select next.

Click to enlarge

Click to enlarge

Now, you get a screen where you can select the event you want to subscribe to, in this case, I’ve selected the OnProcessStarted event.

Click to Enlarge

Click to Enlarge

Time to select the action, this is done by first selecting the assembly. Click search and get all of them, including the one you’ve just added.

Click to Enlarge

Click to Enlarge

Click next and select the class you want to use. In this example, TwitterCustomActionEvent.SendTweets.

Click to Enlarge

Click to Enlarge

Click next to select the Method you want to use, I’m going to do ‘SendTweet’, finally click finish.

Click to enlarge

Click to enlarge

As you can see, the screen is updated and you are now able to add Action Parameters. Simply select data from the left object browser and drag them into the Text field. You can add extra text if you want too.

Click to enlarge

Click to enlarge

After that, click finish and you’re done! Start the process and see your twitter happening!

Update a K2 ClientEvent URL using code

In our current project there are 18 processes with each at least 4 client events. There are even processes with 8 or 12 client events. We also have 1 webpart that handles all the client events. In the beginning we decide on the URL passing a parameter to allow the webpart to render correctly. The basis of that decision has (of course) changed and the querystring isn’t used anymore.

This also means, that querystring only contains the SerialNumber. The URL itself is based on a field from the Environment library. As you noticed, we’ve got at least 72 client events to update, this means a lot of manual work, luckily there is the K2 SourceCode.Workflow.Authoring API. If you have a big-ish project like we do, you’re going to use this API more and more….

Show me the code!

The following code allows us to update the Client Event URL:

 DirectoryInfo di = new DirectoryInfo(@"C:\LocationOfK2Solution\");
FileInfo[] fileInfo = di.GetFiles("*.kprx");
 
foreach (FileInfo processFile in fileInfo)
{
    Process proc = Process.Load(processFile.FullName);
    Console.WriteLine("Process: {0}", proc.Name);
    foreach (Activity act in proc.Activities)
    {
        Console.WriteLine("\tActivity: {0}", act.Name);
        foreach (Event evnt in act.Events)
        {
            Console.WriteLine("\t\tEvent name: {0}", evnt.Name);
            Console.WriteLine("\t\tEvent type: {0}", evnt.Type);
            if (evnt.Type == EventTypes.Client)
            {
                ClientEventItem clEvent = (ClientEventItem)evnt.EventItem;
 
                if (clEvent.InternetUrl == null || clEvent.InternetUrl.Parts == null)
                {
                    throw new Exception("client event InternetURl is empty.");
                }
 
                K2FieldPartCollection fieldPartCollection = clEvent.InternetUrl.Parts;
 
                // The first fieldpart should be the envField(from the artifact library)
                K2FieldPart envField = fieldPartCollection[0];
                if (envField.GetType() != typeof(ArtifactLibraryFieldPart))
                {
                    throw new Exception("K2FieldPartCollection's 1st element is not an ArtifactLibraryFieldPart (is not the expected environment setting)");
                }
 
                // Remove everything and build it up again.
                fieldPartCollection.Clear();
 
                // Add the original first element
                fieldPartCollection.Add(envField);
 
                // Add the SerialNumberField.
                SerialNoFieldPart serialField = new SerialNoFieldPart();
                fieldPartCollection.Add(serialField);
 
                // Save it back to the clientEvent.
                clEvent.InternetUrl.Parts = fieldPartCollection;
 
                Console.WriteLine("\t\tClient event URL updated, is now {0}", clEvent.InternetUrl.DesignTimeValue);
            }
        } // foreach act.Events
    } // Foreacht process.activities
 
    proc.Save();
    Console.WriteLine("Saving process");
} //foreach file

Code explained

The code isn’t very hard to understand. We first get all the kprx files (i know, you can load the solution and get the files from there). We load the process using Process.Load(). Loop trough the activities and then loop trough al the events. We simply get all the clientevents by looking at the event type.

This is where it gets interesting. You can cast an event to a ClientEventItem. This allows you to get the InternetUrl as a property. That InternetURL is actually a K2FieldPartCollection. A k2FieldPart can be a lot of things, in this case we check if the first one is an ArtifactLibraryFieldPart which is a value from the ArtifactLibrary (or the Environment Library as most people know it). This check was simply there to check if we are doing the correct thing.

After that we clear the K2FieldPartCollection and add the ArtifactLibrary field we just saved in another variable, then just add the SerialFieldPart which represents the SerialNumber.
You can then simply print out the DesignTimeValue as shown. After that, we save the process and we’re done.

As you can see, the SourceCode.Workflow.Authoring API is very easy to use. We use it a lot to update and do stuff to our processes and the K2 Documentation also provide some examples on how to build processes using code!

WordPress Themes