Scriptrunner - Create subtask based on multi picker

Richard Duffy September 2, 2018

Hi All

 

I am new to scriptrunner and trying to create my own script to auto create sub-task based on a custom field (multi picker). Our UMS works from our active directory. Here is what i have so far, any help would be appreciated?

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.IssueFactory

def cfRIA = CustomFieldManager.getCustomFieldObjectByName("Release Impact Assessor(s)")
def issue = com.atlassian.jira.issue.MutableIssue
def issueObject = IssueFactory.getIssue()

Collection<ApplicationUser> users= (Collection) issue.getCustomFieldValue(cfRIA);

if(users != null)
{
for(i in 0..users.size()-1)
{
Object AssigneeValue = users.get(i).getName();

issueObject = IssueFactory.getIssue()
issueObject.setProjectObject(issue.getProjectObject())
issueObject.setIssueTypeId("10600")
issueObject.setParentId(issue.getId())

issueObject.setSummary(issue.getSummary())
issueObject.setAssigneeId(AssigneeValue)

subTask = issueManager.createIssue(authenticationContext.getUser(), issueObject)
subTaskManager.createSubTaskIssueLink(issue.getGenericValue(), subTask, authenticationContext.getUser())
i++
}

}

 

4 answers

1 accepted

1 vote
Answer accepted
Mark Markov
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 3, 2018

Hello @Richard Duffy

Is this postfunction?

Try this

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

def cfRIA = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("Release Impact Assessor(s)")
def issueObject = ComponentAccessor.issueFactory.getIssue()
Collection<ApplicationUser> users= (Collection) issue.getCustomFieldValue(cfRIA);

if(users != null)
{
for(i in 0..users.size()-1)
{
def AssigneeValue = users.get(i).getName();
issueObject.setProjectObject(issue.getProjectObject())
issueObject.setIssueTypeId("10600")
issueObject.setParentId(issue.getId())

issueObject.setSummary(issue.getSummary())
issueObject.setAssigneeId(AssigneeValue)
def issueManager = ComponentAccessor.getIssueManager()
def subTask = issueManager.createIssueObject(ComponentAccessor.jiraAuthenticationContext.getLoggedInUser(), issueObject)
ComponentAccessor.subTaskManager.createSubTaskIssueLink(issue, subTask, ComponentAccessor.jiraAuthenticationContext.getLoggedInUser())
i++
}

}
Richard Duffy September 3, 2018

Mark

 

Thanks for the reply, yes this is for a post function. 

I have edited my script using some of your code, now there i no errors. But when i run the script i get the following:

018-09-04 11:13:09,134 ERROR [workflow.ScriptWorkflowFunction]: Script function failed on issue: PILOT-263, actionId: 91, file: <inline script>
groovy.lang.MissingMethodException: No signature of method: static com.atlassian.jira.issue.MutableIssue.getCustomFieldValue() is applicable for argument types: (com.atlassian.jira.issue.fields.ImmutableCustomField) values: [Release Impact Assessor(s)]
 at Script584.run(Script584.groovy:10)



Here is the script:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.config.SubTaskManager

def cfRIA = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("Release Impact Assessor(s)")
def issueObject = ComponentAccessor.issueFactory.getIssue()
def issue = com.atlassian.jira.issue.MutableIssue

Collection<ApplicationUser> users= (Collection) issue.getCustomFieldValue(cfRIA);

if(users != null)
{
for(i in 0..users.size()-1)
{
def AssigneeValue = users.getAt(i).getName();
issueObject.setProjectObject(issue.getProjectObject())
issueObject.setIssueTypeId("10600")
issueObject.setParentId(issue.getId())

issueObject.setSummary(issue.getSummary())
issueObject.setAssigneeId(AssigneeValue)

def issueManager = ComponentAccessor.getIssueManager()
def subTask = issueManager.createIssueObject(ComponentAccessor.jiraAuthenticationContext.getLoggedInUser(), issueObject)
def SubTaskManager = ComponentAccessor.getSubTaskManager()
def JiraAuthenticationContext = ComponentAccessor.getJiraAuthenticationContext()

ComponentAccessor.SubTaskManager.createSubTaskIssueLink(issueObject, subTask, ComponentAccessor.jiraAuthenticationContext.getLoggedInUser())
i++
}

}

 

Thanks for the feedback

Richard

0 votes
Andreas Kroschel July 14, 2022

Hi @Chris Annal

 

Thank you so much for your script. I've added two lines to copy the description too and it works perfectly. Kudos to you!

def description = parentIssue.getDescription()
[…]
newSubTask.setDescription(description)
0 votes
Martin Maida April 7, 2022

Hello,

I try to create a new subtask for a parent with a Scritpt but after run the code the ERROR:

Somebody know what it is :

2022-04-07 16:19:20,707 WARN [runner.AbstractScriptRunner]: Script D:\Atlassian\Application Data\Jira\XXXXXXXXXXX\SkillsAutofill.groovy failed to load/compile
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
file:/D:/Atlassian/Application%20Data/Jira/XXXXX/JiraSupport/Connection/BigPicture.groovy: 15: unable to resolve class groovy.json.internal.LazyMap
@ line 15, column 1.
import groovy.json.internal.LazyMap
^
1 error
2022-04-07 16:19:21,660 ERROR [runner.AbstractScriptListener]: *************************************************************************************
2022-04-07 16:19:21,660 ERROR [runner.AbstractScriptListener]: Script function failed on event: com.atlassian.jira.event.issue.IssueEvent, file: null
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
file:/D:/Atlassian/Application%20Data/Jira/XXXXXX/JiraSupport/Connection/BigPicture.groovy: 15: unable to resolve class groovy.json.internal.LazyMap
@ line 15, column 1.
import groovy.json.internal.LazyMap

 

 

 

 

____________________________________________________________________________________________

My code is

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.fields.config.manager.PrioritySchemeManager

// the issue key of the parent issue
final parentIssueKey = 'PROJ-13973'

// the issue type for the new issue - should be of type subtask
final issueTypeName = 'Sub-task'

// user with that user key will be the reporter of the issue
final reporterKey = 'TESTER'

// the summary of the new issue
final summary = 'Groovy Friday'

// the priority of the new issue
final priorityName = 'High'

def issueService = ComponentAccessor.issueService
def constantsManager = ComponentAccessor.constantsManager
def loggedInUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def prioritySchemeManager = ComponentAccessor.getComponent(PrioritySchemeManager)

def parentIssue = ComponentAccessor.issueManager.getIssueByCurrentKey(parentIssueKey)
assert parentIssue : "Could not find parent issue with key $parentIssueKey"

def subtaskIssueTypes = constantsManager.allIssueTypeObjects.findAll { it.subTask }
def subTaskIssueType = subtaskIssueTypes.findByName(issueTypeName)
assert subTaskIssueType : "Could not find subtask issue type with name $issueTypeName. Avaliable subtask issue types are ${subtaskIssueTypes*.name.join(", ")}"

// if we cannot find user with the specified key or this is null, then set as a reporter the logged in user
def reporter = ComponentAccessor.userManager.getUserByKey(reporterKey) ?: loggedInUser

// if we cannot find the priority with the given name or if this is null, then set the default priority
def priorityId = constantsManager.priorities.findByName(priorityName)?.id ?: prioritySchemeManager.getDefaultOption(parentIssue)

def issueInputParameters = issueService.newIssueInputParameters().with {
setProjectId(parentIssue.projectObject.id)
setIssueTypeId(subTaskIssueType.id)
setReporterId(reporter.username)
setSummary(summary)
setPriorityId(priorityId)
}


issueInputParameters.setOriginalAndRemainingEstimate(100,100)

 

issueInputParameters.addCustomFieldValue(10544, '11507' )
issueInputParameters.addCustomFieldValue(10601, '12911' )
issueInputParameters.addCustomFieldValue(10601, '12706' )
issueInputParameters.addCustomFieldValue(10229, '31/DEC/22' )
issueInputParameters.addCustomFieldValue(10235, '01/FEB/22' )

def validationResult = issueService.validateSubTaskCreate(loggedInUser, parentIssue.id, issueInputParameters)
assert validationResult.valid : validationResult.errorCollection

def issueResult = issueService.create(loggedInUser, validationResult)
assert issueResult.valid : issueResult.errorCollection

def subtask = issueResult.issue
ComponentAccessor.subTaskManager.createSubTaskIssueLink(parentIssue, subtask, loggedInUser)

0 votes
Richard Duffy September 5, 2018

Hi @Mark Markov

I just figured out you cant write a script for Post Function in the console. When i put your script in the workflow it does work and creates a subtask. However when I enter multiple users in the multi pick field it still just creates 1 subtask, can you advise?

 

Thanks for the help

Richard

Richard Duffy September 5, 2018

Mark

 

I got my script working for multiple users, here it is:

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

def cfRIA = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("Release Impact Assessor(s)")

Collection<ApplicationUser> users= (Collection) issue.getCustomFieldValue(cfRIA);

if(users != null)
{
for(i in 0..users.size()-1)
{
Object AssigneeValue = users.get(i).getName();

issueObject = ComponentAccessor.getIssueFactory().getIssue()
issueObject.setProjectObject(issue.getProjectObject())
issueObject.setIssueTypeId("10600")
issueObject.setParentId(issue.getId())

issueObject.setSummary(issue.getSummary() + ' ' + users.get(i).getName() + ' - Impact Assessment')
issueObject.setAssigneeId(AssigneeValue)
def issueManager = ComponentAccessor.getIssueManager()
def subTask = issueManager.createIssueObject(ComponentAccessor.jiraAuthenticationContext.getLoggedInUser(), issueObject)
ComponentAccessor.subTaskManager.createSubTaskIssueLink(issue, subTask, ComponentAccessor.jiraAuthenticationContext.getLoggedInUser())
i++
}

}

 

There is one part of the script i dont really understand:

Collection<ApplicationUser> users= (Collection) issue.getCustomFieldValue(cfRIA);

Can you explain the Collection? Where can i find the Collections in ->  https://docs.atlassian.com/software/jira/docs/api/7.8.0/overview-summary.html

 

Thanks Again

Richard

Mark Markov
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 6, 2018

Hello

Collection is a java interface

You can read here.

Richard Duffy September 6, 2018

Cheers Mark

Deleted user May 15, 2020

Thanks for providing this!! I think it may help me solve a problem I've been having.

VTB SAM4 July 22, 2020

I met many error when tried by copy this Script. Pls see this attach file.

At this code line: Object AssigneeValue = users.get(i).getName();

--> I meet this Error: 

[Static type checking] - can not find matching method
java.util.Collection#get(Java.lang.Integer). Please check if the declared type is right and if the method exits.
Possible solution: grep(), grep(), getAt(int),getAt(Java.lang.String),
getAt(jaba.lang.String), grep (java.lang.Object)@line14,column 25.

 

Please help me asap. Thank so much

Chris Annal July 23, 2020

(Edited 10/29/2020 to add a line to "set" the Due Date to the parent's Due Date.)

Give this script a try. I indicated where in the script you need to modify it to suit the custom field you are trying to create sub-tasks for. Note that some lines below "wrap" to the next line. Be mindful of this when copying/pasting.

 

// Imports
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.issue.MutableIssue

// import for debug only
import org.apache.log4j.Logger
import org.apache.log4j.Level
log = Logger.getLogger("com.acme.CreateSubtask")
log.setLevel(Level.DEBUG)

//Current issue - uncomment for post-function
Issue parentIssue = issue

//Get Value of Required Reviewers - Replace "XXXXX" in "customfield_XXXXX" with the actual value of your custom field
CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager()
String customfieldID_MultiUserFieldName = 'customfield_XXXXX'
CustomField customfield_MultiUserFieldName = customFieldManager.getCustomFieldObject(customfieldID_MultiUserFieldName)
Object customfieldIDValue_MultiUserFieldName = (ArrayList) parentIssue.getCustomFieldValue(customfield_MultiUserFieldName)

//Pre-define JQL Parser functions
def queryParser = ComponentAccessor.getComponent(JqlQueryParser)
def searchService = ComponentAccessor.getComponent(SearchService)
def activeUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

//Pre-define Sub-Task Generation functions
def issueFactory = ComponentAccessor.getIssueFactory()
def subTaskManager = ComponentAccessor.getSubTaskManager()
def constantManager = ComponentAccessor.getConstantsManager()
def issueManager = ComponentAccessor.getIssueManager()

//Get Values to copy from Parent
def summary = "Subtask for " + parentIssue.getSummary()
def dueDate = parentIssue.getDueDate()
def project = parentIssue.getProjectObject()

//Define Sub-Task Type - Replace "PUT CUSTOM FIELD NAME HERE" with the actual name you're using for your custom field
def issueTypeId = constantManager.getAllIssueTypeObjects().find{it.getName() == "PUT CUSTOM FIELD NAME HERE"}.id

//Iterate through and create subtasks
for (int i = 0; i < customfieldIDValue_MultiUserFieldName.size(); i++){
ApplicationUser reviewerObject = customfieldIDValue_MultiUserFieldName[i] as ApplicationUser
String reviewer = reviewerObject?.name
log.debug reviewer
//do not create sub-tasks if a sub-task already exists and has a certain Resolution
def query = queryParser.parseQuery("parent = ${parentIssue} and assignee = ${reviewer} and (resolution = Abstained or resolution = Approved or resolution = Unresolved)")
log.debug query
def search = searchService.search(activeUser, query, PagerFilter.getUnlimitedFilter())
def total = search.total
log.debug total
if (total == 0){
//Create core Sub-Task Values
MutableIssue newSubTask = issueFactory.getIssue()
newSubTask.setProjectObject(project)
newSubTask.setIssueTypeId(issueTypeId)
newSubTask.setParentObject(parentIssue)
newSubTask.setSummary(summary)
newSubTask.setDueDate(dueDate)
newSubTask.setReporter(activeUser)
//Assign Sub-Task
newSubTask.setAssigneeId(reviewer)
log.debug newSubTask.assigneeId
//Create Sub-Task
def newIssueParams = ["issue" : newSubTask] as Map
log.debug "Creating task for ${reviewer}"
def createdSubTask = issueManager.createIssueObject(activeUser, newIssueParams)
subTaskManager.createSubTaskIssueLink(parentIssue, createdSubTask, activeUser)
}

}

 

Like Andreas Kroschel likes this
VTB SAM4 July 26, 2020

Hi Chris_Annal, thanks so much for your Reply!

If I use a Multi User Custom field. When I run Script, I meet this error:

The following log information was produced by this execution. Use statements like:log.info("...") to record logging information.

2020-07-27 10:08:39,121 ERROR [workflow.ScriptWorkflowFunction]: *************************************************************************************
2020-07-27 10:08:39,121 ERROR [workflow.ScriptWorkflowFunction]: Script function failed on issue: UTL-111, actionId: 1, file: <inline script>
java.lang.NullPointerException: Cannot get property 'id' on null object
at Script1180.run(Script1180.groovy:44)

If I Use a Group User Custom Field (I want to use Group User Custom Field)), I meet this error:

Time (on server): Mon Jul 27 2020 09:43:02 GMT+0700 (Indochina Time)

The following log information was produced by this execution. Use statements like:log.info("...") to record logging information.

2020-07-27 09:43:02,296 ERROR [workflow.ScriptWorkflowFunction]: *************************************************************************************
2020-07-27 09:43:02,297 ERROR [workflow.ScriptWorkflowFunction]: Script function failed on issue: UTL-109, actionId: 1, file: <inline script>
java.lang.NullPointerException
at com.atlassian.jira.issue.IssueImpl.getCustomFieldValue(IssueImpl.java:896)
at com.atlassian.jira.issue.Issue$getCustomFieldValue$1.call(Unknown Source)
at Script1172.run(Script1172.groovy:25)

Please help me. I want to create SubTask for a Group User (This Group get value from a Custom Field)

Thanks so much!

VTB SAM4 July 26, 2020

I tried again. It's fine for a Multi User Custom field. But I need for a Group User Custom Field. Can you help me? Thanks so much!

VTB SAM4 July 26, 2020

I have more one Question, how can I Set value for a MuitiUser Custom Field base on value of an User Group Custom field. Please help. Thanks so much!

VTB SAM4 July 27, 2020

I already above problem. But I have a new question:

I want to use Script Runner Behavior to Set "Start Date" is Start of current Month, "End Date" is End of Current Month. Please help, thanks so much!

Chris Annal July 28, 2020

Sorry I can't help you for a Group User Custom Field. That seems like a much more complex problem.

Also, your last comment suggests an entirely different topic. I'd suggest you ask that type of question in a new thread, only because anyone else with that problem is not likely to look under this topic for an answer.

Like Richard Duffy likes this
Swati Gupta June 12, 2022

Hi @Chris Annal - I tried your script for my requirement, which is listed below:

Post function is required- There is a custom field known as products (can have multiple values) - if it has 1 value, 1 subtask having its summary as product name should be created, if it has 2 values, 2 subtasks to be created, 3 values in products, 3 subtasks to be created and so on.
Used your script:

// Imports
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.issue.MutableIssue

// import for debug only
import org.apache.log4j.Logger
import org.apache.log4j.Level
log = Logger.getLogger("com.acme.CreateSubtask")
log.setLevel(Level.DEBUG)

//Current issue - uncomment for post-function
Issue parentIssue = issue

//Get Value of Required Reviewers - Replace "XXXXX" in "customfield_XXXXX" with the actual value of your custom field
CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager()
String customfieldID_MultiUserFieldName = 'customfield_18410'
CustomField customfield_MultiUserFieldName = customFieldManager.getCustomFieldObject(customfieldID_MultiUserFieldName)
Object customfieldIDValue_MultiUserFieldName = (ArrayList) parentIssue.getCustomFieldValue(customfield_MultiUserFieldName)

//Pre-define JQL Parser functions
def queryParser = ComponentAccessor.getComponent(JqlQueryParser)
def searchService = ComponentAccessor.getComponent(SearchService)
def activeUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

//Pre-define Sub-Task Generation functions
def issueFactory = ComponentAccessor.getIssueFactory()
def subTaskManager = ComponentAccessor.getSubTaskManager()
def constantManager = ComponentAccessor.getConstantsManager()
def issueManager = ComponentAccessor.getIssueManager()

//Get Values to copy from Parent
def summary = "Subtask for " + parentIssue.getSummary()
def dueDate = parentIssue.getDueDate()
def project = parentIssue.getProjectObject()

//Define Sub-Task Type - Replace "PUT CUSTOM FIELD NAME HERE" with the actual name you're using for your custom field
def issueTypeId = constantManager.getAllIssueTypeObjects().find{it.getName() == "products"}.id

//Iterate through and create subtasks
for (int i = 0; i < customfieldIDValue_MultiUserFieldName.size(); i++){
ApplicationUser reviewerObject = customfieldIDValue_MultiUserFieldName[i] as ApplicationUser
String reviewer = reviewerObject?.name
log.debug reviewer
//do not create sub-tasks if a sub-task already exists and has a certain Resolution
def query = queryParser.parseQuery("parent = ${parentIssue} and assignee = ${reviewer} and (resolution = Abstained or resolution = Approved or resolution = Unresolved)")
log.debug query
def search = searchService.search(activeUser, query, PagerFilter.getUnlimitedFilter())
def total = search.total
log.debug total
if (total == 0){
//Create core Sub-Task Values
MutableIssue newSubTask = issueFactory.getIssue()
newSubTask.setProjectObject(project)
newSubTask.setIssueTypeId(issueTypeId)
newSubTask.setParentObject(parentIssue)
newSubTask.setSummary(summary)
newSubTask.setDueDate(dueDate)
newSubTask.setReporter(activeUser)
//Assign Sub-Task
newSubTask.setAssigneeId(reviewer)
log.debug newSubTask.assigneeId
//Create Sub-Task
def newIssueParams = ["issue" : newSubTask] as Map
log.debug "Creating task for ${reviewer}"
def createdSubTask = issueManager.createIssueObject(activeUser, newIssueParams)
subTaskManager.createSubTaskIssueLink(parentIssue, createdSubTask, activeUser)
}

}

======================================================

Below is the error:

2022-06-12 10:54:17,052 ERROR [workflow.AbstractScriptWorkflowFunction]: Workflow script has failed on issue TPFSPP-2 for user 'ac-swagup'. View here: https://jira-dev.assaabloy.net/secure/admin/workflows/ViewWorkflowTransition.jspa?workflowMode=live&workflowName=Software+Simplified+Workflow+for+Project+TPFSPP&descriptorTab=postfunctions&workflowTransition=11&highlight=1 java.lang.NullPointerException: Cannot get property 'id' on null object at Script162.run(Script162.groovy:45)

Suggest an answer

Log in or Sign up to answer