It is simple. Really! To do things that can give a pretty good mileage during plugin configuration, especially for commercial plugins, is simple? Let us see. 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:
Writing an event listener in JIRA is quite easy.
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. Over to you to explore further! Have a look at the JIRA Development Cookbook if you liked this recipe. You will find more. Also, attached is the full code below.
20 Comments
This is neat stuff and a handy reference - thanks.
Reply
J-Tricks
3/20/2012 02:30:40 pm
Totally agree Matt :) I kind of merged 2 recipes into one for the sake of an example and I see where this can be an issue. Thanks for pointing out.
Reply
Ignasi
3/26/2013 01:07:21 am
I review project and seems me that a dependency to springframework is needed because in jira sdk it is not available as a library.
Reply
J-Tricks
3/26/2013 04:41:55 am
Yes, in the later versions, Spring is not a transitive dependency on the jira-api.
Reply
sisdog
7/17/2013 06:22:33 pm
I'm very new to JIRA and java (I'm a .net guy trying to customize JIRA). In following this example I'm getting the same dependency issue but I have no idea where this <dependency> tag goes and how, in general, this library is made available to the running JIRA app where my plugin is running. Is it always available and this tag is just a necessity to make it available to my plugin? How do I get the dependency error to go away in eclipse?
J-Tricks
7/18/2013 05:02:29 am
It goes in the pom.xml. You will have to rebuild the Eclipse project using the below command and refresh/clean in Eclipse. 7/29/2013 02:10:03 am
Is there any problem with the .zip file which you have shared above? because I have tried twice to download the file but it showing 'missing file' error.
Reply
J-Tricks
7/30/2013 03:26:55 pm
Not sure what the issue is but works fine for us. If you are still facing the issue, write to [email protected] and we will send you the zip file.
Reply
5/14/2014 05:59:30 pm
That you are my inhalation , I own couple of blogs and rarely run out from to post : (.
Reply
Brad
7/3/2014 09:53:10 am
Should this still work if the PluginLoader component and the Custom Field that it is adding are both contained int he same plugin?
Reply
J-Tricks
7/3/2014 10:41:22 am
Interesting. That might well be the case. Can you try using the Startable (https://docs.atlassian.com/jira/6.2.1/com/atlassian/jira/extension/Startable.html) interface instead of InitializingBean? JIRA will be fully initialized by then.
Reply
Adrián
6/21/2015 11:48:59 pm
You could fix the problem? i have the same
Reply
Chris
8/18/2014 07:47:28 am
I am getting the error below whenever I run atlas-run and the plugin tries to activate. I have to atlas-run and use the atlas-cli to install the plugin
Reply
J-Tricks
8/18/2014 08:49:02 am
Never seen that. Might be an issue with SDK.
Reply
Amrit
4/11/2016 06:44:47 am
Hi , I tried converting this to spring scanner way - used @Named("PluginListener")
Reply
J-Tricks
4/11/2016 09:57:37 pm
Use @ComponentImport.
Reply
Humsawani
9/4/2017 09:08:47 am
Hi..I got below error while executing this pluginListener.java.
Reply
J-Tricks
9/5/2017 07:13:49 am
It looks like you are developing against a newer version of JIRA. Please modify the code to comply with the latest API method signatures.
Reply
Humsawani
9/7/2017 02:02:01 am
Thank you J-tricks.
J-Tricks
9/7/2017 07:10:51 am
It looks like you are dealing with the Atlassian Spring Scanner issues here. Check the logs for errors. Your comment will be posted after it is approved.
Leave a Reply. |
AuthorJobin Kuruvilla - Works in Adaptavist as Head of DevOps Professional Services. Categories
All
Archives
October 2016
|