Tutorial - Adding a JQL function to JIRA
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.
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
- operator is
- operand is
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.
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.
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: https://bitbucket.org/atlassian_tutorial/jira-simple-jql-function
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.
- If you have not already set up the Atlassian Plugin SDK, do that now: Set up the Atlassian Plugin SDK and Build a Project.
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.
The SDK generates the initial plugin project files in a directory named
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.
Change to the new
jira-simple-jql-functiondirectory and open the
pom.xmlfile for editing.
Add your company or organisation name and your website to the
<organization>element (the following code blocks show how it looks in plain text):
- 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
- From the plugin root folder (where the
pom.xmlis located), enter the following command:
- Choose the option labelled
Supply the following information as prompted:
Enter New Classname
Nfor Show Advanced Setup.
Nfor Add Another Plugin Module.
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.
- Change to the src/main/resources/ and open
jql-functionelement and add two elements,
list, after the description, as shown here:
fnamerepresents the name for our function as it will be used in JQL statements, while the
listelement indicates whether this function returns a list of issues or a single value.
- 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:
- Change to the source code directory for our function,
- Open the
RecentProjectFunction.javafile for editing.
Remove the following import statement:
Add the following import statements:
@scannedannotation before the class definition as follows:
We can use the
UserProjectHistoryManagerthat JIRA gives us to determine what projects the current user has recently accessed. Inject it into a constructor for our
recentProjectFunctionclass as follows:
Our function doesn't take any arguments, so in the
validate()method, change the number of arguments from 1 to 0, as follows:
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
userProjectHistoryManagerand 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.
getMinimumNumberOfExpectedArguments(), change the return value to 0:
getDataType(), change the datatype returned from
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:
- Open a command window and go to the plugin root folder (where the
atlas-debugif you might want to launch the debugger in your IDE).
- Open the JIRA interface in a browser by navigating to the URL indicated in the console output.
- Log in using the default username and password, admin/admin.
- 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.
- After creating a few projects and issues, from the JIRA header, click Issues > Search for Issues.
- Click Advanced to switch the form to advance search mode using JQL.
Enter the following in the search field:
project in recentProjects()
Notice that autocomplete should offer your new function in its project completion suggestions.
- Click the search icon to run the search. The list of issues in recently visited projects appears.
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: