Groovy scripy Post Function CF update with history


Im looking for a way to update a customfield using a groovy script. With history.
Currently my script is updating the CF value as it should. Bu there are no entry in the history, that the user freforming the transition also changed the cf value.

This is my script:

Issue issue = issue

ComponentManager componentManager = ComponentManager.getInstance()
CustomFieldManager cfManager = componentManager.getCustomFieldManager()

CustomField customField = cfManager.getCustomFieldObjectByName("Story Points")

// Obtain the FieldLayoutItem associated with the custom field for this issue
FieldLayoutItem fieldLayoutItem = ComponentManager.getInstance().getFieldLayoutManager().getFieldLayout(issue).getFieldLayoutItem(customField);

// Read a value
Object oldValue = customField.getValue(issue);

// Create a modified value object with the old value and the new value
ModifiedValue modifiedValue = new ModifiedValue(oldValue, 0d)

// Update the value
customField.updateValue(fieldLayoutItem, issue, modifiedValue, new DefaultIssueChangeHolder());

I thought the last line would both update the field AND add the history entry. But It dosent.
Can anyone point me in the correct direction.

3 answers

1 accepted

2 votes
Accepted answer

AFAIK, you should add entry of ChangeItemBean into transientVars.changeItems.

User currentUser = UserUtils.getUser(((WorkflowContext) transientVars.get("context")).getCaller())

//Add update to change History
ChangeItemBean changeBean = new ChangeItemBean(ChangeItemBean.CUSTOM_FIELD, customField.getName(), oldValue.toString(), "0")
IssueChangeHolder changeHolder = new DefaultIssueChangeHolder();
GenericValue changeLog = ChangeLogUtils.createChangeGroup(currentUser, issue, issue, changeHolder.getChangeItems(), false)

Hi! I have tried to reuse this solution here, but it would not work... This is my script: import com.atlassian.crowd.embedded.api.User import import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.Issue import com.atlassian.jira.issue.IssueManager import com.atlassian.jira.user.util.UserUtil import com.atlassian.jira.web.bean.PagerFilter import com.atlassian.jira.issue.ModifiedValue; import com.atlassian.jira.issue.util.DefaultIssueChangeHolder; import org.ofbiz.core.entity.GenericValue; import com.atlassian.jira.issue.util.IssueChangeHolder import com.atlassian.jira.issue.history.ChangeItemBean; def customFieldManager = ComponentAccessor.getCustomFieldManager(); //" + issue.project.key + " //form JQL with exception for BBS core project if(issue.project.key == 'PSP' || issue.project.key == 'BC'){ //get issue status as we want to have priorityin multiple stauses def issueStatus = issue.getStatusObject().getName(); //get the curent issue requested by country - we want to have for BSS core separate backlogs def requestedByCountry = customFieldManager.getCustomFieldObjectByName("Requested by Country"); def requestedByCountryValue = issue.getCustomFieldValue(requestedByCountry); //jqlSearch = "project=" + issue.project.key + " AND status='" + issueStatus + "' AND 'Requested by Country'='" + requestedByCountryValue + "' AND (issuetype='Solution Story' or issuetype=Story or issuetype=Bug or issuetype=Task or issuetype=Adaptation) order by rank" if(issueStatus == 'Draft' || issueStatus == 'Fast scan Done' || issueStatus == 'Waiting for Analysis' || issueStatus == 'In Progress' || issueStatus == 'In Analysis' || issueStatus == 'Waiting for Approval' || issueStatus == 'Waiting For Design' || issueStatus == 'In Design' || issueStatus == 'Waiting for Dev and ST' ) jqlSearch = "project=" + issue.project.key + " AND (status='Draft' or status='Fast scan Done' or status='Waiting for Analysis' or status='In Progress' or status='In Analysis' or status='Waiting for Approval' or status='Waiting For Design' or status='In Design' or status='Waiting for Dev and ST') AND 'Requested by Country'='" + requestedByCountryValue + "' AND (issuetype='Solution Story' or issuetype=Story or issuetype=Bug or issuetype=Task or issuetype=Adaptation) order by rank" else jqlSearch = "project=" + issue.project.key + " AND (status='In Dev and ST' or status='Waiting for SOT' or status='In SOT') AND 'Requested by Country'='" + requestedByCountryValue + "' AND (issuetype='Solution Story' or issuetype=Story or issuetype=Bug or issuetype=Task or issuetype=Adaptation) order by rank" }else{ jqlSearch = "project=" + issue.project.key + " AND (issuetype=Story or issuetype=Bug or issuetype=Task or issuetype=Adaptation) and status!=Closed and status!=Resolved order by rank" } log.error("JQL: " + jqlSearch); SearchService searchService = ComponentAccessor.getComponent(SearchService.class) UserUtil userUtil = ComponentAccessor.getUserUtil() User user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser() IssueManager issueManager = ComponentAccessor.getIssueManager() if (!user) { user = userUtil.getUserObject('jira_bot') } List<Issue> issues = null SearchService.ParseResult parseResult = searchService.parseQuery(user, jqlSearch) if (parseResult.isValid()) { def searchResult =, parseResult.getQuery(), PagerFilter.getUnlimitedFilter()) // Transform issues from DocumentIssueImpl to the "pure" form IssueImpl (some methods don't work with DocumentIssueImps) issues = searchResult.issues.take(100).collect {issueManager.getIssueObject(} log.error("Issues found: " + issues.toString()); def i = 0; issues.each { i++; def issueX = issueManager.getIssueObject(; def tgtField = customFieldManager.getCustomFieldObjects(issueX).find { == "Prio List"} //Add update to change History //ChangeItemBean(String fieldType,String field, String from, String to); ChangeItemBean changeBean = new ChangeItemBean(ChangeItemBean.CUSTOM_FIELD, "Prio List", issueX.getCustomFieldValue(tgtField), "0"); IssueChangeHolder changeHolder = new DefaultIssueChangeHolder(); changeHolder.addChangeItem(changeBean); //GenericValue changeLog = createChangeGroup(user, issueX, issueX, changeHolder.getChangeItems(), true); //update field tgtField.updateValue(null, issueX, new ModifiedValue(issueX.getCustomFieldValue(tgtField), i.toString()),changeHolder); } } else { log.error("Invalid JQL: " + jqlSearch); }

If I uncomment //GenericValue changeLog = createChangeGroup(user, issueX, issueX, changeHolder.getChangeItems(), true); i will get an error: groovy.lang.MissingMethodException: No signature of method: org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.createChangeGroup() is applicable for argument types: (com.atlassian.jira.user.BridgedDirectoryUser, com.atlassian.jira.issue.IssueImpl, com.atlassian.jira.issue.IssueImpl, java.util.ArrayList, java.lang.Boolean) values: [leonulja:10000, CA-1033, CA-1033, [com.atlassian.jira.issue.history.ChangeItemBean@7aebaea7[fieldType=custom,field=Prio List,from=1,fromString=<null>,to=0,toString=<null>,created=<null>]], ...] at Script250$_run_closure2.doCall(Script250.groovy:67) at

Hi, did you manage to get this worked? if so, can you please share sample script?

Suggest an answer

Log in or Sign up to answer
Community showcase
Published Oct 31, 2018 in Marketplace Apps

Marketplace Spotlight: Zephyr

Hello Atlassian Community! Each month, we run a series of Spotlights to highlight Marketplace vendors and apps that our team thinks this Community would find valuable. In last month's Spotlig...

346 views 0 1
Read article

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you