How do you 'completely' update a custom field using ScriptRunner

Harvey Bennett March 26, 2019

I am currently having some problems updating a radio button custom field using SciptRunner. The field is reflecting the changes made on the view issues screen but it is not being updated in my database. My current situation is that I am trying to update a dynamic set of issues generated from my JQL search. I am trying to perform the update in a listener. Jira version is 7.6.4 and SciptRunner version is 5.4.28

// used to access fields and manipulate data
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.customfields.manager.OptionsManager
import com.atlassian.jira.issue.customfields.option.Option
// used to update issues
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.index.IssueIndexingService
// access resolution of an issue
import com.atlassian.jira.config.ResolutionManager
// used to access worklogs
import com.atlassian.jira.issue.worklog.Worklog
// used to access issue history
import com.atlassian.jira.issue.changehistory.ChangeHistoryManager
import com.atlassian.jira.issue.history.ChangeItemBean
// used to modify existing field values
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.IssueChangeHolder
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
// used for JQL searches
import com.atlassian.jira.issue.search.SearchProvider
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.web.bean.PagerFilter
// time libraries (external)
import java.sql.Timestamp
import java.time.LocalDate
// used for logging/debugging ... log.info("VALUE HERE")
import org.apache.log4j.Logger
import org.apache.log4j.Level
log.setLevel(Level.INFO)

import com.atlassian.jira.util.ImportUtils;
import com.atlassian.jira.issue.Issue;
//import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.index.IssueIndexingService;


log.info("RUNNING")
// get the current issue that triggered this listener
Issue issue = event.issue
// helps manage issues
def issueManager = ComponentAccessor.getIssueManager()
// used to retrieve resolution
def resolutionManager = ComponentAccessor.getComponent(ResolutionManager)
// custom field usage
def customFieldManager = ComponentAccessor.getCustomFieldManager()
// define current issues pending field and retrive field value
def cfNameForPending = customFieldManager.getCustomFieldObjects(issue).find {it.name == "Pending"}
def cfPending = customFieldManager.getCustomFieldObjectByName("Pending").getValue(issue)
String cfStringForPending = cfPending.toString()
// the resolution is not set meaning its unresolved (this means it is considered empty). The label exist in the triggered issue
if (!issue.getResolution() && cfStringForPending == "Yes")
{
log.info("RUNNING YES CASE")
// might need to define the user in future versions???
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
// get the project key name
String[] extractedProjectNameArray = issue.getKey().split("-")
String extractedProjectName = extractedProjectNameArray[0]
// allow for use of the JQL search engine
def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)
def searchProvider = ComponentAccessor.getComponent(SearchProvider)
// create and generate the query
def readyToUseQuery = "project = " + extractedProjectName + " AND issue in childIssuesOf('" + issue.getKey() + "') AND resolution is EMPTY AND Pending != Yes"
def query = jqlQueryParser.parseQuery(readyToUseQuery)
def results = searchProvider.search(query, user, PagerFilter.getUnlimitedFilter())
// go through list of returned issues and updated their 'Pending' field
results.getIssues()?.each {queryIssue ->
log.info(queryIssue.getKey())
def cfNameForPendingForQueryIssue = customFieldManager.getCustomFieldObjects(queryIssue).find {it.name == "Pending"}
def cfConfigForPending = cfNameForPendingForQueryIssue.getRelevantConfig(queryIssue)
def option = ComponentAccessor.optionsManager.getOptions(cfConfigForPending)?.find { it.toString() == 'Yes' }
def changeHolder = new DefaultIssueChangeHolder()
cfNameForPendingForQueryIssue.updateValue(null, queryIssue, new ModifiedValue(queryIssue.getCustomFieldValue(cfNameForPendingForQueryIssue), option),
}
}

 

 

Edit 1: I noticed after I manually perform a reindex in the system settings the values are set to what they show on the view screen. So I am toggling from "No & "Yes". When I run this query in the JQL search in the GUI it is accurately showing me my results. So my question is is there more that I am supposed to do then just call that 'updateValue' method? Thanks for any insight!

1 answer

1 accepted

0 votes
Answer accepted
Harvey Bennett March 26, 2019

The solution was missing an index method that needs called after the values are set. I am not sure why this requires multiple lines of code. Maybe someone can provide a more cleaner route for writing this. I have used a method before called issue.store() that reflects the changes for default system fields. 

https://community.atlassian.com/t5/Answers-Developer-Questions/Issue-reindex-from-groovy-script/qaq-p/509901

I added this code below after updating the issue.

def issueIndexingService = ComponentAccessor.getComponent(IssueIndexingService)

boolean wasIndexing = ImportUtils.isIndexIssues();
ImportUtils.setIndexIssues(true);
log.warn("Reindex issue ${issue.key} ${issue.id}")
issueIndexingService.reIndex(issueManager.getIssueObject(issue.id));
ImportUtils.setIndexIssues(wasIndexing);

 

Suggest an answer

Log in or Sign up to answer