Create an Automation Services Custom Task in TIBCO Spotfire®
Last updated:
10:19am May 09, 2017

Back to Extending Spotfire page

Introduction

Spotfire Automation Services provides a platform and tools for automating TIBCO Spotfire without user interaction and visible user interface.

Automation Services can be used to send reports at scheduled intervals, to save a snapshot of data embedded in a Spotfire document when certain events occur, and in many other situations requireing an automated action based on a Spotfire document.

The Automation Services API lets you create custom tasks that can be used together with the built in tasks when running automated jobs.

Prerequisites

  • TIBCO Spotfire® SDK, available in the TIBCO Spotfire Developer software which is available for download from edelivery.tibco.com. The SDK contains the following Visual Studio projects as an example of an Automation Services custom task:

    • Spotfire SDK\Examples\Extensions\SpotfireDeveloper.AutomationServicesExample
    • Spotfire SDK\Examples\Extensions\SpotfireDeveloper.AutomationServicesExample.Forms
  • TIBCO Spotfire® Analyst (installed instance or Portable edition)
  • Microsoft Visual Studio® 2013 or higher. The free Community edition is available for download here.

References

APIs

Manuals

Terminology

Task                    

An Automation Services Task is the building block for creating a complex job. Automation Services comes with a number of predefined tasks such as Apply Bookmark or Send Email, but since the platform is extendible additional tasks may be supplied by other vendors or your IT organization.

Job

An Automation Services Job is a collection of Tasks to be executed in a sequential manner. A job is stored in a Job File.

Job File

A Job File is a human-readable XML defining a job.

Job Builder

The Automation Services Job Builder is an application that runs within Spotfire Professional and provides an easy-to-use interface for creating and editing jobs.

Job Sender  

The ClientJobSender is a tool that sends off a job to the Spotfire Server for execution. Use ClientJobSender for setting up scheduled or event-driven job execution.

Architecture

The Job is normally created in the Job Builder and saved as an XML Job File. This file is then sent to the Spotfire Server for execution from the Job Builder window (for testing) or using the provided ClientJobSender tool.

For each job in XML format sent to the Spotfire Server for execution, a job executor process is started on an Automation Services node. This internal Job Executor executes the tasks one by one and then exits when a task fails or all tasks have completed successfully.

The Automation Services Job File Format

The XML format of the Job File has been designed to be easy to understand and modify. While there is no formal specification of the format, it is more or less self-explanatory.

The following job example opens an Analysis Document from the Analytics Server Library and exports an image to a predefined location:

<as:Job xmlns:as="urn:tibco:spotfire.dxp.automation">
  <as:Tasks>
    <OpenAnalysisFromLibrary xmlns="urn:tibco:spotfire.dxp.automation.tasks">
      <as:Title>Open Analysis from Library</as:Title>
      <AnalysisPath>/Users/Username/Baseball stats</AnalysisPath>
    </OpenAnalysisFromLibrary>
    <ExportImage xmlns="urn:tibco:spotfire.dxp.automation.tasks">
      <as:Title>Export Image</as:Title>
      <VisualizationId>292a90c6-0e03-47fe-961e-a528a14e9735</VisualizationId>
      <DestinationPath>C:\inetpub\wwwroot\MyWebServer\Image.png</DestinationPath>
      <Width>640</Width>
      <Height>480</Height>
    </ExportImage>
  </as:Tasks>
</as:Job>

 

Automation Services Example Task

This example highlights the important parts of the Apply Bookmark task that comes with the SDK, included in the projects:

  • Spotfire SDK\Examples\Extensions\SpotfireDeveloper.AutomationServicesExample - the model part containing the actual task implementation.
  • Spotfire SDK\Examples\Extensions\SpotfireDeveloper.AutomationServicesExample.Forms - the task UI to be embedded in the Automation Services Job Builder.

The Model Implementation

A task is implemented by extending the Task base class. 

A Task class must have a parameter-less constructor calling the case constructor with a title and a description. Optionally it can have an XmlRoot namespace to avoid naming conflicts if the same task name is already in use. Use a custom name spave for your custom task.

[XmlRoot(Namespace = "urn:spotfiredeveloper.automationservicesexample"]
public sealed class ApplyBookmark : Task
{
    /// <summary>Initializes a new instance of the ApplyBookmark class</summary>
    public ApplyBookmark()
        : base(Properties.Resources.ApplyBookmarkTitle, Properties.Resources.ApplyBookmarkDescription)
    {
    }
    
    // Properties and Methods goes here.
}

 

Public properties are added for all task properties that needs to accessed and set from the UI and to be saved as XML to the Automation Services Job File.

/// <summary>Gets or sets the GUID of the bookmark to apply.</summary>
[Description("The GUID of the bookmark to apply")]
public Guid BookmarkId { get; set; }

 

The ExecuteCore method is called by the framework when the task is executed. 

As often the case, ths example is dependent on that a document is loaded. If no document is loaded or no bookmark is found, the method returns with a status flag set to false and an error message. If a document is loaded and a bookmark is found, the task completes (applies the bookmark) and returns true.

/// <summary>This is executed when the add in is run on Automation Server.</summary>
/// <param name="context">The context.</param>
/// <returns>The result of the execution.</returns>
protected override TaskExecutionStatus ExecuteCore(TaskExecutionContext context)
{
    if (context.Application.Document == null)
    {
        // No analysis document loaded.
        Console.WriteLine("Error in execution of job {0}. No analysis loaded.", context.Id);
        return new TaskExecutionStatus(false, Properties.Resources.NoAnalysisLoaded);
    }

    // Check if the bookmark can be found among the new bookmarks
    var manager = context.Application.GetService<BookmarkManager>();
    if (manager != null)
    {
        Bookmark bookmark;
        if (manager.TryGetBookmark(this.BookmarkId, out bookmark))
        {
            // Apply the found bookmark and report success.
            manager.Apply(bookmark);
            return new TaskExecutionStatus(true);
        }
    }

    // Check if the bookmark can be found among the old bookmarks
    foreach (var bookmark in context.Application.Document.Bookmarks)
    {
        if (bookmark.Id == this.BookmarkId)
        {
            // Apply the found bookmark and report success.
            bookmark.Apply();
            return new TaskExecutionStatus(true);
        }
    }

    // Bookmark not found, report error.
    Console.WriteLine("Error in execution of job {0}. The bookmark {1} was not found.", context.Id, this.BookmarkId);
    return new TaskExecutionStatus(false, Common.Format(Properties.Resources.BookmarkNotAvaliable, this.BookmarkId));
}

 

Finally, the task implementation is registered in a separate RegisterTasksAddin class.

/// <summary>This AddIn class handles registration of all the base tasks to the Task registry.</summary>
public sealed class TasksAddIn : RegisterTasksAddIn
{
    /// <summary>Gets called once the framework is up. Implement this to register your tasks and their executors.</summary>
    /// <param name="registrar">The registrar helper</param>
    public override void RegisterTasks(TaskRegistrar registrar)
    {
        registrar.Register(new ApplyBookmark());
    }
}