FitNesse is extensible. It can be extended via components configured in the Configuration File. Since version 20150226 FitNesse also has another mechanism: service providers. It's using the Java ServiceLoader functionality to load services dynamically.

How does it help me?

Previously, to install a plugin you had to download the plugin and load it alongside FitNesse (either from the plugins folder or by using a build tool such as Ant or Maven to launch FitNesse) and you had to configure the plugin in the Configuration File. When a plugin has a service provider it is no longer needed to also define it in the configuration file. Just put the plugin jar on the FitNesse class path or in the plugins folder and it will be configured automatically.

Add service providers to your plugin

To add a service provider the plugin provider class (plugin feature factory) has to be configure in

META-INF/services/fitnesse.plugins.PluginFeatureFactory
This file has to contain the plugin implementations (which should implement the PluginFeatureFactory interface), one per line. Plugins can also extend PluginFeatureFactoryBase, which contains empty implementations for all methods.

The interface looks like this:

public interface PluginFeatureFactory {

  Authenticator getAuthenticator();

  ContentFilter getContentFilter();

  void registerResponders(ResponderFactory responderFactory) throws PluginException;

  void registerSymbolTypes(SymbolProvider symbolProvider) throws PluginException;

  void registerWikiPageFactories(WikiPageFactoryRegistry wikiPageFactoryRegistry) throws PluginException;

  void registerTestSystemFactories(TestSystemFactoryRegistry testSystemFactoryRegistry) throws PluginException;

  void registerSlimTables(SlimTableFactory slimTableFactory) throws PluginException;

  void registerCustomComparators(CustomComparatorRegistry customComparatorRegistry) throws PluginException;

}

The methods getAuthenticator() should return one instance. If multiple plugins provide an authenticator, the first authenticator found will be used. The setting can be overridden by explicitly defining an authenticator in the configuration file.

The same rules are applicable for getContentFilter().

The registerXxx methods are invoked with the appropriate provider or registry. It is the responsibility of the plugin to register it's plugins with those providers.