How to Update Custom Field for Multiple Issues using a Listener without using setCustomField

Luke Renchik July 5, 2024

Hello, I am trying to implement a queue to sort workload priority on my JIRA instance, when a item is inserted into the queue I want to update all items with a higher number from a custom field, but I am unable to use the setCustomField() method in my IssueManager class. Is there another way to update custom fields from the scripting environment?

Here is my code:


 

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.web.bean.PagerFilter


def new_issue_queue_location = event.issue.getCustomFieldValue("Queue Location")
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def issueManager = ComponentAccessor.getIssueManager()
def searchService = ComponentAccessor.getComponent(SearchService)
def user = ComponentAccessor.jiraAuthenticationContext.loggedInUser

// Get the custom field "Queue Priority"
def queuePriorityField = customFieldManager.getCustomFieldObjectsByName("Queue Location")
if (!queuePriorityField) {
    return // Exit if the custom field doesn't exist
}


// JQL to find all issues with the "Queue Priority" field
def jqlQuery = "cf[${queuePriorityField}] >= ${new_issue_queue_location}"
def parseResult = searchService.parseQuery(user, jqlQuery)
if (!parseResult.valid) {
    return // Exit if the JQL query is not valid
}

// Perform the search
def searchResult = searchService.search(user, parseResult.query, PagerFilter.getUnlimitedFilter())
def issues = searchResult.results

           

issues.each { relatedIssue ->
    if (relatedIssue.id != event.issue.id) { // Skip the newly created issue
        def currentPriorityValue = relatedIssue.getCustomFieldValue("Queue Location")
        if (currentPriorityValue != null && currentPriorityValue instanceof Number) {
            currentPriorityValue = currentPriorityValue as Integer
            def newPriorityValue = currentPriorityValue + 1
           
--------------------------THIS IS PROBLEMATIC AREA--------------------
            //relatedIssue.update {
            //    "fields": {
            //        "customfield_16800" : newPriorityValue
            //    }
            //}
-----------------------------------------------------------------------------
        }
    }
}

1 answer

1 vote
Matt Parks
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
July 5, 2024

The setCustomFieldValue() method is in the MutableIssue class, not the IssueManager class. You should be able to add the following code at various points in your script:

import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.event.type.EventDispatchOption

import com.atlassian.jira.issue.index.IssueIndexingService
import com.atlassian.jira.util.ImportUtils

MutableIssue mutIssue

Then, inside your issues.each section add the following when you want to update

mutIssue = relatedIssue as MutableIssue
mutIssue.setCustomFieldValue(queuePriorityField, newPriorityValue)
issueManager.updateIssue(user, mutIssue, EventDispatchOption.DO_NOT_DISPATCH, false)

//the below section will re-index the issue after the update, as that doesn't happen automatically

boolean wasIndexing = ImportUtils.isIndexIssues();
ImportUtils.setIndexIssues(true);
issueIndexingService.reIndex(issueManager.getIssueObject(mutIssue.id));
ImportUtils.setIndexIssues(wasIndexing);
Ram Kumar Aravindakshan _Adaptavist_
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
July 8, 2024

Hi @Luke Renchik 

The approach you are using isn't recommended.

Instead of using:-

            //relatedIssue.update {
            //    "fields": {
            //        "customfield_16800" : newPriorityValue
            //    }
            //}
Have you tried this approach with HAPI:-
issues.each { relatedIssue ->
...
...
...
relatedIssue.update {
setCustomFieldValue(16800, newPriorityValue.toString()) //customfield_16800
}

}.reindex()
Let me know how it goes.
Thank you and Kind regards,
Ram
Luke Renchik July 8, 2024

Hi Ram, I am getting an error when trying to add the .reindex() to the end of the loop, is that a method from HAPI?

Luke Renchik July 8, 2024

Additionally my JQL query isn't returning anything. I'm attempting to return all items that contain the customfield_16800, but am currently getting nothing. Is this the correct method to be using?

// JQL to find all issues with the "Queue Location" field populated
def jqlQuery = "customfield_16800 IS NOT EMPTY"
def parseResult = searchService.parseQuery(user, jqlQuery)
if (!parseResult.valid) {
    log.warn("JQL query is not valid: ${jqlQuery}")
    return // Exit if the JQL query is not valid
}
Matt Parks
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
July 9, 2024

I have a generic function that I include in all of my Scriptrunner scripts to get a list of issues from a JQL query. I pass in the authenticated user and sometimes another variable (as in the case below).

Collection<Issue> getTemplateEpicIssues(String epicKey, ApplicationUser user)
{
    def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)
    def childrenQuery = jqlQueryParser.parseQuery(""" issuefunction in issuesInEpics("key = ${epicKey}") ORDER BY Created ASC""")
    def children = searchService.search(user, childrenQuery, PagerFilter.getUnlimitedFilter())
    log.error("Found Children: " + children.getEnd())
    return children.getResults()
}
The searchService variable is defined earlier in the script. I use the @field function to allow the variable to be used inside individual functions, but you could just add the following line at the beginning of the function as well:
SearchService searchService = ComponentAccessor.getComponent(SearchService.class)
If I just use "customfield_xxxxx is not empty" in an Issue Navigator window, that doesn't work for me, but using "cf[xxxxx] is not empty" does return expected values, so maybe you just need to modify your query that way?

Suggest an answer

Log in or Sign up to answer