Project Configuration SPI

On this page:

SPI API Reference

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

Get Started

Apps may store configuration that is associated with a project. The Service Provider Interface for projects 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 project configuration - for example, custom fields, users and groups, etc.

This integration point is available since SPI version 1.2.0

ProjectConfigurationHandler

The SPI for projects consists of only one interface - com.botronsoft.cmj.spi.configuration.project.ProjectConfigurationHandler.

/** * Implement this interface to handle export/import for custom configuration related to a {@link com.atlassian.jira.project.Project}. * * The implementation of this interface is responsible for serializing/deserializing project configuration data and recording references to * Jira configuration elements like users, groups, custom fields, etc. * * @see ConfigurationReferenceCollector * @see ConfigurationReferenceLookup */ @PublicSpi public interface ProjectConfigurationHandler { /** * Invoked when a configuration is being exported. This method will be called by Configuration Manager for each exported project. * Implementors may return {@link Optional#empty()} if there is no configuration to be exported for this particular project. * * Implementers may call {@link com.botronsoft.cmj.spi.configuration.ConfigurationReferenceCollector} methods to handle references to * other configuration objects. * * @param project * the currently exported {@link Project}. * @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 configuration * for this project. * * @see ExportContext */ Optional<String> exportConfiguration(Project project, ExportContext exportContext); /** * Invoked when a configuration is being imported. This method will be called by Configuration Manager for each imported project. * * Implementers can call {@link com.botronsoft.cmj.spi.configuration.ConfigurationReferenceLookup} methods to retrieve the respective * matching configuration objects referred with {@link com.botronsoft.cmj.spi.configuration.ConfigurationReferenceCollector}. * * @param configuration * the configuration as serialized by {@link ProjectConfigurationHandler#exportConfiguration(Project, ExportContext)}. * @param project * the currently imported {@link Project} instance. * @param importContext * context of the import operation. * * @see ImportContext */ void importConfiguration(String configuration, Project project, ImportContext importContext); /** * Invoked when configuration needs to be deleted. This method will be called by Configuration Manager when a project is deleted so any * configuration stored by the app and associated with this project can also be deleted. * * @param project * the deleted {@link Project} instance. */ void deleteConfiguration(Project project); }

The different methods of this interface will be invoked by Configuration Manager when:

  • The configuration for a project is exported on the source system - this happens when a snapshot is being created.

  • The configuration for a project is imported into the target system - this happens when a snapshot is being deployed and a new project is created or an existing one is being updated.

  • The configuration for a project is deleted - this happens when a project is being deleted, usually when a snapshot is deployed in Restore mode.

Configuration Serialization and Versioning

The SPI does not impose any restrictions about how the configuration of the project is serialized, only that the end result should be a String (see the return value of method exportConfiguration). Internally you can use XML, JSON, or whatever format is needed, as long as the app can deserialize it when the configuration is imported (see the method importConfiguration).

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 semantics of the stored configuration string. To ensure smooth user experience, make sure the SPI implementation in your app is backwards compatible with previous versions.

Collecting References

Your project configuration may contain references to other configuration elements in Jira, such as other fields, JQLs, Saved Filters, etc. It is important that during export Configuration Manager is notified about these references because the IDs of these elements may be different between the source and 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, that 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 a snapshot is being deployed, 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 implemented to handle this possibility.

Merge vs Restore

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 configuration for the project which already exists on the target system and only to add what is new. In restore mode, the whole project 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

Annotate the handler class with the ConfigurationManagerSpiHandler annotation:

@ConfigurationManagerSpiHandler public class SampleAnnotatedProjectConfigurationHandler implements ProjectConfigurationHandler { ... }

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

<!-- 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 needed. The classes in these packages will be scanned by Configuration Manager for the SPI annotations.

Via atlassian-plugin.xml

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

Here is the list of supported attributes:

Attribute

Purpose

Attribute

Purpose

name

The name of the SPI implementation.

Required: no

The unique key of the SPI implementation.

Required: yes

The implementation class - must extend the com.botronsoft.cmj.spi.configuration.project.ProjectConfigurationHandler interface.

Required: yes