In this article I would like to discuss the problem of duplicating code in Adaptivist ScriptRunner.
When you start writing scripts in ScriptRunner, you usually write all the code in one script and then add this script to the post function, validator, condition, and the like.
Everything goes well until you find an error in the code, or there are no changes in the business requirements. At this point, you realize that you need to fix not one script, but several scripts with changed logic, and even worse, you do not remember which scripts you need to correct.
You can run a search in the directory where the scripts are located, but as practice shows, this solution almost always leaves bugs in the code.
This is a classic duplication problem.
Let's try to get rid of code duplication.
Method 1
The easiest way to solve a problem is to create an auxiliary class, which will contain the common parts of the code, and the groovy script will access this auxiliary class.
')
Let's try to implement it.
First, create a helper class named UtilHelper.groovy in the scripts / groovy / util directory:
package groovy.util; public class UtilHelper { public static String getMessage() { return "util helper message"; } }
Then we create a post function called postfunction.groovy in the scripts / groovy / directory. In this function post, we will call the getMessage function from our helper class.
package groovy import groovy.util.UtilHelper; log.error(UtilHelper.getMessage())
In order not to complicate the example, we will not add a post function to the business process, but call it from the script console (Script Console):

We received a message from the UitlHelper.groovy file. So our method 1 worked.
Now I would like to talk about the pitfalls of this method:
I tested this code on ScriptRunner version 5.2.2
- If I add the postfunction.groovy file as an inline script to the script console,
then the UitlHelper class is not always located for import. - I originally created postfunction.groovy in the scripts / groovy directory, and then moved the file to the scripts / groovy / util directory. But despite this, I could still import the class from the scripts / groovy / directory.
On earlier versions of ScriptRunner, the following problems are possible:
- A static compilation error occurs due to the fact that the compiler cannot find the class being imported by the UtilHelper. When the script is run, the script runs without errors.
- If you make changes to the helper class, the script does not see the changes in the helper class until you make changes to the script.
To avoid the problems of this method of implementation, as well as get a number of additional benefits, I would suggest a different way to solve the issue with duplicate code.
Method 2
This method is based on the fact that we have a plugin that contains common code. Thus, we could use common code both in our plugins and in ScriptRunner.
In my
previous article, I talked about how to make a plugin that can be accessed from other plugins. The plugin was called jira-library. The plugin provided the LibraryService service with the getLibraryMessage function. Let's try to call this function.
The jira-library plugin can be found
here . The plugin must be assembled with the
atlas-mvn package
installed in Jira.
Next, we need to write a script on ScriptRunner, which will refer to the jira-library plugin. The annotations @WithPlugin and @PluginModule are used for this. @WithPlugin allows you to import jira-library plugin classes, and @PluginModule allows you to embed (inject) LibraryService into a script. Read in detail about the principle of operation of these annotations
here .
The script will look like this:
import com.onresolve.scriptrunner.runner.customisers.PluginModule import com.onresolve.scriptrunner.runner.customisers.WithPlugin import ru.matveev.alexey.tutorial.library.api.LibraryService @WithPlugin("ru.matveev.alexey.tutorial.library.jira-library") @PluginModule LibraryService libraryService log.error(libraryService.getLibraryMessage()
Let's try to run it in the script console:

The screenshot shows that the message from the jira-library plugin is displayed. So our solution works.
With this method of implementation, the following problems arise:
The advantages of this approach are as follows:
- You can make common code for both developed plugins and scripts in ScriptRunner
- You can implement in your own plugin what ScriptRunner does not support, and then use the functionality of the plugin in ScriptRunner. For example, in this way you can implement feature toggle rotation . You can create a webwork type module that allows you to enable or disable some kind of functionality and place it in the plugins section. Then you can export a service that will inform the script in ScriptRunner whether the required functionality is enabled. If enabled, the script will perform the necessary actions.