Last updated Dec 8, 2017

Adding Feature Discovery to your plugin

Available:

This service is available in Confluence 5.1.5, Confluence 5.2, and later.

Confluence provides a feature discovery service that you can use in your plugin. Let's say you've added a new module or feature to your plugin, and you want to let users know about it. In other words, you need a way of letting users discover the new features. The feature discovery service is provided by the Confluence Feature Discovery plugin, which is bundled in Confluence 5.1.5, Confluence 5.2 and later.

Summary: How to let users know about a new feature

In brief:

  • If necessary, register the new feature with the feature discovery service. This is not required if your feature is associated with a new plugin module.
  • Use the feature discovery service to find all modules or features that were enabled on the user's Confluence site within a specified period.
  • Let your users know. For example, you could add code to your plugin that highlights the new functionality in the Confluence user interface. (This functionality is not part of the feature discovery service.)

Details are on the rest of this page.

Step 1. Register the new feature if necessary

The feature discovery service keeps track of features via a context (usually the plugin key) and a key (usually the module key).

The plugin automatically detects when plugin modules are enabled, using the plugin key as the context and the module key as the key. You do not have to register features that are backed by plugin modules.

When do you need to register a feature?

Examples of situations where you need to register your new feature manually:

  • The feature is not associated with a plugin module. For example, the feature may be provided purely by JavaScript.
  • You have changed an existing plugin module. Note that you must unregister the module, and then register it again. Simply registering won't work as registration is an idempotent operation.

How to register a feature

To register a feature, call one of the register() methods of the feature service, providing the context and key. See the methods reference below. You could do this in a plugin upgrade task or any other place. Feature registration is an idempotent operation - if you try to register something that has already been registered, nothing happens.

How to unregister a feature

To register a feature, call one of the unregister() methods. See the methods reference below.

Step 2. Use the feature discovery service to find new modules or features

2.1 Add a dependency on the Feature Discovery plugin

Add the following dependency in your plugin's pom.xml:

1
2
<dependency>
  <groupId>com.atlassian.confluence.plugins</groupId>
  <artifactId>confluence-feature-discovery-plugin</artifactId>
  <version>1.7</version>
  <scope>provided</scope>
</dependency>

2.2 Import the component

Add the component-import in your plugin's atlassian-plugin.xml:

1
2
<component-import key="featureDiscoveryService" interface="com.atlassian.confluence.plugins.featurediscovery.service.FeatureDiscoveryService"/>

2.3 Write Java code to find new features

Call isNew() to see if a given feature is newly installed/enabled on this Confluence site, or call getNew() to get a list of new features within a given set. See the methods reference below.

Step 3. Highlight the new features for your users

It is up to your plugin to let the Confluence users know about the new functionality. For example, you could add code to your plugin that highlights the new options in the Confluence user interface. This functionality is not part of the feature discovery service. See the example below.

Reference: Methods in the feature discovery service

Method signature - registering a feature or moduleDescription
1
2
void register(
  String context, 
  String key
)

void register( String context, String key, Date installationDate )

Call this method to register your plugin module or feature with the feature discovery service.

Parameters:

  • context - Usually the plugin key.
  • key - Usually the module key, but can be a string of your choice that uniquely identifies the feature.
  • installationDate - Optional. The date on which the plugin module or feature was installed. The default is the current time.

1
2
void register(
  ModuleCompleteKey
    moduleCompleteKey
)

void register( ModuleCompleteKey moduleCompleteKey, Date installationDate )

 

Call this method to register your plugin module with the feature discovery service.

Parameters:

  • moduleCompleteKey - The full key of the plugin module, as defined in the Atlassian plugin framework.
  • installationDate - Optional. The date on which the plugin module or feature was installed. The default is the current time.
1
2
void register(
  FeatureCompleteKey
    featureCompleteKey
)

void register( FeatureCompleteKey featureCompleteKey, Date installationDate )

You can use this function to register features that are not backed by a plugin module.

Parameters:

  • featureCompleteKey - The context and key of the feature, combined to form the complete key of the feature.
  • installationDate - Optional. The date on which the feature was installed. The default is the current time.
Method signature - unregistering a feature or moduleDescription
1
2
void unregister(
  String context,
  String key
)
Call this method to de-register a given module or feature.
1
2
void unregister(
  ModuleCompleteKey
    moduleCompleteKey
)
Call this method to de-register a given module or feature.
1
2
void unregister(
  FeatureCompleteKey
    featureCompleteKey
)
Call this method to de-register a given feature.
Method signature - checking if a feature or module is newDescription
1
2
boolean isNew(
  ModuleCompleteKey 
    moduleCompleteKey
)

boolean isNew( ModuleCompleteKey moduleCompleteKey, TimePeriod timePeriod )

Call this method to query if a given plugin module is new. A module is considered new if it has been registered within the specified time period.

Parameters:

  • moduleCompleteKey - The full key of the plugin module, as defined in the Atlassian plugin framework.
  • timePeriod - Optional time period. The default is 7 days.

Returns: true if the module is found and is new, otherwise false.

1
2
boolean isNew(
  String context,
  String key
)

boolean isNew( String context, String key, TimePeriod timePeriod )

Call this method to query if a given feature or plugin module is new. A feature or module is considered new if it has been registered within the specified time period.

Parameters:

  • context - Usually the plugin key.
  • key - Usually the module key, but can be a string of your choice that uniquely identifies the feature.
  • timePeriod - Optional time period. The default is 7 days.

Returns: true if the feature or module is found and is new, otherwise false.

Method signature - checking multiple features or modules for newnessDescription
1
2
List<
  ModuleCompleteKey
> getNew(
  List<ModuleCompleteKey>
    moduleCompleteKeys
)

List< ModuleCompleteKey > getNew( List<ModuleCompleteKey> moduleCompleteKeys, TimePeriod timePeriod )

Call this method to find the new plugin modules within a given set. A module is considered new if it has been registered within the specified time period.

Parameters:

  • moduleCompleteKeys - A collection of complete keys of plugin modules.
  • timePeriod - Optional time period. The default is 7 days.

Returns: A collection with just the new module complete keys found in the given input collection.

1
2
List<
  FeatureCompleteKey
> getNewFeatures(
  List<FeatureCompleteKey>
    featureCompleteKeys
)

List< FeatureCompleteKey > getNewFeatures( List<FeatureCompleteKey> featureCompleteKeys, TimePeriod timePeriod )

Call this method to find the new features or plugin modules within a given set. A feature or module is considered new if it has been registered within the specified time period.

Parameters:

  • featureCompleteKeys - A collection of complete keys of plugin modules or features.
  • timePeriod - Optional time period. The default is 7 days.

Returns: A collection of complete keys for just the new features or modules found in the given input collection.

Usage example: New blueprints are highlighted in the Confluence 'Create' dialog

In the Confluence 'Create' dialog, you will notice a 'NEW' lozenge next to recenty-installed blueprints. This dialog is produced by the Confluence Create Content plugin, which uses the feature discovery service to detect new blueprints. In the Confluence Create Content plugin, the DefaultBlueprintWebItemService issues the following call to the feature discovery service:

1
2
featureDiscoveryService.getNew(blueprintsModuleCompleteKeys);

Screenshot: The 'New' lozenge next to newly-installed blueprints

REST API

The Feature Discovery plugin exposes a limited REST API.

Action: Check if a given module is new

HTTP Method:GET
URL format:
1
2
https://{my.confluence.com}
  /rest
  /feature-discovery
  /latest
  /{context}/{key}

https://{my.confluence.com} /rest /feature-discovery /latest /{context}/{key} ?newPeriod=<number of seconds>

Path variables and URL parameters:

  • my.confluence.com - The base URL of your Confluence site.

  • context -- The plugin key.
  • key - The module key.
  • newPeriod=<number of seconds> - Optional time period. A module is considered new if it has been registered within the specified time period. The default is 7 days.
Sample response:
1
2
{
  "context":"com.atlassian.confluence.plugins.myplugin",
  "key":"mymodule",
  "isNew":false
}

Action: Send the server a list of modules and get back a filtered list of what's new

HTTP Method:POST
URL format:
1
2
https://{my.confluence.com}
  /rest
  /feature-discovery
  /latest/new

https://{my.confluence.com} /rest /feature-discovery/ latest/new ?newPeriod=<number of seconds>

Path variables and URL parameters:

  • my.confluence.com - The base URL of your Confluence site.

  • newPeriod=<number of seconds> - Optional time period. A module is considered new if it has been registered within the specified time period. The default is 7 days.

Body:

The post body must contain a JSON array.

Sample body:

1
2
[
  {
    "context":
      "com.atlassian.confluence.plugins.myplugin",
    "key":"mymodule"},
  {
    "context":
      "com.atlassian.confluence.plugins.myotherplugin",
    "key":"myothermodule"
  }
]

Notes

How the service detects new and existing modules

The feature discovery service listens for plugin module 'enable' events. On enabling of a module, if an entry does not already exist, the service stores the plugin key, the module key and the current time in an Active Objects table.

The service also does a full scan of all enabled plugin modules when Confluence starts up and whenever the Feature Discovery plugin is enabled or reinstalled. Items discovered during scans are considered to be installed when the system was installed, because the plugin does not have a date for them.

The effect of installation, uninstallation, enabling and disabling

  • If a plugin module is installed but is disabled by default, it will only be recognised as new when an administrator enables it.
  • The feature discovery service ignores 'uninstall' events. If a plugin is uninstalled and then re-installed, the original installation date is still stored in the system and is not updated.
  • The feature discovery service ignores 'disable' events. If an administrator disables a plugin module then re-enables it, the installation date is not updated.
  • You can override the installation date by unregistering and re-registering your plugin module inside a plugin upgrade task. This will have the effect of forcing an item to be new.

Dark features

If your plugin module has a DarkFeatureEnabledCondition on it, and that is the only condition, the plugin module is ignored. This means it will not be recognised as new until the condition is removed.

If you wish to use the dark feature functionality, ensure that the only condition on your module is a dark feature condition. If there is more than one condition, the module will be registered and its installation date will be set to the date the dark feature was installed This is mostly due to limitations in the interfaces for compound conditions.

Name clashes

Make sure your context does not clash with an existing plugin module key. If there is a clash, only the first key is registered.

More notes

More things to know:

  • The feature discovery is at the level of a plugin module (not the whole plugin).

  • The Confluence system installation date can now be programmatically accessed using the getInstallationDate() method on the SystemInformationService's ConfluenceInfo object. System content is used to estimate the date if it was not recorded when Confluence was installed.

    1
    2
    featureDiscoveryService.getNew(blueprintsModuleCompleteKeys); 
    

Rate this page: