JDF Blog

Tools, techniques and advice for real-world JDF integrations

Archive for August 2011

Fluent JDF Version 0.4.0.31 Released

with one comment

Fluent JDF Version 0.4.0.31 has been released. You can get the latest package on Nuget or download the binaries from the Codeplex page. Release notes are on our documentation site. This release has a couple of bug fixes including a work-around for what looks like a .NET Framework bug that causes problems with schema validation under some circumstances. The release notes include a link out to a good blog article that explains the problem. The major feature in this release is the ability to pass up to five string parameters to custom template replacement formulas. Let’s take a quick look at how that works.

I’m going to use a simple formula we added to our JDF Workflow Foundation (JWF) product as an example. JWF is our server framework for building JDF devices and controllers. It uses Fluent JDF’s template support to produce responses to standard JMF command and queries. Because it supports hosting multiple devices or controllers in a single process and JDF requires unique device ids, device descriptions, JMF URLs and other similar things per device or controller, we needed a way to pass those elements to template replacements. Here’s a fragment of XML we need to generate in a response that includes information about the current device.

<Device DescriptiveName="my device name" DeviceID="my device id" .../>

If you wanted to turn that into a template, you’d change it to look like this:

<Device DescriptiveName="[:deviceName:]" DeviceID="[:deviceId:]" .../>

And perform the replacement something like this:

var ticket = Ticket.CreateFromTemplate(templateFileName).With()
    .NameValue("deviceName", JwfLibrary.Settings.ServerSettings.DeviceSettings["my device id"].Name)
    .NameValue("deviceId", "my device id")
    .Generate();

Pretty simple right? Now imagine that you are writing dozens of message handlers that need the current device name or other data that is looked up based on the device id. Seems kind of tedious to look it up every time and pass it as a name-value. Well, parameterized custom functions solve the problem rather nicely. First, you setup the formula as shown in the next code fragment:

//Could use an anonymous function (Func<string, string>).  This example
//will use a static function declared somewhere in the code
public static string ConfiguredDeviceName(string deviceId) {
    if (deviceId == null) {
        return JwfLibrary.Settings.ServerSettings.DefaultDeviceSettings != null ? JwfLibrary.Settings.ServerSettings.DefaultDeviceSettings.Name : null;
    }
    if (JwfLibrary.Settings.ServerSettings.DeviceSettings.ContainsKey(deviceId)) {
        return JwfLibrary.Settings.ServerSettings.DeviceSettings[deviceId].Name;
    }
    return null;
}

//Here's the code to configure the function above as a 
//global custom template replacement formula
FluentJdfLibrary.Settings.WithTemplateEngineSettings()
    .CustomFormula("configuredDeviceName", deviceId => CustomFormulas.ConfiguredDeviceName(deviceId));

Once you have the configuration in place, you need to change the template to use your custom formula and pass it the parameter:

<Device DescriptiveName="[:deviceName=configuredDeviceName(deviceId):]" DeviceID="[:deviceId:]" .../>

Now the code only needs to pass the device ID as shown below:

var ticket = Ticket.CreateFromTemplate(templateFileName).With()
    .NameValue("deviceId", "my device id")
    .Generate();

Admittedly, we’re not saving a huge amount of code here but we are gaining considerable re-use. The nice thing is the template now takes care of the device name lookup for the device. The code only has to pass what the template can’t know until replacement time. I would not suggest using parameterized custom formulas when only one template will use the replacement. However, when you have something that needs parameters and will be used over and over again, a parameterized custom formula can make your life simpler.

Advertisements

Written by Tom Cabanski

August 23, 2011 at 2:54 pm

Posted in FluentJDF