Calling WatcherService.addWatcher means you can never drop the number of issue watchers?

I have an add-on that adds watchers to a JIRA issue via the WatcherService.addWatcher method. I’ve noticed that once this has been applied to an issue, I can no longer drop the number of watchers on that issue below the number of times addWatcher has been called:

  • If I called it once, there must always be one watcher on the issue. If I remove them and refresh the issue they pop back up.
  • If I call it twice, there must always be at least two watchers on the issue. Again, they pop back up after a refresh if removed.
  • In either case, I can swap who the watchers are, so it is not insisting that the user added via addWatcher watches the issue, but they do have to find someone to take their place. (I.e. If Bill and Ted are added as watchers via addWatcher, I can remove them and add Wayne and Garth, but now I can’t remove Wayne and Garth.)

I can find nothing interesting in the logs.

This has become a problem since it’s not obvious that the watcher removal didn’t work until after the page is refreshed: person A removes person B from an issue and then makes a comment that they didn’t want person B to see, but person B was not actually removed so still gets the watcher notification.

Is this a bug?

Hi @andrew.pane,

thanks for posting this, it does sound like a bug to me.
But I’m not the expert :slight_smile:

I would recommend that you create a Developer Support ticket so our team can follow up on this with the Jira team.


Hey @andrew.pane,

i tried recreating your issue.

Please take a look at my test setup and tell me what im doing wrong in order to recreate ure problem:

I´ve created a project and an issue (Issuekey TEST-1) and developed following groovy script

import com.atlassian.jira.bc.issue.watcher.WatcherService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.user.ApplicationUser

WatcherService watcherService = ComponentAccessor.getComponentOfType(WatcherService.class)
IssueManager issueManager = ComponentAccessor.issueManager
String userName = "watcherTestUser"
final ApplicationUser watcherTestUser = ComponentAccessor.userUtil.createUserNoNotification(userName, "", userName + "", userName)
final ApplicationUser adminUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser

Issue sampleIssue = issueManager.getIssueByKeyIgnoreCase("TEST-1")

//Step 1
watcherService.addWatcher(sampleIssue, adminUser, watcherTestUser)

//Step 2
watcherService.removeWatcher(sampleIssue, adminUser, watcherTestUser)

//Step 3
ComponentAccessor.userUtil.removeUser(adminUser, watcherTestUser)

After executing till step 1 an watcher gets added to the issue as expected.
After executing till step 2 the watcher gets removed as expected and watcher count is as it was before step 1
After executing till step 3 the user gets deleted as expected and watcher count is still the same (this step is only for testing purposes)

1 Like

Hi @felix.lahmer,

While I am adding the watchers using the Java code below…

ServiceOutcome<List<ApplicationUser>> listServiceOutcome = watcherService.addWatcher(issue, adminUser, watcherTestUser);

…I am attempting to remove the watchers using the JIRA web page GUI. So in your example you should comment out steps 2 and 3 and then visit the sampleIssue in the browser and see if you can recreate the problem.

(I can upload a video showing it in action if you like.)


(JIRA Core 7.3.6.)

Hey @andrew.pane,

i tested for you on a completely naked Jira 7.3.8 Server version

i´ve done as you told me and removed step 2 and 3 in my script

Then i have ->

1.) Visited the Issue with my watcherTestUser
2.) Watcher count looks good (before was 1 now is 2)
3.) Clicked “Stop watching this issue”
4.) Instantly watcher count was 1 again
5.) Refreshed the page count is still 1
6.) Checked with a different user and is still 1

So far all looks good.

Am i missing something?

Else i can just guess, that there is a problem with ure code.
Sharing it could help us helping you :slight_smile:

1 Like

This is the utility method I call to add watchers to an issue:

public void addWatcher(MutableIssue issue, ApplicationUser adminUser, ApplicationUser watcher) {
if (watcherService.isWatchingEnabled()) {
ServiceOutcome<List> listServiceOutcome = watcherService.addWatcher(issue, adminUser, watcher);
if (!listServiceOutcome.isValid()) {
throw new UnrecoverableException(describeWatcherOutcome(“add”, issue, watcher, listServiceOutcome));
log.trace(describeWatcherOutcome(“add”, issue, watcher, listServiceOutcome));

This gets called from a pre-event post function on a transition.

I’ve posted a video showing the bug in action:

(Audio not great - sorry.)

Hey @andrew.pane,

i believe i’ve found the root of your problem.
You telling me that that part of your plugin gets executed in a post function reminded me of a bug i have seen lately. Jira bug report

I will recreate your behaviour tomorrow and see if i can think of a programmatic fix :slight_smile:

Maybe @pvandevoorde can get in touch with the jira developers and find out if they are already aware of a programmatic workaround? Could save some of my time :wink:

I think you’re right, @felix.lahmer. And in fact just over a year ago another user (Fidel) noted the same behavior we’re seeing here: that you can swap in another user through the GUI to take the place of a user added through the API.