Scriptrunner for Confluence - Figuring out how to call the built in canned script, AddRemoveWatchers

Melanie Pasztor September 24, 2020

Hello!

I am trying to figure out how to get a groovy script calling a builtin canned script with Scriptrunner for Confluence to work.

import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.confluence.spaces.SpaceManager
import com.atlassian.user.UserManager
import com.atlassian.user.GroupManager
import com.onresolve.scriptrunner.canned.confluence.admin.AddRemoveWatchers

//Managers
def spaceManager = ComponentLocator.getComponent(SpaceManager)
def groupManager = ComponentLocator.getComponent(GroupManager)
def userManager = ComponentLocator.getComponent(UserManager)

//Canned built-in script
def removeWatchers = new AddRemoveWatchers()

//Variables
def spaceKey = "TEST"
def groupNames = "confluence-users"
def userKeys = ""
def targetSpace = spaceManager.getSpace(spaceKey)
def targetGroup = groupManager.getGroup(groupNames)
def targetUser = userManager.getUser(userKeys)

//Script Parameters
def scriptParams = [
"FIELD_CONTENT_TYPE": "Space",
"FIELD_SPACE_KEY": targetSpace,
"FIELD_GROUPS": targetGroup,
"FIELD_USERS": targetUser,
"FIELD_WATCH_OR_UNWATCH": "Unwatch",
]

//Run Script
def runScript = removeWatchers.doScript(scriptParams)
runScript

Console giving the errror:

groovy.lang.GroovyRuntimeException: Could not find matching constructor for: com.onresolve.scriptrunner.canned.confluence.admin.AddRemoveWatchers() at Script170.run(Script170.groovy:13)

And before that, a groovy.lang.MissingMethodException error for the same thing (not even sure how the error can change overnight without any changes). 

The only examples I have found are for calling the CopySpace or Labels scripts. 

My scriptrunner/groovy-fu is lacking, and despite having AddRemoveWatchers class opened as referenced, unsure what command/method/call is needed, and/or run the built-in script. 

The goal is to automate the AddRemoveWatchers for designated spaces with a Event Listener or Job.

I appreciate any insight and help!

 

-Melanie

 

2 answers

1 accepted

1 vote
Answer accepted
Dominic Lagger
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 24, 2020

Hi @Melanie Pasztor 

This script should do what you want. Thanks for the challenge :) 

import com.onresolve.scriptrunner.runner.customisers.PluginModule;
import com.atlassian.sal.api.component.ComponentLocator;
import com.atlassian.confluence.core.ContentPermissionManager;
import com.atlassian.confluence.security.PermissionManager;
import com.atlassian.confluence.security.SpacePermissionManager;
import com.onresolve.scriptrunner.runner.ScriptRunner;
import com.atlassian.confluence.spaces.SpaceManager;
import com.atlassian.confluence.mail.notification.NotificationManager;
import com.atlassian.sal.api.user.UserManager;
import com.atlassian.user.GroupManager;
import com.onresolve.scriptrunner.canned.util.SimpleBuiltinScriptErrors;
import org.apache.log4j.Level
import org.apache.log4j.Logger
import com.atlassian.confluence.user.UserAccessor
import com.onresolve.scriptrunner.canned.confluence.utils.CQLSearchUtils
import com.onresolve.scriptrunner.canned.confluence.admin.AddRemoveWatchers
import com.onresolve.scriptrunner.canned.confluence.admin.model.AddRemoveWatchersCommand
import com.atlassian.confluence.core.ContentEntityManager
import com.atlassian.confluence.api.service.search.CQLSearchService

import com.google.gson.Gson

import java.util.Map;
import java.util.LinkedHashMap

class AddWatcher {
def String addWatcher() {

UserAccessor userAccessor = ComponentLocator.getComponent(UserAccessor)
GroupManager groupManager = ComponentLocator.getComponent(GroupManager)
ContentPermissionManager contentPermissionManager = ComponentLocator.getComponent(ContentPermissionManager)
SpaceManager spaceManager = ComponentLocator.getComponent(SpaceManager)
NotificationManager notificationManager = ComponentLocator.getComponent(NotificationManager)

@PluginModule
CQLSearchService cqlSearchService
ContentEntityManager contentEntityManager = ComponentLocator.getComponent(ContentEntityManager)
CQLSearchUtils cqlSearchUtils = new CQLSearchUtils(cqlSearchService, contentEntityManager)

SpacePermissionManager spacePermissionManager = ComponentLocator.getComponent(SpacePermissionManager)

@PluginModule
ScriptRunner scriptRunner

AddRemoveWatchers watchers = new AddRemoveWatchers(userAccessor, groupManager, spaceManager, notificationManager, cqlSearchUtils, spacePermissionManager, contentPermissionManager)


AddRemoveWatchersCommand command = new AddRemoveWatchersCommand()

command.setContentType("space")
command.setSpaceKey("spacekey")
command.setGroupNames([""])
command.setUserKeys(["USERKEY"])
command.setWatchOrUnwatch("watch")

SimpleBuiltinScriptErrors errorCollection = (SimpleBuiltinScriptErrors) watchers.validate(command, false)
if(errorCollection.hasAnyErrors()) {
log.debug("Could not copy page tree: $errorCollection")
} else {
watchers.execute(command)
}

}
}

Regards Dominic

Melanie Pasztor September 25, 2020

Awesome, that helps a lot! Helps understanding what is referring to. 

With that, trying to get working. Regardless what I enter for the command variables, nothing happens other than saying 'class AddWatcher' in the Console, and then the following error when triggered to run in a listener: 

groovy.lang.MissingMethodException: No signature of method: AddWatcher.main() is applicable for argument types: ([Ljava.lang.String;) values: [[]]
Possible solutions: wait(), wait(long), find(), any(), wait(long, int), is(java.lang.Object)

at com.onresolve.scriptrunner.runner.RunScriptInvoker$run.call(Unknown Source)
at com.onresolve.scriptrunner.runner.AbstractScriptRunner.runScriptWithRawBindings(AbstractScriptRunner.groovy:190)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at com.onresolve.scriptrunner.runner.AbstractScriptRunner.runScript(AbstractScriptRunner.groovy:184)
at com.onresolve.scriptrunner.runner.AbstractScriptRunner$runScript$6.callCurrent(Unknown Source)
at com.onresolve.scriptrunner.runner.AbstractScriptRunner.runScriptAndGetContext(AbstractScriptRunner.groovy:210)
at com.onresolve.scriptrunner.runner.AbstractScriptRunner$runScriptAndGetContext$4.callCurrent(Unknown Source)
at com.onresolve.scriptrunner.runner.AbstractScriptRunner.runFileAsScript(AbstractScriptRunner.groovy:322)
at com.onresolve.scriptrunner.runner.ScriptRunner$runFileAsScript$11.call(Unknown Source)
at com.onresolve.scriptrunner.canned.jira.utils.CustomScriptDelegate.doScript(CustomScriptDelegate.groovy:78)
at com.onresolve.scriptrunner.canned.jira.utils.CustomScriptDelegate$doScript$3.call(Unknown Source)
at com.onresolve.scriptrunner.canned.confluence.events.SimpleScriptedEventHandler.doScript(SimpleScriptedEventHandler.groovy:59)

Similar error I had before, but from the console. I am gathering that it missing an expected parameter. 

Dominic Lagger
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 28, 2020

What exactly do you type in the script console? 

I do it with: 

AddWatcher aut = new AddWatcher()
aut.addWatcher()

Hope this helps

Regards, Dominic

Melanie Pasztor September 29, 2020

The script above with some details changed for space, group, user, and set to unwatch. Directly in the scriptrunner's Script Console.  The error when using same script, and some of the modification attempts to make it work. 

Removing the whole class thing, leaving everything under def String addWatcher() {...}, says it ran successfully, no change with the watchers of the designated space. Some colleagues cannot help me, as they are not familiar with groovy despite being java based. 

Does not seem the class is needed, and is just stopping from the rest to being runned. 

As for the new suggestion, I am not sure how that would be implemented with the script above. Do I replace the class with that? Does aut replace watchers in watchers.execute portion?

My experience with Scriptrunner and groovy are simpler scripts in Jira that area triggered in workflows or behaviours.  And my Java limited to tweaking and modding something existing.

Dominic Lagger
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 29, 2020

Okay, I think I know what the problem is.

The script with the class is a File in the "Script Editor" and can not be runned in the console directly. This is the idea of object oriented programming.

To run it directly in the script console, use this script: (It is the same, but without the "class" and "methwod" definitions)

import com.onresolve.scriptrunner.runner.customisers.PluginModule;
import com.atlassian.sal.api.component.ComponentLocator;
import com.atlassian.confluence.core.ContentPermissionManager;
import com.atlassian.confluence.security.PermissionManager;
import com.atlassian.confluence.security.SpacePermissionManager;
import com.onresolve.scriptrunner.runner.ScriptRunner;
import com.atlassian.confluence.spaces.SpaceManager;
import com.atlassian.confluence.mail.notification.NotificationManager;
import com.atlassian.sal.api.user.UserManager;
import com.atlassian.user.GroupManager;
import com.onresolve.scriptrunner.canned.util.SimpleBuiltinScriptErrors;
import org.apache.log4j.Level
import org.apache.log4j.Logger
import com.atlassian.confluence.user.UserAccessor
import com.onresolve.scriptrunner.canned.confluence.utils.CQLSearchUtils
import com.onresolve.scriptrunner.canned.confluence.admin.AddRemoveWatchers
import com.onresolve.scriptrunner.canned.confluence.admin.model.AddRemoveWatchersCommand
import com.atlassian.confluence.core.ContentEntityManager
import com.atlassian.confluence.api.service.search.CQLSearchService

import com.google.gson.Gson

import java.util.Map;
import java.util.LinkedHashMap

UserAccessor userAccessor = ComponentLocator.getComponent(UserAccessor)
GroupManager groupManager = ComponentLocator.getComponent(GroupManager)
ContentPermissionManager contentPermissionManager = ComponentLocator.getComponent(ContentPermissionManager)
SpaceManager spaceManager = ComponentLocator.getComponent(SpaceManager)
NotificationManager notificationManager = ComponentLocator.getComponent(NotificationManager)

@PluginModule
CQLSearchService cqlSearchService
ContentEntityManager contentEntityManager = ComponentLocator.getComponent(ContentEntityManager)
CQLSearchUtils cqlSearchUtils = new CQLSearchUtils(cqlSearchService, contentEntityManager)

SpacePermissionManager spacePermissionManager = ComponentLocator.getComponent(SpacePermissionManager)

@PluginModule
ScriptRunner scriptRunner

AddRemoveWatchers watchers = new AddRemoveWatchers(userAccessor, groupManager, spaceManager, notificationManager, cqlSearchUtils, spacePermissionManager, contentPermissionManager)


AddRemoveWatchersCommand command = new AddRemoveWatchersCommand()

command.setContentType("space")
command.setSpaceKey("SPACEKEY")
command.setGroupNames([""])
command.setUserKeys(["USERKEY"])
command.setWatchOrUnwatch("watch")

SimpleBuiltinScriptErrors errorCollection = (SimpleBuiltinScriptErrors) watchers.validate(command, false)
if(errorCollection.hasAnyErrors()) {
log.debug("Could not copy page tree: $errorCollection")
} else {
watchers.execute(command)
}

Hope this works

Regards, Dominic

Melanie Pasztor September 29, 2020

I have tried both stripping the class and the def String before, yet got a NullPoint error. Posted yours exactly, and ran successfully. I had the NullPointer it seems due to some capitalization in the command.setEtcs. >.>

It works in console, and in turn with the event listener. Woot!

Lesson learned, groovy script does not function like a java class script. Scriptrunner and/or groovy factors that in when implementing. Also helps better understand the interaction with the API structure. 

Thank you! :)

Like Dominic Lagger likes this
Nathanael Motz February 28, 2021

This is great but how do I extend it to other built-in scripts? CopyTree, for example. There is no CopyTreeCommand under com.onresolve.scriptrunner.canned.confluence.admin.model. How can I figure out which items are needed when creating a new instance of CopyTree (such as userAccessor, groupManager, etc used in the "AddRemoveWatchers watchers = new AddRemoveWatchers" command in the above script)?

Dominic Lagger
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 28, 2021

Hi, there is no way of finding it easily. 

What I did: I decrypted the jar File of the scriptrunner plugin and searched for the correct classes... for CopyTree, this is it: 

PageManager pageManager = ComponentLocator.getComponent(PageManager)
AttachmentManager attachmentManager = ComponentLocator.getComponent(AttachmentManager)
CommentManager commentManager = ComponentLocator.getComponent(CommentManager)
ContentPermissionManager contentPermissionManager = ComponentLocator.getComponent(ContentPermissionManager)
LabelManager labelManager = ComponentLocator.getComponent(LabelManager)
UserManager userManager = ComponentLocator.getComponent(UserManager)
EventPublisher pub = ComponentLocator.getComponent(EventPublisher)
ConfluenceApplicationProperties properties = ComponentLocator.getComponent(ConfluenceApplicationProperties)

@PluginModule
PermissionManager permissionManager

SpaceManager spaceManager = ComponentLocator.getComponent(SpaceManager)
TransactionTemplate transactionTemplate = ComponentLocator.getComponent(TransactionTemplate)
CopyPageService service = new CopyPageService(pageManager,attachmentManager,commentManager,contentPermissionManager,labelManager,permissionManager,spaceManager,userManager,pub)
CopyTree copyTree = new CopyTree(service)

Hope this helps for your project :) 

Regards

Like Nathanael Motz likes this
0 votes
Jillian Patterson March 1, 2021

Hi @Melanie Pasztor and @Nathanael Motz
I'm the Product Manager for ScriptRunner for Confluence and wanted to let you know that Adaptavist is working on this very thing to make it easier to automate our built-in script functionality whether it be as scheduled jobs or listeners. The first few will be Add/Remove Watchers, Copy Space, and Copy Page Tree listeners. Keep an eye out for more info in our newsletter and release notes. Hope this helps! 

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
SERVER
VERSION
7.3.5
TAGS
AUG Leaders

Atlassian Community Events