Shared Groovy Scripts
This document details the Shared Groovy scripts feature of JMWE. Using this you can define global Groovy scripts that will be available from any Groovy script written in the Groovy console, post-functions, conditions and validators. This is useful for reusing complex/lengthy scripts across multiple workflow transitions. It is available under JMWE administration pages.
On this page:
Create a Shared Groovy Script
To create a shared Groovy script:
Click on Shared Groovy Scripts
Click on
New shared script
Enter the name of this shared script in
Shared script name
. This name can be used as the name of theClass
that will contain all methods and data members defined in the script.Enter an optional description in
Description
.Input a valid Groovy script in
Groovy script
. It is strongly recommended to wrap any (static) method in a class.Click on
Save
.
Edit a Shared Groovy Script
To edit a Shared Groovy script:
Click on
Shared Groovy Scripts
Click on
Edit
for the specific Shared Groovy ScriptModify the script.
Click on
Save
.
Delete a Shared Groovy Script
To delete a Shared Groovy script:
Click on
Shared Groovy Scripts
Click on
Delete
for the specific Shared Groovy ScriptConfirm the action.
The Shared Groovy Script gets deleted.
It is strongly recommended to remove the references to the Shared Groovy Script in any workflow extension before deleting it.
Shared Groovy Scripts best practices
Defining a static method
In this example, we will create a simple static method plusOne
in a shared Groovy Script named Functions
. Note, the name of the shared script becomes the name of a class.
static int plusOne(int i) {
return i+1;
}
You can use this in a Groovy script section of any workflow extension (e.g. a Scripted Groovy Operation post-function) like this:
return Functions.plusOne(1)
When you test this script in the Groovy editor against any issue the tester will return 2
Defining an explicit class
In this example, we will create a shared script named GreetMe
with the script:
class GreetMe{
String aString = "Hello"
String sayIt() {
return aString;
}
}
You can use this in a Groovy script section of any workflow extension (e.g. a Scripted Groovy Operation post-function) like this:
def obj = new GreetMe()
return obj.sayIt()
When you test this script in the Groovy editor against any issue the tester will return Hello
Defining multiple classes inside a single shared script
In this example, we will create a shared script named MyClasses
with the script:
interface Animal {
String getName()
}
class Cat implements Animal {
String getName() {
return "Cat"
}
}
static String exec() {
return new Cat().name
}
You can use this in a Groovy script section of any workflow extension (e.g. a Scripted Groovy Validator) like this:
return new Cat().name == MyClasses.exec()
When you test this script in the Groovy editor against any issue the tester will return true
Defining a service with access to global variables and functions
The global variables and functions that can be used in any Groovy script defined in a workflow extension are not available directly in shared Groovy scripts. The easiest approach to be able to access them is to define a class that will contain all the desired methods (non-static) and to pass the globals to that class. This will be like a "Service". For example:
import com.atlassian.jira.issue.IssueManager
class MyService {
private Script globals;
public MyService(Script globals) {
this.globals = globals;
}
public String getIssueKey() {
return globals.issue.key;
}
public Issue getIssue(String key) {
return globals.getComponent(IssueManager).getIssueObject(key)
}
}
And you can then use this "Service" from the main script:
MyService utils = new MyService(this)
utils.issueKey //calls the getIssueKey() method, which accesses the issue global variable
utils.getIssue("TEST-1") //calls the getIssue method which accesses the global getComponent function
Use cases for Shared Groovy scripts
Add Days to Date excluding weekends
Create a shared Groovy script that adds a certain number of days to a date excluding weekends
Create a shared groovy script,
AddDaysExcludingWeekends
, with the following scriptstatic Date addWorkingDays(Date from, int nod){ Calendar c1 = GregorianCalendar.getInstance(); c1.setTime(from); int weeks = nod/5; int remDays = nod%5; //Adding whole weeks c1.add(Calendar.WEEK_OF_YEAR, weeks); //Run a loop and check each day to skip a weekend for(int i=1;i<=remDays;i++){ c1.add(Calendar.DAY_OF_MONTH, 1); if (c1.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) c1.add(Calendar.DAY_OF_MONTH, 1); if (c1.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) c1.add(Calendar.DAY_OF_MONTH, 1); } //Skip ending weekend if (c1.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) c1.add(Calendar.DAY_OF_MONTH, 1); if (c1.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) c1.add(Calendar.DAY_OF_MONTH, 1); //move to 0:00 c1.clearTime(); return c1.getTime(); }
Save it.
You can use this in a post-function to set a Date-time picker field. For example Set a Date time picker field to the Due date plus 5 days, excluding weekends. The script in the post-function will be:
return AddDaysExcludingWeekends.addWorkingDays(issue.duedate,5)
Check for attachments with a specific extension during a transition
Create a shared validator that checks for attachments of a specific extension were added to the transition screen
Create a shared groovy script,
AttachmentValidator
, with the following script:import com.atlassian.jira.issue.IssueFieldConstants import com.atlassian.jira.issue.attachment.Attachment import com.atlassian.jira.issue.attachment.TemporaryWebAttachment import com.atlassian.jira.issue.attachment.TemporaryWebAttachmentManager class AttachmentValidator{ static checkAttachments(issue,ext){ TemporaryWebAttachmentManager attachmentManager = ComponentAccessor.getComponent(TemporaryWebAttachmentManager) try { List<Long> ids = issue.getModifiedFields().get(IssueFieldConstants.ATTACHMENT).getNewValue(); if (ids) return ids.any { id -> def attachment = attachmentManager.getTemporaryWebAttachment(id).getOrNull() return attachment?.filename?.endsWith(ext) } } catch (Exception e) { } return false } }
Save it.
Now you can use this in Scripted Groovy validator across transitions to validate the attachments added on the transition screen. Add the Scripted Groovy validator and call the method passing the issue
variable and extension as parameters.
AttachmentValidator.checkAttachments(issue,".pdf")