It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

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
Answer accepted

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 in Marketplace Apps & Integrations

Marketplace Spotlight: Manage your assets with asset management apps

  The role of IT professionals has become increasingly difficult over the last decade. Our organizations work in an increasingly software-powered world and IT professionals are expected to not...

292 views 3 9
Read article

Community Events

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

Find an event

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

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you