Skip to main content
RSS feed Subscribe to feed

 

How to create an Automation Services Task

Automation Services automates tasks in TIBCO Spotfire. This tutorial explains how to automate posting of status messages, in this case to Twitter.

Overview

This tutorial shows how to implement and deploy a custom Automation Services Task for Automation Services 2.2. The source code available for download requires Visual Studio® 2008, and implements a task which can post status messages to TwitterExternal link. Also refer to the Twitter API documentationExternal link. The code is easily adapted to other systems.

Download for 2.2 and 3.0: AutomationServicesTaskTwitter.zip
Download for 3.1: AutomationServicesTaskTwitter31.zip. For 3.1 works best if the project is copied to the <Spotfire SDK 3.1>\Examples\Extensions folder.

Create the Project

  1. In Visual Studio® 2008, create a Class Library project. The AutomationServicesTaskTwitter project is called MyTask.
  2. Reference the Spotfire.Dxp.Automation.Framework.dll as well as the Spotfire platform Spotfire.Dxp.Application.dll, Spotfire.Dxp.Data.dll and Spotfire.Dxp.Framework.dll SDK assemblies. Make sure to use the SDK assemblies of the same version as the installed Automation Services.
  3. Set Copy Local to False for all these references.
    Copy Local is False for all Spotfire assemblies
  4. In the Project Properties pages, sign the assembly. Check the Sign the assembly check-box. Either make a new key or select an existing. In SDK version 3.1 or later, the Spotfire SDK key is used; for older versions the supplied AutomationServicesTutorial.snk key is used.
    Signing the assembly

Implement the Task Sub Class

First create a parameter-less constructor calling the base constructor with a title and description. Optionally create an XmlRoot namespace to avoid task naming conflicts if the same task name is already in use. In this code urn:spotfiredeveloper.automation.twittertask is used.

[XmlRoot(Namespace = "urn:spotfiredeveloper.automation.twittertask")]
public class MyTask : Task
{
    private const string title = "Send Twitter Message";
    private const string description = "Posts a message to Twitter";

    [Description("The twitter user name")]
    public string UserName { get; set; }
    [Description("The twitter password")]
    public string Password { get; set; }
    [Description("The message to post to twitter")]
    public string Message { get; set; }

    public MyTask()
        : base(title, description)
    {
    }
    protected override TaskExecutionStatus
        ExecuteCore(TaskExecutionContext context)
    {
        /* Implement the task execution code here. */
        return new TaskExecutionStatus(true);
    }

Provide a Custom View

If no custom view is provided, a simplistic default view is provided.
Default view when no custom view is implemented

It is recommended to implement a custom view to provide the expected user experience.
Custom view layout for the task

Create a new UserControl class and change the base class to BaseTasksControl.

Create a constructor that accepts exactly one instance of the Task sub class. Store the supplied model object in a local variable.

public partial class MyTaskControl : BaseTasksControl
{
    private MyTask model;

    public MyTaskControl()
    {
        InitializeComponent();
    }

    public MyTaskControl(MyTask model)
        : this()
    {
        this.model = model;
    }

Override the UpdateControlsCore method of the BaseTasksControl class to display the contents of the model object in the view:

protected override void UpdateControlsCore()
{
    base.UpdateControlsCore();

    // This is called whenever the controls need to be updated.
    // The IsUpdating flag is TRUE during this method's execution.

    this.textBoxName.Text = this.model.UserName;
    this.textBoxPassword.Text = this.model.Password;
    this.textBoxMessage.Text = this.model.Message;
}

Finally, handle the user's input and write it to the model object. When changing the contents of the model object also make sure to notify the framework to let it know the document is in an unsaved state:

private void textBoxName_TextChanged(object sender, EventArgs e)
{
    if (!IsUpdating)
    {
        // Update the model.
        this.model.UserName = this.textBoxName.Text;
        
        // Notify the change to the framework, which sets the document to unsaved state.
        EditingContext.NotifyChange();
    }
}

Implement the RegisterTasksAddIn Sub Class

The task implementation is now finished, but to make it load into the Spotfire runtime it must be registered. Create a sub class of the RegisterTasksAddIn class and override the RegisterTasks method and, optionally, the RegisterViews method to register the task and its view.

public class MyTaskAddIn : RegisterTasksAddIn
{
    public override void RegisterTasks(TaskRegistrar registrar)
    {
        registrar.Register(new MyTask());
    }

If a custom view was implemented, register it. Otherwise the simplistic default view will be used.

protected override void RegisterViews(ViewRegistrar registrar)
{
    base.RegisterViews(registrar);
    registrar.Register(typeof(BaseTasksControl), typeof(MyTask),
        typeof(MyTaskControl));
}

Debug the Task Locally

To debug in the TIBCO Spotfire Professional application as exposed in the Job Builder, use the Spotfire SDK Package Builder  application.

  1. Add the /bin directory for where you have compiled your task.
  2. To include the base Automation Services binaries, add the Modules\Automation Services_N.N.N.N for folder next to the Spotfire.Dxp.exe application. It is typically installed at C:\Program Files\TIBCO\Spotfire\N.N.
    Note: This folder is created by logging on to a Spotfire Server on which the Automation Services Job Builder package has been deployed.
Using Package Builder

Run the Automation Services Job Builder tool and create a job file containing the new task.

If the message posted to Twitter is the same as the previously posted message, the new message will be ignored by Twitter. To test effectively you must update the message between test runs, for instance by adding the Automation Services {time} tag in the message field, ensuring that each time the task is run a new message containing the current time is generated.


You should now be able to run the job by selecting Tools > Execute Locally for Testing.

Job with the Twitter task

Deploy the Task to an Spotfire Sever

Use the package builder to build a Spotfire package file (.spk) for the task and deploy it to the Spotfire Server.

Deploy the Task on the Automation Services Server

Add your extension to the Automation Services web server by copying your assembly .dll to C:\Program Files\TIBCO\Spotfire\AutomationServices\bin on the server. Then edit the AddIns.xml file in the same directory to include your assembly .dll. This tells the Automation Services runtime to load the extension on launch.

The following code snippet shows an example AddIns.xml where the MyTask.MyTaskAddIn class residing in the MyTask.dll assembly has been added:

<?xml version="1.0" encoding="utf-8" ?>
<!-- This is the AddIns.xml file which must be deployed together with the AS assembly
     in the Automation Services directory. -->
<AddInRegistry xmlns="http://www.spotfire.com/schemas/AddInRegistry1.0.xsd" SchemaVersion="1.0">
  <!-- namespace, assembly -->
  <AddIn FullTypeName="Spotfire.Dxp.Automation.Framework.FrameworkAddIn, Spotfire.Dxp.Automation.Framework"/>
  <AddIn FullTypeName="Spotfire.Dxp.Automation.Tasks.BaseTasksAddIn, Spotfire.Dxp.Automation.Tasks"/>
  <AddIn FullTypeName="MyTask.MyTaskAddIn, MyTask"/>
</AddInRegistry>

You should now be able to execute your job remotely by invoking Tools > Execute on Server in the Job builder.