Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

SPI API Reference

If you need more technical information on the latest SPI packages and interfaces, please read the complete API reference.

Get Started

Jira apps may store configuration data that does not belong to any project but applies to all projects - i.e., "global" configuration. The Service Provider Interface for global app configuration provides the facilities for moving such configuration between different Jira instances. Configuration Manager will handle all the heavy load around moving the right configuration elements which are referenced in the global configuration - for example, custom fields, users and groups, etc. When creating a snapshot, users will be allowed to choose whether to include a global app configuration. You can learn more about migrating global app data with CMJ from this document.

Info

This integration point is available since SPI 1.5.0 and requires Configuration Manager version 6.4.5.

GlobalConfigurationHandler

The SPI for global app configuration consists of only one interface - com.botronsoft.cmj.spi.configuration.global.GlobalConfigurationHandler.

Code Block
/**
 * Implement this interface to handle export/import for custom configuration which is global for the Jira instance.
 *
 * The implementation of this interface is responsible for serializing/deserializing global configuration data and recording references to
 * Jira configuration elements like users, groups, custom fields, etc.
 *
 * @see ConfigurationReferenceCollector
 * @see ConfigurationReferenceLookup
 */
@PublicSpi
public interface GlobalConfigurationHandler {

	/**
	 * Invoked when a configuration is being exported. This method will be called by Configuration Manager when the app which implements it
	 * is selected for export. Implementors may return {@link Optional#empty()} if there is no configuration to be exported.
	 *
	 * Implementers may call {@link ConfigurationReferenceCollector} methods to handle references to other configuration objects.
	 *
	 * @param exportContext
	 *            context of the export operation.
	 * @return an {@link Optional} with the exported configuration or {@link Optional#empty} if the app does not store any global
	 *         configuration.
	 *
	 * @see ExportContext
	 */
	Optional<String> exportConfiguration(ExportContext exportContext);

	/**
	 * Invoked when a configuration is being imported.
	 *
	 * Implementers can call {@link ConfigurationReferenceLookup} methods to retrieve the respective matching configuration objects referred
	 * with {@link ConfigurationReferenceCollector}.
	 *
	 * @param configuration
	 *            the configuration as serialized by {@link GlobalConfigurationHandler#exportConfiguration(ExportContext)}.
	 * @param importContext
	 *            context of the import operation.
	 *
	 * @see ImportContext
	 */
	void importConfiguration(String configuration, ImportContext importContext);

	/**
	 * Invoked when configuration needs to be deleted. This method will be called by Configuration Manager when app data is deleted.
	 *
	 */
	void deleteConfiguration();
}
Info

An app may declare only one implementation of this interface.

...

  • exportConfiguration is invoked when a project snapshot is being created, and the global configuration of an app that implements this interface is selected for export. The method will also be invoked during a system snapshot creation if the "Export Global App Data" option is selected. The method may return an empty Optional if there is no global configuration currently present.

  • importConfiguration is invoked when a snapshot with a global configuration for a given app is being deployed, and the global configuration is not empty - i.e. if exportConfiguration returned a non-empty Optional during snapshot creation.

  • deleteConfiguration is invoked when a snapshot with a global configuration for a given app is deployed. The global configuration is empty - i.e. if exportConfiguration returned an empty Optional during snapshot creation.

Info

Why is the exportConfiguration methodcalled during deployment?

A major phase of the deployment process in CMJ is the deep change and impact analysis. To perform it, CMJ compares Jira's configuration between the source and the target instances. The snapshot being imported is a model of the source Jira configuration built at the time when it was exported. So, CMJ creates another model of the target instance by exporting Jira configuration on that instance at the time of the deployment.

The exportConfiguration method is called during deployment so that the global app configuration of the apps on the target instance is included in the target instance model and compared to the global app configuration of the apps in the snapshot during the Analyze phase.

Configuration Serialization and Versioning

The SPI does not impose any restrictions on how the configuration in each property value is serialized, only that the end result should be a String.

Warning

When you are implementing the SPI, it is very important to think about configuration versioning in advance. Consider the following situation - source Jira has version 1.2 of your app, while target Jira has version 1.3, and there is a change in the number and/or semantics of stored configuration properties (the key-value map). To ensure smooth user experience, make sure the SPI implementation in your app is backwards compatible with previous versions.

Collecting References

The global app data may contain references to other configuration elements in Jira, such as custom fields, saved filters, etc. It is essential that during export, Configuration Manager is notified about these references because the IDs of these elements may be different between the source and the target instance, and Configuration Manager will match them and provide the correct IDs during import.

This can be achieved by invoking the methods of the ConfigurationReferenceCollector interface, accessible via the ExportContext interface. The key must be a unique identifier, which will be used when importing the configuration to resolve the reference on the target instance. The keys need to be unique only within the type of the configuration element - i.e., you can use the same key for a resolution or a status. In this sense, the Jira internal identifiers can be used as keys as well.

Resolving References

When deploying a snapshot, all collected references to other configuration elements must be resolved because the identifiers of these elements are most probably different on the target system.

Use the ConfigurationReferenceLookup interface, accessible via the ImportContext interface. It provides convenient methods for resolving references by the same keys which were provided when collecting these references. The methods return java.util.Optional, because, in certain situations, references may be unresolvable. SPI implementations should be developed to handle this possibility.

Merge vs. Restore

Info

This API is available since SPI version 1.6.1.

When a configuration is imported, it may be necessary to distinguish between the merge and restore modes in which Configuration Manager operates. In merge mode, a handler may choose to keep the global app configuration that already exists on the target system and only adds what is new. In restore mode, the whole configuration may be overwritten. A handler may check the current mode by retrieving the ImportMode value via ImportContext.getImportMode().

Registering the Handler with Configuration Manager

There are two options for registering the handler with Configuration Manager - via Java annotations or via the atlassian-plugin.xml

Via Java annotations

Info

Registering the handler with Configuration Manager via Java annotations is available since SPI version 1.7.0.

...

Code Block
@ConfigurationManagerSpiHandler
public class SampleAnnotatedGlobalConfigurationHandler implements GlobalConfigurationHandler {
...
}

In addition, the following entry needs to be added to the atlassian-plugin.xml which specifies the Java packages which contain the handlers:

Code Block
<!-- Configuration Manager SPI Handler Packages -->
<configurationManagerSpiHandler key="configuration-manager-spi-handler-packages">
  <package>com.mycompany.app.handlers</package>
</configurationManagerSpiHandler>

Only one entry is needed per app - multiple packages may be defined if required. Configuration Manager will scan the classes in these packages for the SPI annotations.

Via atlassian-plugin.xml

Another approach is to directly declare the handler in atlassian-plugin.xml and create a <globalConfigurationHandler> tag with the attributes below.

Code Block
<!-- Configuration Manager SPI -->
<globalConfigurationHandler key="my-global-app-handler" class="com.mycompany.app.MyGlobalAppConfigurationHandlerImpl"/>

Here is the list of supported attributes:

Attribute

Purpose

Code Block
key

The unique key of the SPI implementation.

Required: yes

Code Block
class

The implementation class - must extend the com.botronsoft.cmj.spi.configuration.global.GlobalConfigurationHandler.

Required: yes