Cloning K2 environment field values

K2 blackpearl has the ability to hold configurable values that target different environments, during design time this data is stored in the K2 environment library. Upon deployment the Environment Library will used to create the string table entries required at runtime.

During the development life cycle you may find yourself creating a substantial amount of environment fields. However when creating these K2 will set a value for the current environment however the value will not be set for any of the other environments configured on the K2 Environment Library. Resulting in a deployment that may inject empty string table entries into another environment. This can be easily corrected depending on the approach being taken for deployment. Generally speaking I prefer deployment package creation, purely due to the fact that this is how I would provide the solution to the client. I would not expect them to have a visual studio workstation where I could simply deploy from ( which in itself poses another issue that this post attempt to resolve ).

Although the code here is pretty basic, it satisfied my immediate need and I’m sure it will help many of you too.

So let’s get dirty, and the first warning: This API does not appear to be documented in K2 4.5 with update 1230., although I have tested this functionality.

First thing we need to do is reference SourceCode.EnvironmentSettings.Client.dll this should appear in the GAC if it doesn’t just navigate to the bin directory of your blackpearl installation folder and reference it from there. You should see it is marked as Global rather than Copy Local indicating that it is being pulled from the GAC.

To connect we create an instance of the EnvironmentSettingsManager. We then specify the connection string for the K2 Environment Server, which is effectively the same connection string for connecting to the K2 workflow management server (note port 5555 as opposed to 5252 which is used by the workflow server). It is important to note that the EnvironmentSettingsManager class does implement IDisposable so you could actually use a using statement when you instantiate the class to ensure that the class is disposed of correctly, and all of the connections are closed.

// This will set up the class with out actually opening the connection.
// The first argument indicates that the connection should not be opened,
// and the second that we shouldn't use the caching mechanism.
EnvironmentSettingsManager manager =
   new EnvironmentSettingsManager(false, false);

// specify the connection string. Impersonate the calling user rather than provide a user name and password.
manager.ConnectionString = "Integrated=True;IsPrimaryLogin=True;Authenticate=True;EncryptedPassword=False;Host=localhost;Port=5555";

// initialize the manager, and specify true as the argument to establish the connection to the environment library.
manager.InitializeSettingsManager(true);

The next thing we need to do is select an environment. One thing to consider is the environment template being used this however is out of scope for this particular post as we’re dealing a standard k2 installation where little customisation has taken place. I will therefore always use the first available template, and to keep the demo short I’ve selected the first environment in that template.

// Retrieve available environments
EnvironmentInstanceCollection environments = manager.EnvironmentTemplates[0].Environments;

// Change the environment
manager.ChangeEnvironment(environments[0].EnvironmentName);
manager.Refresh()

Now given that we’re copying values from one environment to another on the same server we can assume that environment fields will already exist, but their values will be blank.

Setting the value is as simple as executing the following code we will use the first available environment field and set its value to test.
You have the option of using the actual field name or the internal field id. It is important to note that the SaveUpdate() method is also available on the EnvironmentFields property this however does not seem to persist the data back to the K2 server, and I would recommend that you would execute the SaveUpdate() method on the individual EnvironmentField to guarantee success.

// Set new value
manager.CurrentEnvironment.EnvironmentFields[0].Value = "Some Value";

// Persist to K2
manager.CurrentEnvironment.EnvironmentFields[0].SaveUpdate();

In cleaning up if the code has not been wrapped in a using block, be sure to invoke Disconnect() method on the manager instance in this document.

manager.Disconnect();