In this short recipe, let us look at creating a custom field automatically during a plugin installation and deleting it while un-installation. Same applied for enabling/disabling of the plugin.
All you need to do is 2 simple steps:
- Write an event listener. We will use the atlassian-event library here.
- Implement the Spring interfaces InitializingBean and DisposableBean to capture the plugin lifecycle events.
Writing an event listener in JIRA is quite easy.
- Import the EventPublisher instance used to register events. You can do this by adding the following component in atlassian-plugin.xml
<component-import key="eventPublisher" interface="com.atlassian.event.api.EventPublisher"/> - Now, instantiate our listener class
<component key="eventListener" >
<description>A Listener for plugin lifecycle events</description>
</component>
So, what's the deal with a listener here? Basically, Atlassian plugins are implemented as Spring dynamic modules and the atlassian-plugin.xml is transformed into a Spring XML bean configuration before it is loaded by the JIRA. Since our listener is registered as a <component>, it will become a Sping bean when loaded and hence we can use the Spring interfaces InitializingBean and DisposableBean to capture plugin lifecycle events.
Whenever the component (here PluginListener) is registered, i.e. during the enabling or installation of the plugin, afterPropertiesSet() method from InitializingBean is invoked. Similarly, when the component is un-registered, during plugin disabling or un-installation, destroy() method from DisposableBean is invoked.
Our listener will look like this:
public class PluginListener implements InitializingBean, DisposableBean {
@Override
public void destroy() throws Exception {
//Handle plugin disabling or un-installation here
}
@Override
public void afterPropertiesSet() throws Exception {
//Handle plugin enabling or installation here
}
}
That's it! How does it help during plugin configurations? Read on..
Suppose we have a plugin that needs a Text custom field for its functionality, with a pre-defined name. Users will have to configure this manually when the install a plugin and remove it when they un-install it. This is also prone to manual errors. Why not do this in the plugin itself?
Let us create a Text CF during the plugin enabling/installation and associate it with a screen. We will also remove this when the plugin is disabled or un-installed. The code is an extention to the above and self explanatory. Here it goes:
public class PluginListener implements InitializingBean, DisposableBean {
private static final String TEST_TEXT_CF = "Test Text CF";
private final CustomFieldManager customFieldManager;
private final FieldScreenManager fieldScreenManager;
public PluginListener(CustomFieldManager customFieldManager, FieldScreenManager fieldScreenManager) {
this.customFieldManager = customFieldManager;
this.fieldScreenManager = fieldScreenManager;
}
@Override
public void destroy() throws Exception {
//Get the already installed custom field by name
CustomField cField = this.customFieldManager.getCustomFieldObjectByName(TEST_TEXT_CF);
//Remove if not null
if (cField != null) {
this.customFieldManager.removeCustomField(cField);
}
}
@Override
public void afterPropertiesSet() throws Exception {
//Create a list of issue types for which the custom field needs to be available
List<GenericValue> issueTypes = new ArrayList<GenericValue>();
issueTypes.add(null);
//Create a list of project contexts for which the custom field needs to be available
List<JiraContextNode> contexts = new ArrayList<JiraContextNode>();
contexts.add(GlobalIssueContext.getInstance());
//Add custom field
CustomField cField = this.customFieldManager.createCustomField(TEST_TEXT_CF, "A Sample Text Field",
this.customFieldManager.getCustomFieldType("com.atlassian.jira.plugin.system.customfieldtypes:textfield"),
this.customFieldManager.getCustomFieldSearcher("com.atlassian.jira.plugin.system.customfieldtypes:textsearcher"),
contexts, issueTypes);
// Add field to default Screen
FieldScreen defaultScreen = fieldScreenManager.getFieldScreen(FieldScreen.DEFAULT_SCREEN_ID);
if (!defaultScreen.containsField(cField.getId())) {
FieldScreenTab firstTab = defaultScreen.getTab(0);
firstTab.addFieldScreenLayoutItem(cField.getId());
}
}
}
Here is a screenshot on how the field looks like once it is created.

plugin-listener.zip |