TIBCO Spotfire Community

Welcome to TIBCO Spotfire Community Sign in | Join | Help

Extending Extensions

This article targets: TIBCO Spotfire 2.1 and forward                Download Source Code

NOTE: This article is for TIBCO Spotfire 2.1, if you are using TIBCO Spotfire 2.2 there is an improved mechanism for this same task. For more information on the new method read this post.

Introduction

When developing an extension to Spotfire (be it a calculation, a custom visualization, and so forth.) you may want to enable others to be able to add on to the capabilities of your code. For instance, more methods could be added to a custom calculation, or a custom visualization could be enhanced with additional graphical features and rendering strategies. Although you are free to implement any mechanism, there is a very convenient way of achieving extendibility.

It might not be obvious, but you are actually free (and encouraged) to use the Spotfire add-in framework itself to enable extensions to your code. First, in doing so you will be using a framework that is proven to work, which dramatically reduces your effort. You escape issues like defining an add-in definition language, serialization and de-serialization of a definition file, assembly loading issues, and deployment mechanisms. Second, you are doing your users a favor since they will not have to learn yet another framework. Finally, the users of your framework do not have to register their add-ins twice, once in your framework and once in the regular add-in framework. The latter is always necessary to load an assembly in Spotfire.


The Extendable Framework

The way you would approach creating your framework is to start off by extending the AddIn class with a new abstract class. This will become the new base class that implementers of your code will inherit (instead of the default AddIn class) to plug their extensions into both Spotfire and your framework. Note that the Spotfire packaging and deployment tools are implemented to handle this scenario. What they mind is that there is some inheritance from the AddIn class; the number of intermediate classes just doesn’t matter. In this example we will call our new base class ExtendableAddIn.

public abstract class ExtendableAddIn : AddIn { … }

I do recommend you to seal those of the virtual methods inherited from AddIn that do not make sense to your framework. For instance, if your framework only revolves around custom visualizations, it probably does not seem sensible for anyone extending ExtendableAddIn to use the class to register calculations. Hence, we remove the RegisterCalculations method to prevent misuse.
public abstract class ExtendableAddIn : AddIn 
{
   // Seal the overrides that do not make sense to extend from base class.
   protected override sealed void RegisterCalculations(CalculationRegistrar registrar) 
   {
      base.RegisterCalculations(registrar);
   }

   …
}


Having sealed some methods, you need to define new Register* methods that users will override to hook their additions into your framework. Note that it is considered best practice for a Register method to have a registrar as its input parameter. The registrar is a simple helper class that takes care of the registration process in the underlying registry object. The registry in turn could be as simple as a wrapped collection that keeps track of all registered extensions. The advantage of using the registrar pattern is that you can hide the registry implementation altogether from your public API.

public abstract class ExtendableAddIn : AddIn 
{
   /// <summary>
   /// Require sub classes to implement this method and register extensions
   /// using the given registrar.
   /// </summary>
   /// <param name="registrar">The object to use to register extensions.</param>
   /// <remarks>We require other to implement this method (instead of overriding
   /// a virtual method) as the whole purpose of extending this class is to
   /// use this method.
   /// </remarks>
   public abstract void RegisterExtension(ExtensionRegistrar registrar);

   public class ExtensionRegistrar
   {
       private ExtensionRegistry registry;

       internal ExtensionRegistrar(ExtensionRegistry registry)
       {
           this.registry = registry;
       }

       public void RegisterExtension(Extension extension)
       {
            this.registry.Register(extension);
       }
   }
}
/// <summary>
/// Simple implementation of a registry that contains the registered extensions.
/// </summary>
internal class ExtensionRegistry
{
    private List<Extension> extensions;

    public IEnumerable<Extension> Extensions { get { … } }

    public ExtensionRegistry() { … }

    public void Register(Extension extension) { … }
}


A problem that needs to be solved is how to make the registry that will keep your users’ extensions available to the registrar. The best practice for this scenario is to make it available as a global service. This is achieved using the RegisterGlobalServices override of the AddIn base class. Having done so, the registry will be available through any of the GetService method provided throughout Spotfire. Note that the registration of our registry is not carried through in ExtentableAddIn but in the AddIn implementation of your framework (called FrameworkAddIn in this article).

internal class FrameworkAddIn : AddIn
{
    /// <summary>
    /// Registers the registry as a global service.
    /// </summary>
    protected override void RegisterGlobalServices(AddIn.ServiceRegistrar registrar)
    {
        base.RegisterGlobalServices(registrar);
        registrar.Register<ExtensionRegistry>(new ExtensionRegistry());
    }
}


Unfortunately the only way an instance of ExtendableAddIn can perform a GetService call to obtain the registry is through registration of an ApplicationEventHandler. By registering a delegate we can get a callback when the Spotfire application object is made available. The callback also makes the application object available and hence allows us to retrieve our registry.

public abstract class ExtendableAddIn : AddIn 
{
   protected override void RegisterApplicationEventHandlers(ApplicationEventHandlerRegistrar registrar)
   {
       base.RegisterApplicationEventHandlers(registrar);
       registrar.Register(new ApplicationEventHandler(this));
   }

   private class ApplicationEventHandler : CustomApplicationEventHandler
   {
        private ExtendableAddIn addIn;

        public ApplicationEventHandler(ExtendableAddIn addIn)
        {
            this.addIn = addIn;
        }

        /// <summary>
        /// When the application instance is created we can be sure that the global services
        /// all have been registered, including our own registry. So it is safe to call
        /// all sub classes of ExtendableAddIn and allow them to register their extensions.
        /// </summary>
        protected override void OnApplicationInstanceCreated(AnalysisApplication application)
        {
            this.addIn.RegisterExtension(new ExtensionRegistrar(
                application.GetService<ExtensionRegistry>()));
        }
    }
}


Note that using the ApplicationEventCallback to access the registry is not the optimal approach. Had the AddIn class provided a callback when all global services had been registered, we could use that to access our registry in a much more straight-forward fashion. Nevertheless, the aforementioned approach works and it doesn’t have any remarkable negative side-effects.


Conclusion

Hopefully this article gives you an idea of how to create a framework that is easily extendible by yourself or others through a simple inheritance from the AddIn class. Also, it has illustrated a number of best practices for registering global services, extensions, etc, all leading to developing better extensions to Spotfire.

Published Nov 15 2008, 11:37 AM by Ehsan Yazdani
Filed under: , ,
Rating:
Comments

About Ehsan Yazdani

Ehsan Yazdani is a developer with the TIBCO Spotfire and the TIBCO Spotfire Analytics Server Framework teams. His fields of expertise are network communication, web services, and framework extensibility.