This tutorial applies to JIRA 5.0 and later.
Level of experience:
This is an advanced tutorial. You should have completed at least one intermediate tutorial before working through this tutorial. See the list of developer tutorials.
It should take you approximately 1 hour to complete this tutorial.
On this page:
- Overview of the tutorial
- Step 1. Create the plugin project
- Step 2. Modify the POM metadata and add dependencies
- Step 3. Add the message handler module to the plugin descriptor
- Step 4. Add UI text to the i18n resource file
- Step 5. Create the MessageHandler implementation
- Step 6. Build, install and run the plugin
- Step 7: Implement a real message handler back-end
- Step 8. Improve the configuration UI
- Step 9. Test the finished plugin
Overview of the tutorial
Administrators can configure JIRA to receive and process mail messages sent to a particular account on an IMAP or a POP server. Depending on the message handler selected, JIRA can create an issue or add a comment to an issue based on message content.
JIRA provides several built-in mail handlers, as described in Creating Issues and Comments from Email. In addition, plugin developers can create custom mail handlers by implementing a message-handler module.
This tutorial shows you how to build a message handler plugin. To keep things simple, the plugin will turn email content into a comment for a specific issue in a project. Also, we'll use JIRA's ability to read mail files from a local directory rather than configuring a mail server. Your completed plugin will consist of the following components:
- Java classes encapsulating the plugin logic.
- Resources for display of the plugin user interface (UI).
- A plugin descriptor (XML file) to enable the plugin module in the Atlassian application.
When you have finished, all these components will be packaged in a single JAR file.
To complete this tutorial, you need to know the following:
- The basics of Java development: classes, interfaces, methods, how to use the compiler, and so on.
- Familiarity with development tools, such as Maven and IDEs.
- How to create an Atlassian plugin project using the Atlassian Plugin SDK.
- Configuring JIRA system settings.
We encourage you to work through this tutorial. If you want to skip ahead or check your work when you have finished, you can find the plugin source code on Atlassian Bitbucket. Bitbucket serves a public Git repository containing the tutorial's code. To clone the repository, issue the following command:
Alternatively, you can download the source by choosing Downloads > Branches here: https://bitbucket.org/atlassian_tutorial/jira-add-email-handler.
Step 1. Create the plugin project
In this step, you'll use an
atlas command to generate stub code for your plugin. The
atlas commands are part of the Atlassian Plugin SDK, and automate much of the work of plugin development for you.
- If you have not already set up the Atlassian Plugin SDK, do that now: Set up the Atlassian Plugin SDK and Build a Project.
- Open a terminal and navigate to the directory where you want to create the project directory.
Enter the following command to create a plugin skeleton:
Choose 1 for JIRA 5 when asked which version of JIRA you want to create the plugin for.
As prompted, enter the following information to identify your plugin:
- Confirm your entries when prompted.
Step 2. Modify the POM metadata and add dependencies
It is a good idea to familiarise yourself with the project configuration file, known as the POM (Project Object Model definition file). The POM declares your plugin's dependencies, build settings, and metadata (information about your plugin).
Modify the POM as follows:
- Change to the
directory created by the SDK.
- Open the
pom.xmlfile for editing.
Add your company or organisation name and your website as the
urlvalues of the
nameelement to something more readable:
This is the name of your plugin that will appear on the Manage Add-ons page in the JIRA administration console.
Next add the dependencies your plugin will rely on. Add the following dependencies to the ones added by the SDK:
providedfor these dependencies, since the JIRA plugin framework includes those JARs. If you were to use a different scope, it would result in classloader issues related to duplicate classes available on the plugin classpath.
- Save the
Step 3. Add the message handler module to the plugin descriptor
For most plugin module types, but not all, you can use the Atlassian Plugin SDK to add modules to your plugin. The module you need for this plugin,
message-handler, is one of the exceptions. You'll need to add it by hand.
- Open the
atlassian-plugin.xmlfile for editing. The file is located in
message-handlermodule as a child of
classattribute identifies our handler implementation class,
weightvalue of 0 means that the handler will be first in the handler selection list in the administration user interface. (Built-in handlers come with a weight of 1 to 5, the lower weight the earlier in the list the handler will be displayed.) Also notice the
add-edit-urlvalue. It defines the resource used to configure our handler. For now, we've set it to a resource that comes with JIRA. We'll describe that resource, and replace it with our own a little later.
- Save the file.
Step 4. Add UI text to the i18n resource file
When you created the plugin, the SDK generated an i18n resources file for you. This is where our UI text comes from. Add a UI text string to it as follows:
- Open the
mail-handler-demo.propertiesresource file for editing. It is located in
Add the following property to the resource file:
Step 5. Create the MessageHandler implementation
Finally let's create the message handler, the one referenced in the plugin descriptor. We're going to make it simple to start with, and build on this class as we go.
- Create a new file named
Add the following contents to the file:
As it turns out, our initial message handler code doesn't do a lot. But it forms a good foundation for building upon, and it gives us a chance to reflect on some concepts. Notice the methods in the class:
The init()method is called at message handler set up time, that is, when the administrator configures the message service and the message handler is instantiated (dependency injection works here). The message service may fetch mail via POP or IMAP, using the
MailFetcherServiceclass. Or it may read messages from a file system, using the
paramsargument contains the message handler configuration. But a plugin developer can choose to keep that data elsewhere, if desired, such as in PropertySet or by using ActiveObjects. The module code may use the
monitorargument to report problems spotted while initializing the handler.
- Each time a message is successfully fetched and read, JIRA calls the
messageparameter contains the message itself and
contextis a thin abstraction that allows you to develop handlers that work in test mode (where they should not modify JIRA) and in normal production mode. More about that soon.
- Save the file.
Step 6. Build, install and run the plugin
Let's start JIRA and see what we've got have so far:
- Open a command window and go to the plugin root directory (where the
- Enter this SDK command:
This command downloads and starts JIRA with your plugin installed.
- Once JIRA is done starting up, open the JIRA interface in a browser.
- Log in with the default username and password, admin/admin.
- Create a simple issue tracking project when prompted.
- Open the cog menu and choose System.
- Click Incoming Mail from the left menu. It's under the section of the menu labelled Mail.
- Click Add incoming mail handler. You should see something like this:
That's the mail handler you added!
- Give your handler a name (the name can be anything; we won't be saving it this time), and click Next.
Notice the configuration form for this handler.
How does JIRA know what to display in this step of the wizard? It gets it from the
add-edit-urlparameter in your
message-handlerdeclaration. If you recall, you set that attribute to
/secure/admin/EditHandlerDetailsUsingParams!default.jspa. JIRA 5.0 and later provides this built-in resource for the benefit of legacy (JIRA 4.x) mail handlers. Legacy handlers take configuration parameters in the form of a comma-delimited list of name-value pairs. If you were to enter Handler params text in the field, such as
issueKey=TST-1, otherParam=abc, your message handler's
init()method would get a
paramsmap constituted of:
- Cancel your mail handler configuration for now.
Let's make our Java class do something more meaningful. Also, we'll update our configuration interface resource, the
add-edit-url target, for the post-5.0 world.
From here on out, you can keep JIRA running while you continue development of the plugin. To reload your plugin, use FastDev. It reinstalls your plugin behind the scenes as you work. Alternatively, you can keep the application running in one command window and use the CLI (command line interface) in another window to dynamically re-install your plugin after each change.
- Open a new command window and go to the plugin's root folder (where the
atlas-clito start the CLI.
- Wait until you see a message,
Waiting for commands.
pi(plugin install) to compile, package and install the plugin.
- Go back to your browser and test your changes. (You may need to refresh the browser page first.)
- Continue making changes to your code.
piagain. And so on.
The full instructions are in the SDK guide.
Step 7: Implement a real message handler back-end
Our message handler needs one configuration parameter, the issue key defining the issue it will add comments to. We would like to validate the correctness of this parameter, whether such an issue exists, whether it's editable, and whether the sender has permissions to comment on it.
As we are going to use such validation in at least two places, let's encapsulate it as a separate component.
- Create a new file named
Give it the following contents:
Add the validator as a
DemoHandler.javaagain and replace its content with the following:
Now our code is actually doing something. The
init()method simply makes sure the parameter passed in the handler configuration UI is not empty. The
handleMessage()method does the work of taking a mail messages from JIRA's mail service, and making an issue comment out of it. See the code comments for line-by-line details.
- Save the file.
Step 8. Improve the configuration UI
So we have now a fully functional mail handler but it still has a rudimentary, error-prone UI. Let's fix it and unleash the power of the custom handler configuration UI:
Add a WebWork module to your plugin by adding the following element to
This module will perform the function of rendering the configuration UI for the handler.
Replace the message-handler module you added to the descriptor earlier with the following:
The message handler will now use our webwork action as the resource for adding or editing our handler settings.
Create a new file named
src/main/java/com/example/plugins/tutorial/jira/mailhandlerdemodirectory, and give it the following contents:
The class inherits from
AbstractEditHandlerDetailsWebActionwhich allows us to concentrate on parameter validation. It takes care of the add, edit, and cancel handler lifecycle itself.
Finally, implement the mark up used by the action. Create a new Velocity template file named
editDemoHandlerDetails.vmin a directory named
You may have noticed the
demohandler.issue.keyi18n key the Velocity template uses. Add a definition for this property to the resources file,
Now try it again.
Step 9. Test the finished plugin
- Reload your plugin in JIRA. As mentioned, you can do this using FastDev or the
picommand, or simply by restarting JIRA.
- If you don't already have one, create a JIRA issue that your handler can add a comment to. Note its issue key.
- Back in the System administration page, try adding the mail handler based on your custom handler again. As before, give the handler a name. If you like, you can configure a mail server to use as the source for the message. Otherwise, keep the default Local Files and click Next.
- In the handler configuration screen, enter an issue key value. Notice that if you first enter the key of an issue that doesn't exist, you get an error message, thanks to our validation code.
- Enter the key for an existing issue and click Add.
Now let's create the mail message JIRA will pick up. Copy this content to a file named
testmessage.txtin the following location:
The name of the file is not important. Only that each message occupies its own text file in the directory.
Watching the terminal where you started JIRA, give JIRA a few minutes to find the new message and apply it. When it does, you'll see a log message such as this:
It worked! JIRA removed the message after applying it, as logged, so you would need to recreate the text file each time you want to test.
- Look at your issue again. Now you should see a new comment added by your mail handler.