Atlassian JIRA, as we all know, is primarily an Issue Tracking and Project Tracking System. What many people do not know, though, is the power of its numerous customization capabilities, using which we can turn it into a different system altogether! Maybe a helpdesk system, a user story management system, an online approval process, and a lot more. This is in addition to the issue tracking and project tracking capabilities for which JIRA, arguably, is the best player in the market.
So what are these customizations? How can we convert the JIRA we know into a product we want? Or maybe just add extra functionalities that are specific to our organization?
The answer to these questions probably can be summarized in a single word—plugins. JIRA has given the power to its users to write plugins and customize the functionality in a way they find suitable.
But is that the only way? Definitely not! JIRA itself provides a lot of customization options through its user interface, and in more demanding cases, using property files like jira-application.properties. In some cases, you will also find yourself modifying some of the JIRA core files to tweak functionality or to work around a problem. We will see more of that in the chapters to come but the best entry point to JIRA customizations are plugins. And that is where we start our cookbook, before we move on to the in-depth details.
So, what is a JIRA plugin? JIRA itself is a web application written in Java. But that doesn't mean you need to know JAVA to write a plugin, though in most cases you will need to. You might end up writing a simple descriptor file to add few links here and there. If that makes the non-Java developer in you happy, watch out for the different plugin modules JIRA supports.
A JIRA plugin is a JAR file that has a mandatory plugin descriptor and some optional Java classes and velocity templates. The velocity templates are used to render the HTML pages associated with your plugin, but in some cases, you might also want to introduce JSPs to make use of some pre-existing templates in JIRA. JSPs, as opposed to velocity templates, cannot be embedded in the plugin, but instead they should be dropped into the appropriate folders in the JIRA web application.
The plugin descriptor, the only mandatory part of a plugin, is an XML file which must be named atlassian-plugin.xml
. This file is located at the root of the plugin. The atlassian-plugin.xml
file defines the various modules in a plugin. The different types of available plugin modules include reports, custom field types, and so on, and these are discussed in detail in the next chapter.
The process of developing a JIRA plugin can be of varying complexity depending on the functionality we are trying to achieve. The plugin development process essentially is a four step process:
Develop the plugin.
Deploy it into our local JIRA.
Test the plugin functionality.
Make changes and re-deploy the plugin, if required.
Each of these is explained in detail through the various recipes in this book!
JIRA, on start-up, identifies all the plugins that are deployed in the current installation. You can deploy multiple plugins, but there are some things you need to keep an eye on!
The atlassian-plugin.xml
file has a plugin key which should be unique across all the plugins. It is much similar to a Java package. Each module in the plugin also has a key that is unique within the plugin. The plugin key combined with the module key, separated by a colon, forms the complete key of a plugin module.
Following is a sample atlassian-plugin.xml
file without any plugin modules in it:
<!-- the unique plugin key --> <atlassian-plugin key="com.jtricks.demo" name="Demo Plugin" plugins-version="2"> <!-- Plugin Info --> <plugin-info> <description>This is a Demo Description</description> <version>1.0</version> <!-- optional vendor details --> <vendor name="J-Tricks" url="http://www.j-tricks.com"/> </plugin-info> . . . 1 or more plugin modules . . . </atlassian-plugin>
The plugin, as you can see, has details such as description, version, vendor-details, and so on.
When a plugin is loaded, all the unique modules in it are also loaded. The plugin classes override the system classes and so if there is an action that has the same alias name as that of a JIRA action, it is the plugin action class that will be loaded. We will see more about extending actions in the coming chapters.
Suppose you have a report module in your plugin, it will look as follows:
<report key="demo-report" name="My Demo Report" ....> ... </report>
The plugin key, in this case, will be com.jtricks.demo
and the module key will be com.jtricks.demo:demo-report
.
Hang on, before you start writing your little plugin for a much wanted feature, have a look at the Atlassian plugin exchange to see if someone else has already done the dirty work for you!
Atlassian plugin exchange is a one stop shop where you can find the entire list of commercial and open source plugins people around the world have written. See https://plugins.atlassian.com/search/by/jira for more details.
A common scenario that people encounter while deploying their plugin is when the plugin fails to load even though everything looks fine. Make sure your plugin's key is unique and is not duplicated in one of yours or another third-party's plugin!
The same applies to individual plugin modules.
Now that we know what a plugin is, let 's aim at writing one! The first step in writing a JIRA plugin is to set up your environment, if you haven't done that already. In this recipe, we will see how to set up a local environment.
To make plugin development easier, Atlassian provides the Atlassian Plugin Software Development Kit (SDK). It comes along with Maven and a pre-configured settings.xml
to make things easier.
Atlassian Plugin SDK can be used to develop plugins for other Atlassian products, including Confluence, Crowd, and so on, but we are concentrating only on JIRA.
The following are the pre-requisites for running the Atlassian plugin SDK:
The default port for the SDK: 2990 should be available. This is important because different ports are reserved for different Atlassian products.
JDK Java version 1.5 - 6 must be installed.
Make sure
JAVA_HOME
is set properly and the commandjava –version
outputs the correct Java version details.And of course, JIRA 4.x+ should be installed in your development environment.
Note
Make sure you use a context path for your JIRA because there are known issues with the SDK not working when the context path is empty. See https://studio.atlassian.com/browse/AMPS-122 for more details.
Once we have Java installed and the port ready, we can download the latest version of Atlassian Plugin SDK from https://maven.atlassian.com/content/repositories/atlassian-public/com/atlassian/amps/atlassian-plugin-sdk/.
Unzip the version into a directory of your choice. Let's call this directory
SDK_HOME
going forward.Add the SDK's bin directory into the environment
PATH
variable.Create a new environment variable
M2_HOME
pointing to the Apache-Maven directory in your SDK Home.A lot of commonly used dependencies are already available in the repository folder embedded in the SDK. To use this, edit the
settings.xml
underM2_HOME/conf/
and modify thelocalRepository
attribute to point to the embedded repository folder. By default, it will use theUSER_HOME/.m2/repository
.Install the IDE of your choice. Atlassian recommends Eclipse, IntelliJ IDEA, or NetBeans, as they all support Maven.
Ready, Set, Go…
With these steps executed properly, we have a development environment for JIRA plugins.
The next step is to create a Skeleton plugin, import it into your IDE, and start writing some code! Creating the Skeleton plugin, deploying it, and so on, is explained in detail in the following recipes.
Even though the aforementioned steps will work in most cases, we will come across scenarios where the setting up of the development environment is not that straightforward. For example, there are extra settings needed for Maven if the machine is behind a firewall. You might even have a local Maven version already installed. In this section, we will see some useful tips on similar cases.
If you are behind a firewall, make sure you configure the proxy in the Maven settings.xml
file. The proxy can be configured as follows:
<settings> . <proxies> <proxy> <active>true</active> <protocol>http</protocol> <host>proxy.demo.com</host> <port>8080</port> <username>demouser</username> <password>demopassword</password> <nonProxyHosts>localhost|*.demosite.com</nonProxyHosts> </proxy> </proxies> . </settings>
Find out more about that and other aspects of Maven at http://maven.apache.org/index.html.
If you are a developer, in many cases you will have Maven already installed in your local machine. In that case, point M2_HOME
to your local Maven and update the respective settings.xml
with the repository details in the default settings.xml
that ships with Atlassian plugin SDK.
If you are using IntelliJ IDEA, it is an easy job because IDEA integrated Maven out-of-the-box. Just load the project by selecting the pom.xml
!
If you are using Eclipse, make sure you have M2Eclipse installed. This is because Eclipse integrates Maven through the Sonatype M2Eclipse plugin. You can find more details on configuring this at http://confluence.atlassian.com/display/DEVNET/Configuring+Eclipse+to+use+the+SDK.
If you see Maven download errors like Could not resolve artifact, make sure you verify the following:
Entry in Maven
settings.xml
is correct. That is, it points to the correct repositoriesProxy configuration is done if required
Antivirus in the local machine is disabled if none of the above works! Seriously, it makes a difference.
In this recipe, we will look at creating a skeleton plugin. We will use the Atlassian Plugin SDK to create the skeleton!
Make sure you have the Atlassian Plugin SDK installed and a version of JIRA 4.x running on your local machine.
Open a command window and go to the folder where you want to create the plugin.
Note
Make sure you use a directory without any spaces because there are known issues with the SDK not working in directories with spaces in it. See https://studio.atlassian.com/browse/AMPS-126 for details.
Type
atlas-create-jira-plugin
and press Enter.Enter the
groupID
when prompted. GroupID would normally be coming from your organization name and mostly resembles the Java package. Of course, you can enter a different package name as we move forward if you want to keep it separate. GroupID will be used to identify your plugin along withartifactId
.For example:
com.jtricks.demo
.Enter the
artifactId
—the identifier for this artifact. Do not use spaces here.For example:
demoplugin
.Version
—the default version is1.0-SNAPSHOT
. Enter a new version if you want to change it or press Enter to keep the default.For example:
1.0
Package
—press Enter if the package value is same as thegroupID
. If not, enter the new value here and press Enter.For example,
com.jtricks.mypackage
Confirm the selection when prompted. If you want to change any of the entered values, type
N
and press Enter.Wait for the
BUILD SUCCESSFUL
message. You might see a few warnings which can be ignored.
A skeleton plugin is nothing but a set of directories and sub directories along with a pom.xml
(Maven Project Object Model) file and some sample Java and XML files in the appropriate folders.
Here is a snapshot of how the project will look like in Eclipse. It also shows the design view of the default atlassian-plugin.xml
file:

As you can see, there is a pom.xml
at the root level and a src
folder. A sample LICENSE
file and a README
file are also created for you at the root level.
Under the src
folder, you will find out two folders, main
and test
, with identical folder structure. All your main Java code goes under the main
folder. Any JUnit tests you write will go into the same location under the test
folder. There is an additional folder, it
, under the test folder where all the integration tests will go!
You will find the plugin descriptor under src/main/resources
with sample values already populated in it. The values in the preceding screenshot are populated from the pom.xml
. In our case, the plugin key will be populated as com.jtricks.demo:demoplugin
when the plugin is built.
There are two more folders under the src/test. src/test/resources
, which will hold any resources required for unit tests or integration tests, and the src/test/xml
folder can hold the XML data from any other JIRA instance. If the XML is supplied, the SDK will use it to configure the JIRA instance before running the integration tests.
So, that is our plugin Skeleton. All that is pending is some useful Java code and proper module types in the atlassian-plugin.xml
file!
Sometimes, for the geeks, it is much easier to run a single command to create a project without bothering about the step-by-step creation. In this section, we will quickly see how to do it. We will also have a look at how to create an Eclipse project if you opt out of installing m2eclipse.
You can ignore the interactive mode by passing the parameters like groupID
, artifactId
, and so on, as arguments to the atlas-create-jira-plugin
command.
atlas-create-jira-plugin -g my_groupID -a my_artefactId -v my_version -p my_package –non-interactive
In this example, for the values we saw previously, the single line command will be:
atlas-create-jira-plugin -g com.jtricks.demo -a demoplugin -v 1.0 -p com.jtricks.mypackage –non-interactive
You can pick and choose the parameters and provide the rest in an interactive mode as well!
If you are not using m2eclipse, just run the following command from the folder where you have the
pom.xml
file:
atlas-mvn eclipse:eclipse
This will generate the plugin project for Eclipse and you can then import this project into the IDE.
Type atlas-mvn eclipse:clean eclipse:eclipse
if you want to clean the old project and create again!
With IDEA or m2eclipse, just opening a file will do. That is, you can just import the project using the option File | Import | Existing Maven Projects, and select the relevant project.
In this recipe, we will see how to deploy a plugin into JIRA. We will see both the automated deployment using Atlassian Plugin SDK and the manual deployment.
Make sure you have the development environment set up, as we discussed earlier. Also the skeleton plugin should now have the plugin logic implemented in it.
Installing a JIRA plugin using Atlassian Plugin SDK is a cake walk. Here is how it is done:
Open a command window and go to your plugin's root folder, that is, the folder where your
pom.xml
resides.Type
atlas-run
and press Enter. It is possible to pass more options as argument to this command for which the details can be found at: http://confluence.atlassian.com/display/DEVNET/atlas-run.You will see a lot of things happening as Maven downloads all the dependent libraries into your local repository. As usual, it is going to take lot of time when you run it for the first time.
If you are on Windows, and if you see a security alert popping up, click on Unblock to allow incoming network connections.
When the installation is completed, you will see the following message:
[WARNING] [talledLocalContainer] INFO: Server startup in 123558 ms [INFO] [talledLocalContainer] Tomcat 6.x started on port [2990] [INFO] jira started successfully and available at http://localhost:2990/jira [INFO] Type CTRL-C to exit
Open
http://localhost:2990/jira
in your browser.Login using the username as admin and password as admin.
Test your plugin! You can always go to the Administration | Plugin menu to confirm that the plugin is deployed properly.
If you already have a local JIRA installed or if you want to manually install your plugin for some reason, all you need to do is to package the plugin JAR and copy it across to the JIRA_Home/plugins/installed-plugins
directory.
You can package the plugin using the following command:
atlas-mvn clean package
Use atlas-mvn clean install
if you also want to install the package plugin into your local repository.
There is only one single command that does the whole thing: atlas-run
. When you execute this command, it does the following:
Builds your plugin JAR file
Downloads the latest/specified version of JIRA to your local machine if it is the first time you're running the command.
Creates a virtual JIRA installation under your plugin/target folder.
Copies the JAR file into the /
target/jira/home/plugins/installed-plugins
directoryStarts JIRA in the Tomcat container.
Now, if you look at your target folder, you will see a lot of new folders which were created for the virtual JIRA installation! The two main folders are the container
folder, which has the Tomcat container setup, and the jira
folder, which has the JIRA WAR along with the JIRA home setup!
You will find the database (HSQLDB
), indexes, backups, and attachments under /target/jira/home
. And you will see your jira-webapp
at /target/container/tomcat6x/cargo-jira-home/webapps/jira
.
If you have any JSPs that need to be put under the webapp, you will have to copy it to the appropriate folder under the aforementioned path!
There's more to this.
As mentioned earlier, atlas-run
deploys the latest version of JIRA. But what if you want to deploy the plugin into an earlier version of JIRA and test it?
There are two ways to do it:
Mention the JIRA version as an argument to
atlas-run
; make sure you runatlas-clean
, if you already have the latest version deployed:Run
atlas-clean
(if required).Run
atlas-run –v 4.1.2
oratlas-run –version 4.1.2
if you are developing for JIRA version 4.1.2. Replace the version number with a version of your choice.
Permanently change the JIRA version in your plugin
pom.xml
:Go to your
pom.xml
.Modify the
jira.version
property value to the desired version.Modify the
jira.data.version
to a matching version.
This is how it will look for JIRA 4.1.2:
<properties> <jira.version>4.1.2</jira.version> <jira.data.version>4.1</jira.data.version> </properties>
Suppose you added some data on to virtual JIRA, how do you retain it when you clean start-up JIRA next time?
This is where a new SDK command comes to our rescue.
After the atlas-run
is finished, that is, after you pressed Ctrl + C, execute the following command:
atlas-create-home-zip
This will generate a file named generated-test-resources.zip
under the target folder. Copy this file to the /src/test/resources
folder or any other known locations. Now modify the pom.xml
to add the following entry under configurations in the maven-jira-plugin
:
<productDataPath>${basedir}/src/test/resources/generated-test-resources.zip</productDataPath>
Modify the path accordingly. This will reuse the configurations the next time you run atlas-run
.
Missing JAR file exception? Make sure the local-repository attribute in the
settings.xml
file points to the embedded Maven repository that comes with the SDK. If the problem still persists, manually download the missing JAR files anduse atlas-mvn install
to install them in to the local repository.Watch out for the proxy settings or antivirus settings that can potentially block the download in some cases!
BeanCreationException? Make sure your plugin is of version 2. Check your
atlassian-plugin.xml
to see if the following entry is there or not. If not, add the entry:<atlassian-plugin key="${project.groupId}.${project.artifactId}" name="${project.artifactId}" plugins-version="2">
Run atlas-clean
followed by atlas-run
after you do that.
Now that we have deployed the test plugin, it is time to add some proper logic, re-deploy the plugin, and test it. Making the changes and re-deploying a plugin is pretty easy. In this recipe, we will quickly look at how to do this.
You can make changes to the plugin and re-deploy it while the JIRA application is still running. Here is how we do it:
Keep the JIRA application running in the window where we ran
atlas-run
.Open a new command window and go to the root plugin folder where your
pom.xml
resides.Run
atlas-cli
.Wait for the command—
Waiting for messages
.Run
pi
. Pi stands for "plugin install" and this will compile your changes, package the plugin JAR, and install it into theinstalled-plugins
folder.
Now, there is one thing you need to keep an eye on! Not all the plugin modules can be redeployed like this prior to JIRA 4.4. The following is a list of the plugin modules that can be reloaded with pi
in JIRA 4.0.x:
ComponentImport
Gadget
ModuleType
Resource
REST
ServletContextListener
ServletContextParameter
ServletFilter
Servlet
WebItem
WebResource
WebSection
If your plugin module is not there in the preceding list or if the changes doesn't seem to be reflected, press Ctrl + C in the command window running atlas-run
and re-run the atlas-run
command. That will re-deploy the plugin and restart JIRA.
Post JIRA 4.1, SDK supports reloading of more modules, but whether it works or not depends on what the module does internally.
It is also possible to run the plugin in debug mode and point your IDE's remote debugger to it.
Following are the steps to do this in Eclipse:
Use
atlas-debug
instead ofatlas-run
.Once the virtual JIRA is up and running with tour plugin deployed in it, go to Run | Debug Configurations in Eclipse.
Create a new
Remote Java Application
.Give a name, keep the defaults, and give the port number as
5005
. This is the default debug port on which the virtual JIRA runs.Happy Debugging!
In the world of Test Driven Development (TDD), writing tests is a part and parcel of the development process. I don't want to bore you with why testing is important! Let us just say, all these holds true for JIRA plugin development as well.
In this recipe, we will see the various commands for running unit tests and integration tests in JIRA plugins.
Make sure you have the plugin development environment set up and the skeleton plugin created!
You might have noticed that there are two sample test files, one each for unit tests and integration tests, created under the src/test/java/your_package/
and src/test/java/it
folders.
Once you have it ready, it is time to write some tests and run those tests to make sure things work as expected!
The first step is to write some tests! We recommend you to use some powerful testing frameworks like JUnit in collaboration with mocking frameworks like PowerMock or Mockito. Make sure you have the valid dependencies added on to your pom.xml
.
Let us now make a huge assumption that you have written a few tests!
Following is the command to run your unit tests from the command line:
atlas-unit-test
The normal Maven command atlas-mvn clean test
also does the same thing. If you are running the integration tests, the command to use is:
atlas-integration-test
Or the Maven command: atlas-mvn clean integration-test
.
Once we are on to the stage of running tests, we will see it failing at times. There comes the need for debugging. Checkout the *.txt
and *.xml
files created under target/ surefire-reports/
which has all the required information on the various tests that are executed.
Now, if you want to skip the tests at the various stages, use –skip-tests
. For example, atlas-unit-test --skip-tests
will skip the unit tests.
You can also use the Maven options directly to skip the unit/integrations tests or both together.
-Dmaven.test.skip=true
: skips both unit and integration tests-Dmaven.test.unit.skip=true
: skips unit tests-Dmaven.test.it.skip=true
: skips integration tests
The atlas-unit-test
command merely runs the related Maven command: atlas-mvn clean test
in the backend to execute the various unit tests. It also generates the outputs into the surefire-reports
directory for reference or debugging.
The atlas-integration-test
does a bit more. It runs the integration tests in a virtual JIRA environment. It will start up a new JIRA instance running inside a Tomcat container, set up the instance with some default data including a temporary license that lasts for three hours, and execute your tests!
How does JIRA differentiate between the unit tests and integration tests? This is where the folder structure plays an important role. Anything under the src/test/java/it/
folder
will be treated as integration tests and everything else will be treated as unit tests!
There is more to it.
While atlas-integration-test
makes our life easier by setting up a JIRA instance with some default data in it, we might need some custom data as well to successfully run a few functional tests.
We can do this in a couple of steps:
Export the data from a pre-configured JIRA instance into XML.
Put it under the
src/test/xml/
directory.Provide this path as the value for the
jira.xml.data.location
property in thelocaltest.properties
undersrc/main/resources
.
The XML resource will then be imported to JIRA before the tests are executed.
Just like the atlas-run
command, you can use the -v
option to test your plugin against a different version of JIRA. As before, make sure you do an atlas-clean
before running the tests if you had tested it against another version before.
You can also use the -c
option to test it against a different version of the Tomcat container.
For example, atlas-clean && atlas-integration-test -v 3.0.1 -c tomcat5x
will test your plugin against JIRA version 3.0.1 using Tomcat container 5.