I am trying to copy a custom field from parent to child (sub-task) using a listener on 'issue created' event. This code is piece-meal from many places...I am getting an error on this line
MutableIssue parentIssue = issue.getParentObject()
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.CustomFieldManager;
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.UpdateIssueRequest
import com.atlassian.jira.issue.fields.CustomField
MutableIssue parentIssue = issue.getParentObject()
CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager()
CustomField copyFrom = customFieldManager.getCustomFieldObject("Source of Request - JudahTest")
CustomField cf2Update = customFieldManager.getCustomFieldObject("Source of Request - JudahTest")
def valcf2Update = parentIssue.getCustomFieldValue(cf2Update)
if (valcf2Update == null){
parentIssue.setCustomFieldValue(cf2Update, event.issue.getCustomFieldValue(copyFrom))
}
ComponentAccessor.getIssueManager().updateIssue(
ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
, parentIssue
, UpdateIssueRequest.builder().eventDispatchOption(EventDispatchOption.ISSUE_UPDATED).sendMail(false).build() )
Any help would be greatly appreciated.
Hi,
I made a few modifications to your script and it seems to work fine.
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
Issue issue = event.issue
if (issue.issueType.name == "Sub-task") {
def changeHolder = new DefaultIssueChangeHolder()
def parentIssue = issue.getParentObject()
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def field = customFieldManager.getCustomFieldObjects(event.issue).find { it.name == "Source of Request - JudahTest" }
def subTaskValue = issue.getCustomFieldValue(field)
def parentValue = parentIssue.getCustomFieldValue(field)
if (parentValue == null && subTaskValue) {
field.updateValue(null, parentIssue, new ModifiedValue(parentIssue.getCustomFieldValue(field), subTaskValue), changeHolder)
} else {
field.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(field), parentValue), changeHolder)
}
}
I added a listener that listens for a "Create Issue" event. The listener checks to see if the newly created issue is a sub-task. If it is, it will get the parent value's for the custom field and update the sub-task to match the value.
You can find an example of updating custom field values in listeners on our new website: https://library.adaptavist.com/entity/update-the-value-of-a-custom-field-using-a-listener
Regards,
Josh
Thank you Joshua Yamdogo @ Adaptavistthis works perfectly!
A few clarification questions if you have time...
1. Can you briefly explain what the DefaultIssueChangeHolder() class does? I saw that you passed it as a parameter in the updateValue() method and I'm not sure what a ChangeHolder 'does'.
2. Is updateValue() a better method to use than setCustomFieldValue()? - this is what I attempted to use.
3. How does "it" work in this context, what can I use "it" to reference? Is that a groovy object? I saw that you called "it.name"?
Again, thank you for your efforts and time, this is a beautifully executed solution.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Also, the documentation on the new website you've provided looks great!
https://library.adaptavist.com/
Thanks again!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Sure!
1. I think this is best explained by the Atlassian docs here. Essentially, the IssueChangeHolder defines a simple object that can contain the changes that have occurred to an issue.
2. updateValue() is necessary for listeners because it actually updates the issue in the data store. setCustomFieldValue() will set the value for the issue, but it won't persist the change to the database. So after the listener is finished executing, changes made with setCustomFieldValue() will be erased. setCustomFieldValue() is generally fine to use in things like Post-Functions, which have built-in functionalities to persist changes.
3. 'it' is just the default loop parameter in Groovy. You could write it like this as well:
def field = customFieldManager.getCustomFieldObjects(event.issue).find { field -> field.name == "Source of Request - JudahTest" }
Good example here: https://www.tutorialspoint.com/groovy/groovy_find.htm
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Joshua Yamdogo @ Adaptavist - By chance do you have an example for an updated issue? I am using Portfolio for Jira and my goal is to update a mutli-select field in the parent issue when the single select field is updated on a child. I'm using JMWE for the post function to set the field value in the parent issue, which works perfectly, but if the issue updated, I have nothing to work with.
Thanks,
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I don't have an exact example for that use-case but it would be similar to the one above. You could set up a Script Listener that fires on the Issue Updated Event. The code might look something like this:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
def change = event?.getChangeLog()?.getRelated("ChildChangeItem")?.find {
it.field == "Single Select Field" // your select field name here
}
if (change) {
log.debug("Value changed from ${change.oldstring} to ${change.newstring}")
// your actions if the field has changed
def customFieldManager = ComponentAccessor.customFieldManager
def optionsManager = ComponentAccessor.optionsManager
def issue = event.issue as MutableIssue
def customFieldToChange = customFieldManager.getCustomFieldObject("multi_select_list_name") // your multiselect field name here
def fieldConfig = customFieldToChange.getRelevantConfig(issue.getParentObject())
def allOptions = optionsManager.getOptions(fieldConfig)
def newOptionsToSet = allOptions.findAll { it.value in [].add(change.newstring) } // new values for multiselect field
def changeHolder = new DefaultIssueChangeHolder()
customFieldToChange.updateValue(null, issue.getParentObject(), new ModifiedValue(issue.getCustomFieldValue(customFieldToChange), newOptionsToSet), changeHolder)
}
The script checks the change log of the event and sees if the single select field has changed. If it has, get the MultiSelect field from the parent and all of its field options. Then, get the value from the SingleSelect field and match it to an option that the MultiSelect field has. Finally, update the value of the MultiSelect field on the parent.
I've not tested this and it makes assumptions about the values you want to set for the MultiSelect field, but might be enough to get you started. I'd recommend posting a new question on community if you don't figure it out.
Regards,
Josh
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Atlassian Government Cloud has achieved FedRAMP Authorization at the Moderate level! Join our webinar to learn how you can accelerate mission success and move work forward faster in cloud, all while ensuring your critical data is secure.
Register NowOnline forums and learning are now in one easy-to-use experience.
By continuing, you accept the updated Community Terms of Use and acknowledge the Privacy Policy. Your public name, photo, and achievements may be publicly visible and available in search engines.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.