Skip to end of metadata
Go to start of metadata

Level of experience:

This is an intermediate tutorial. You should have completed at least one beginner tutorial before working through this tutorial. See the list of developer tutorials.

Time estimate:

It should take you approximately half an hour to complete this tutorial.


On this page:

Overview of the tutorial

This tutorial shows you how to add a JQL function to JIRA. You will then be able to use the function in the advanced search form to find issues only in projects you have recently accessed. In the real world, a user would likely use this function combined with another search clause. This would be useful in systems that have many projects, and where the users typically only care only about a few.

How are functions used in JQL queries? A JQL query is made up of one or more clauses. Each clause consists of a field, operator, and operand, such as: assignee = fred

  • field is assignee
  • operator is =
  • operand is fred

In this case the operand is a literal string, "fred". But it can also be a function. JIRA comes with many functions built in. And you can add them, as we'll do here.

In this tutorial, you will create a JQL function plugin consisting of these components:

  • Java classes encapsulating the plugin logic.
  • A plugin descriptor to enable the plugin module in JIRA.

When you have finished, all these components will be packaged in a single JAR file.

About these Instructions


You can use any supported combination of OS and IDE to create this plugin. These instructions were written using IntelliJ IDEA on Ubuntu Linux. If you are using a different OS or IDE combination, you should use the equivalent operations for your specific environment.

This tutorial was last tested with JIRA 6.1-20130626.

Required knowledge

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.
  • How to create an Atlassian plugin project using the Atlassian Plugin SDK.
  • The basics of using and administering JIRA, as well as how to use JQL Advanced Searching.

Plugin Source

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 as a ZIP archive by choosing download here:

Step 1. Create the plugin project

In this step, you'll use an atlas- command to generate stub code for your plugin and set up the stub code. The atlas- commands are part of the Atlassian Plugin SDK, and automate much of the work of plugin development for you.

  1. If you have not already set up the Atlassian Plugin SDK, do that now: Set up the Atlassian Plugin SDK and Build a Project.
  2. Enter the following command to create a plugin skeleton:

  3. Choose 1 for JIRA 5 when asked which version of JIRA you want to create the plugin for. 
  4. As prompted, enter the following information to identify your plugin:









  5. Confirm your entries when prompted.

The SDK generates the initial plugin project files in a directory named jira-simple-jql-function.

Step 2. Review and tweak the POM

It is a good idea to familiarise yourself with the project configuration file, known as the POM (Project Object Model definition file). In this section, you will review and tweak the pom.xml file. The file declares the project dependencies and other information.

Add some metadata about your plugin and your company or organisation.

  1. Change to the new jira-simple-jql-function directory and open the pom.xml file for editing.

  2. Add your company or organisation name and your website to the <organization> element (the following code blocks show how it looks in plain text):

  3. Update the <description> element:

  4. Save and close the file.

Step 3. Add your plugin modules

Now you will use the plugin module generator (another atlas- command) to generate the stub code for modules needed by the plugin.

For this tutorial, you will need a "JQL Function" plugin module. You'll add this via the atlas-create-HOSTAPP-plugin-module command.

  1. From the plugin root folder (where the pom.xml is located), enter the following command:
  2. Choose the option labelled JQL Function.
  3. Supply the following information as prompted:

    Enter New Classname


    Package Name


  4. Choose N for Show Advanced Setup.
  5. Choose N for Add Another Plugin Module.
  6. Confirm your choices.

Step 4. Review and tweak the plugin descriptor

The SDK added a jql-function module to our plugin descriptor, the file that describes the plugin to JIRA. Let's touch up the module declaration it added. 

  1. Change to the src/main/resources/ and open atlassian-plugin.xml for editing.
  2. Find the jql-function element and add two elements, fname and list, after the description, as shown here:

    The fname represents the name for our function as it will be used in JQL statements, while the list element indicates whether this function returns a list of issues or a single value.

  3. Save and close the file.

Step 5. Write the plugin code

The SDK gave us the stub code for our class. We'll add the logic for our function as follows:

  1. Change to the source code directory for our function, src/main/java/com/example/plugins/tutorial/jira/jql/
  2. Open the file for editing. 
  3. Remove the following import statement:

  4. Add the following import statements:

  5. We can use the UserProjectHistoryManager that JIRA gives us to determine what projects the current user has recently accessed. Inject it into a constructor for our recentProjectFunction class as follows:

  6. Our function doesn't take any arguments, so in the validate() method, change the number of arguments from 1 to 0, as follows:

  7. The getValues() function is where most of the work happens. Replace the one that the SDK gave us with this one:

    The function returns a list of QueryLiterals that represent the list of IDs of projects recently visited, as offered by the userProjectHistoryManager and populates a linked list with the results converted to QueryLiterals. Any user can use this function, so we use getProjectHistoryWithoutPermissionChecks(). Alternatively, we could've used  getProjectHistoryWithPermissionChecks(), which performs a permission check based on the permissions that the user must have for the project.

  8. In getMinimumNumberOfExpectedArguments(), change the return value to 0:

  9. In getDataType(), change the datatype returned from TEXT to PROJECT, since we're returning only a list of projects.

 The entire class should look something like this:

Step 6. Remove the test files

The SDK was helpful enough to give us unit and integration test stub files for our plugin code. However, these are really meant to be starting points for your testing coverage, so they require more attention to be useful. Testing is a big topic, so we'll leave that for another tutorial, Writing and Running Plugin Tests.

For now, just remove the tests so that we can try out the plugin without modifying them. From the command line, enter the following command from the project root directory:

Step 7. Start JIRA and try out the plugin

We're ready to give it a try:

  1. Open a command window and go to the plugin root folder (where the pom.xml is located).
  2. Run atlas-run (or atlas-debug if you might want to launch the debugger in your IDE).
  3. Open the JIRA interface in a browser by navigating to the URL indicated in the console output.
  4. Log in using the default username and password, admin/admin.
  5. Before trying to user your new function, create two or three projects and populate them with a few issues. This will give us some data to work with.
  6. After creating a few projects and issues, from the JIRA header, click Issues > Search for Issues.  
  7. Click Advanced to switch the form to advance search mode using JQL. 
  8. Enter the following in the search field: project in recentProjects()
    Notice that autocomplete should offer your new function in its project completion suggestions.

  9. Click the search icon to run the search. The list of issues in recently visited projects appears.

Extra credit

A likely next step for extending your JQL function would be to make it accept a parameter. Also, functions typically need to check permissions in JIRA, so that they only return projects to which the user has access. In our case, since we're using the recent history function, we know that the user can access the returned projects already. For more information on these topics, see JQL Function Plugin Module.

For more information on custom JQL functions, see: