The Adaptavist Group LogoDocumentation

Simplify Current Scripts with HAPI

Learn how to simplify existing ScriptRunner scripts using HAPI, including how to find candidates and what simplified code looks like.

This guidance will include why it's useful to simplify your scripts, how to find scripts that can be simplified, and examples of simplified scripts.

Tip: What is HAPI?

HAPI is an API (application programming interface) for doing common tasks in Jira, including managing issues, searching for issues, updating fields and much more! HAPI is a simple alternative to Jira's regular API and can be used in your Groovy scripts. Go to our main HAPI page to learn more about HAPI.

Why should you simplify your scripts with HAPI?

There are many reasons you should simplify your scripts with HAPI:

  • It significantly reduces the complexity of your scripts by abstracting away a lot of the boilerplate code. This ensures your scripts are easier to write and understand.
  • Scripts that utilize HAPI are easier to maintain, which means less time troubleshooting when scripts stop working. We maintain HAPI functions, so when Atlassian makes changes to their underlying API, we will ensure that your scripts continue to function correctly without you having to make any changes.
  • Scripts that are built using HAPI will be easier to migrate if you decide to move to Jira Cloud. HAPI in ScriptRunner for Jira Cloud works the same as it does in Data Center, however, not all methods that are available in Data Center are available in Cloud (see the Feature Parity page for more details). Scripts that utilize HAPI methods will likely need far fewer modifications to be migrated to ScriptRunner for Jira Cloud.

How to find scripts to simplify

The easiest way to find scripts that can be simplified with HAPI is by using the Script Registry and the HAPI code helper:

  1. From ScriptRunner, select the ellipsis menu and select Script Registry.
  2. Select Run. All of your ScriptRunner custom scripts will display below, categorized by feature.
  3. Browse through your scripts and see what you might be able to update to HAPI.
    • You can identify scripts that can be updated with the help of the HAPI code helper. This helper detects where your scripts can be simplified with HAPI code and suggests an alternative (see image below).
      Note: The HAPI code helper doesn't cover all things HAPI, just some of the most common cases.
    • For scripts not covered by the HAPI code helper, you will have to familiarize yourself with HAPI methods by browsing our HAPI documentation and Javadocs.
      Tip: ComponentAccessor

      The presence of ComponentAccessor in your script may indicate it can be simplified using HAPI. HAPI's architecture often eliminates the need for direct component access in many scenarios, allowing you to replace or remove numerous component-related operations. While not all component interactions become obsolete, HAPI significantly reduces their necessity.

Examples of simplifying scripts with HAPI

Tip: Check out this YouTube video that also shows how to convert a script.

The examples below illustrate the application of HAPI in script simplification. They demonstrate how HAPI can be utilized to:

  1. Reduce script length
  2. Improve code readability
  3. Enhance script comprehensibility

Validating attachments in a transition (Validator)

The following example is taken from the Validating Attachments/Links In Transitions page.

The following example details how to find properties of attachments added to this transition or on creation, for example the file name:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.attachment.TemporaryWebAttachmentManager
import com.atlassian.jira.issue.fields.AttachmentSystemField
import webwork.action.ActionContext
 
def temporaryAttachmentManager = ComponentAccessor.getComponent(TemporaryWebAttachmentManager)
def temporaryAttachmentIds = ActionContext.getRequest()?.getParameterValues(AttachmentSystemField.FILETOCONVERT)
 
temporaryAttachmentIds.each { String attachmentId ->
    def attachment = temporaryAttachmentManager.getTemporaryWebAttachment(attachmentId).getOrNull()
    if (attachment) {
        log.debug "Uploaded attachment name: ${attachment.filename}"
    }
}

We can simplify the above script with the HAPI attachmentsAddedInTransition method:

issue.attachmentsAddedInTransition.each { attachment ->
    log.debug("Uploaded attachment name: ${attachment.filename}")
}

Auto close subtask (Custom Post Function)

Note: The following example is taken from the Custom Post Functions page.

The following example details how to Resolve all currently open sub-tasks when the parent task is transitioned to Resolved:

import com.atlassian.jira.component.ComponentAccessor
 
def issueService = ComponentAccessor.getIssueService()
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
 
def subTasks = issue.getSubTaskObjects()
subTasks.each {
    if (it.statusObject.name == "Open") {
        def issueInputParameters = issueService.newIssueInputParameters()
        issueInputParameters.with {
            setResolutionId("1") // resolution of "Fixed"
            setComment("*Resolving* as a result of the *Resolve* action being applied to the parent.")
            setSkipScreenCheck(true)
        }
 
        // validate and transition subtask
        def validationResult = issueService.validateTransition(user, it.id, 5, issueInputParameters)
        if (validationResult.isValid()) {
            def issueResult = issueService.transition(user, validationResult)
            if (!issueResult.isValid()) {
                log.warn("Failed to transition subtask ${it.key}, errors: ${issueResult.errorCollection}")
            }
        } else {
            log.warn("Could not transition subtask ${it.key}, errors: ${validationResult.errorCollection}")
        }
    }
}

We can simplify the above script with the HAPI transition method:

def subTasks = issue.subTaskObjects
subTasks.each { subTask ->
    if (subTask.status.name == "Open") {
        subTask.transition('Resolve Issue') {
            setResolution('Done')
        }
    }
}

Set a custom field value

Note: The following example is taken from the Clones an Issue and Links page.

The following example details how to set the Summary field, and set a custom field called MyCustomFieldType to my value:

issue.summary = 'Cloned issue'
def cf = customFieldManager.getCustomFieldObjects(issue).find {it.name == 'MyCustomFieldType'}
issue.setCustomFieldValue(cf, "my value")

We can simplify the above script with the HAPI setCustomFieldValue method:

issue.summary = 'Cloned issue'
issue.setCustomFieldValue('My custom field name', "my value")

Search documentation

Start typing to search the docs.