Come for the products,
stay for the community

The Atlassian Community can help you and your team get more value out of Atlassian products and practices.

Atlassian Community about banner
4,363,011
Community Members
 
Community Events
168
Community Groups

Remove watchers when creating clone via workflow post function (scriptrunner)

I've built a workflow that has a transition from Closed to Closed called 'Clone' that creates a clone of the ticket into a different project and as a different issue type.  I'm accomplishing this through a ScriptRunner post function, 'Clones an issue and links'.  (In case it becomes important, it is currently the first post function in that transition.)  Within the clone post function, I've set the new target project and target issue type.  All gravy.  ScriptRunner is the best.

Here is where I need help.  

In the 'Additional issue actions' of that post function I want to replace the clone's Watcher field with users from a custom user-picker field (multi user field, called "Team").  This is important for us because there is often a dozen or more watchers on the original ticket whereas the clone will only have 2-3 watchers.  And those populations don't overlap. 

I don't know groovy, but I've used this community forum and lots of testing to hobble together enough so that this post function already (a) strips attachments, (b) gives the clone a name based on the original ticket, and (c) sets the clone's assignee based on a custom field ("Manager").  

Any ideas on how to replace the Watchers field with information from the "Team" custom user-picker field?  Thanks for any and all help!

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.UpdateIssueRequest

// get required Managers
def customFieldManager = ComponentAccessor.getCustomFieldManager()

// rename clone Summary field
issue.setSummary("Case" + " - " + issue.getSummary())

// remove attachments
checkAttachment = {attachment -> false}

// get a pointer to the user picker field and its value
def userCf = customFieldManager.getCustomFieldObjectByName("Manager")
def implUser = issue.getCustomFieldValue(userCf) as ApplicationUser

// if the user picker field is not null then set the assignee
if(implUser){
issue.setAssigneeId(implUser.username.toString())
}

 

 

1 answer

Hi Becky,

Something like this should work:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.UpdateIssueRequest

// get required Managers
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def watcherManager = ComponentAccessor.getWatcherManager()
def groupManager = ComponentAccessor.getGroupManager()
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def locale = ComponentAccessor.getLocaleManager().getLocaleFor(user)

// rename clone Summary field
issue.setSummary("Case" + " - " + issue.getSummary())

// remove attachments
checkAttachment = {attachment -> false}

// get a pointer to the user picker field and its value
def userCf = customFieldManager.getCustomFieldObjectByName("Manager")
def implUser = issue.getCustomFieldValue(userCf) as ApplicationUser

// if the user picker field is not null then set the assignee
if(implUser){
issue.setAssigneeId(implUser.username.toString())
}

// Remove all watchers from issue
def watchers = watcherManager.getWatchers(issue, locale)
watchers.each { watcher ->
watcherManager.stopWatching(watcher, issue)
}

// Add all users from Team group as watchers
def teamGroup = groupManager.getGroup("Team")
teamGroup.each { teamMember ->
watcherManager.startWatching(teamMember, issue)
}

Thank you for responding!  I used the script above.  In the 'Additional issue actions' it is flagging this piece: 

watcherManager.startWatching(teamMember, issue)

saying: 

Cannot find the matching method com.atlassian.jira.issue.watchers.WatcherManager#startWatching(java.lang.Object,com.atlassian.jira.issue.MutableIssue). Please check if the declared type is right an if the method exists.

I went ahead and ran a ticket through the workflow to get a log:

2018-03-13 10:27:09,681 ERROR [workflow.ScriptWorkflowFunction]: *************************************************************************************
2018-03-13 10:27:09,690 ERROR [workflow.ScriptWorkflowFunction]: Script function failed on issue: OGC-1175, actionId: 41, file: null
java.lang.NullPointerException
 at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:210)
 at com.google.common.cache.LocalCache.get(LocalCache.java:3936)
 at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3941)
 at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4824)
 at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4830)
 at com.atlassian.jira.issue.watchers.DefaultWatcherManager.getWatcherUserKeys(DefaultWatcherManager.java:150)
 at com.atlassian.jira.issue.watchers.DefaultWatcherManager.getWatchers(DefaultWatcherManager.java:136)
 at com.atlassian.jira.issue.watchers.WatcherManager$getWatchers.call(Unknown Source)
 at Script822.run(Script822.groovy:30)

 Do you see the issue?   

Hi Becky, 

There was a small error in the code. It should have been groupManager.getUsersInGroup

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.ApplicationUser

// get required Managers
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def watcherManager = ComponentAccessor.getWatcherManager()
def groupManager = ComponentAccessor.getGroupManager()
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def locale = ComponentAccessor.getLocaleManager().getLocaleFor(user)

// rename clone Summary field
issue.setSummary("Case" + " - " + issue.getSummary())

// remove attachments
//checkAttachment = {attachment -> false}

// get a pointer to the user picker field and its value
def userCf = customFieldManager.getCustomFieldObjectByName("Manager")
def implUser = issue.getCustomFieldValue(userCf) as ApplicationUser

// if the user picker field is not null then set the assignee
if(implUser){
issue.setAssigneeId(implUser.username.toString())
}

// Remove all watchers from issue
def watchers = watcherManager.getWatchers(issue, locale)
watchers.each { watcher ->
watcherManager.stopWatching(watcher, issue)
}

// Add all users from Team group as watchers
def teamGroup = groupManager.getUsersInGroup("Team")
teamGroup.each { teamMember ->
watcherManager.startWatching(teamMember, issue)
}

I tested it in my instance and it seems to work now with new watchers added to my cloned issue:

Screen Shot 2018-03-13 at 12.53.46 PM.png

It's strange -- the post function is still not working in my instance.  I'm getting the same log error as before. 

It seems to be this part that is causing the error.  Do you have an idea why this is failing?

// Remove all watchers from issue
def watchers = watcherManager.getWatchers(issue, locale)
watchers.each { watcher ->
watcherManager.stopWatching(watcher, issue)
}

 Thanks very much for your help with this.  

Hi Becky,

Which version of ScriptRunner are you running? You can find it on the manage add-ons page in JIRA.

Thanks,

Josh

Hi Josh,  We're running version 4.3.15

Hi Becky,

In that case you have to make use of the doAfterCreate callback (closure)

So in your case will be something like 

doAfterCreate = {
def watchers = watcherManager.getWatchers(issue, locale)
watchers.each { watcher ->
watcherManager.stopWatching(watcher, issue)
}
}

Let us know if that worked for you.  

Many thanks, Thanos. I tried the doAfterCreate suggestion.  No luck.  The clone is created but the Watcher field is not wiped.  No error log reported.  I also tried moving the post-function that's creating the clone to be the last post-function -- it had been the first.  No luck there either.

Let me know if there is anything I can try to help troubleshoot. 

Here is the full script:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.UpdateIssueRequest

// get required Managers
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def watcherManager = ComponentAccessor.getWatcherManager()
def groupManager = ComponentAccessor.getGroupManager()
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def locale = ComponentAccessor.getLocaleManager().getLocaleFor(user)

// rename clone Summary field
issue.setSummary("Case" + " - " + issue.getSummary())

// remove attachments
checkAttachment = {attachment -> false}

// get a pointer to the user picker field and its value
def userCf = customFieldManager.getCustomFieldObjectByName("Manager")
def implUser = issue.getCustomFieldValue(userCf) as ApplicationUser

// if the user picker field is not null then set the assignee
if(implUser){
issue.setAssigneeId(implUser.username.toString())
}

// remove all watchers of clone
doAfterCreate = {
def watchers = watcherManager.getWatchers(issue, locale)
watchers.each { watcher ->
watcherManager.stopWatching(watcher, issue)
}
}

Also, do you think a listener be better?  I haven't created a listener before but know that they can modify tickets.  If so, would I use your doAfterCreate script suggestion above or do listeners require different scripting?

Hey Becky, 

This should have worked ,

import com.atlassian.jira.component.ComponentAccessor

doAfterCreate = {
ComponentAccessor.watcherManager.getWatchersUnsorted(issue)?.each {
ComponentAccessor.watcherManager.stopWatching(it, issue)
}
}

Can I ask you where is your post function ? Which step and in what order ?

Also can you please check your application logs for any errors ? 

It is the first post function in a transition called 'Clone' that goes from Closed back to Closed.  The idea is that after a ticket is closed, you press a button and make a clone into a new Project / Issue Type.  Attaching a screenshot of the post function ordering and the workflow.  

Capture.PNG

Capture2.PNG

I'll ask another one of our admins for the application logs. 

Static checking on the script above says it cannot find the matching method for the ComponentAccessor lines.  When I pushed a ticket through the transition to see what would happen, it provided this log:

2018-03-20 16:02:16,787 ERROR [workflow.ScriptWorkflowFunction]: *************************************************************************************
2018-03-20 16:02:16,787 ERROR [workflow.ScriptWorkflowFunction]: Script function failed on issue: OGC-1175, actionId: 41, file: null
groovy.lang.MissingMethodException: No signature of method: com.atlassian.jira.issue.watchers.DefaultWatcherManager.getWatchersUnsorted() is applicable for argument types: (com.atlassian.jira.issue.IssueImpl) values: [BMS-133]
 at Script944$_run_closure2.doCall(Script944.groovy:31)
 at Script944$_run_closure2.doCall(Script944.groovy)
 at com.onresolve.scriptrunner.canned.jira.utils.AbstractCloneIssue.doScript(AbstractCloneIssue.groovy:125)
 at com.onresolve.scriptrunner.canned.jira.utils.CopyIssueWithAttachments.super$2$doScript(CopyIssueWithAttachments.groovy)
 at com.onresolve.scriptrunner.canned.jira.utils.CopyIssueWithAttachments.doScript(CopyIssueWithAttachments.groovy:13)
 at com.onresolve.scriptrunner.canned.jira.workflow.postfunctions.CloneIssue.super$3$doScript(CloneIssue.groovy)
 at com.onresolve.scriptrunner.canned.jira.workflow.postfunctions.CloneIssue.doScript(CloneIssue.groovy:89)

I had the same issue that it would not clear the watchers on creation of the issue. This is how I solved it.

https://community.atlassian.com/t5/Jira-questions/Use-ScriptRunner-to-un-watch-an-issue-when-created/qaq-p/1038959#U1039042

Suggest an answer

Log in or Sign up to answer
TAGS

Atlassian Community Events