Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

Create subtask which are linked to each-other Edited

Hello everyone,

I try to automatically create 3 subtasks at the creation of a specific issue type.

These subtasks are going to be call A,B and C.

I need A to blocks B and C.

I use ScriptRunner and I created the three subtasks using the "Create a subtask" post function of script-runner without any problem in the creation transition.

Now the linking part get me frustrated.

I tried to put it in several places:

  • In the additional issue actions of both B and C
  • In a postfunction in the workflow of both B and C (creation transition)
  • As a postfunction in the parent function after postfunction "Create a subtask"

It nevers works. When I get the parent issue object and ask for the lists of objects of subtasks (using issue.substasksObjects) it always giving me an empty list.

I think the substasks or at least the link between subtasks and parents are not in the index at this moment. I think so because the same type of code works well in the console when doing it just after creation of subtasks...

Any idea how to do it?

This is the code I use for the last place I tried (post-function in the parent workflow):

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.link.IssueLinkTypeManager

def loggedInUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def issueLinkTypeManager = ComponentAccessor.getComponent(IssueLinkTypeManager)
def issueManager = ComponentAccessor.issueManager

def subtasks = issue.subTaskObjects
log.debug(subtasks)

def aIssue = subtasks.find{it.issueType.name == "A"}
assert aIssue: "Subtask A can not be retrieve"

def bIssue = subtasks.find{it.issueType.name == "B"}
assert bIssue: "Subtask B can not be retrieve"

def cIssue = subtasks.find{it.issueType.name == "C"}
assert cIssue: "Subtask C can not be retrieve"

def linkType = issueLinkTypeManager.issueLinkTypes.findByName("Blocks")
assert linkType: "Blocks link type can not be retrieve"

ComponentAccessor.issueLinkManager.createIssueLink(aIssue.id, bIssue.id, linkType.id, 0L, loggedInUser)
ComponentAccessor.issueLinkManager.createIssueLink(aIssue.id, bIssue.id, linkType.id, 1L, loggedInUser)

 First assert give an error.

 

Thank you very much for you help

1 answer

1 accepted

0 votes
Answer accepted

Might be a terrible idea but, have you tried to add a waiting timer after the creation to ensure the parent-subTask links are created later? (given the validation you made that at a later point in time they are there)

Thank you for your answer @Fernando Bordallo

Based on https://community.atlassian.com/t5/Jira-questions/ScriptRunner-and-Post-Function-Scripts-order-and-execution/qaq-p/30485

I tried to put my script in a thread with a while loop and a sleep on it (1000 ms sleep, loop with a watchdog, 100 iteration maximum) but this does not work.

I tried the same on a listener on issue creation with no more luck.

It is just strange because during the time the script run (it tries for more than a minute) I can do the same on the console without any trouble!

Here is my listener:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.link.IssueLinkTypeManager

def loggedInUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def issueLinkTypeManager = ComponentAccessor.getComponent(IssueLinkTypeManager)
def issueManager = ComponentAccessor.issueManager

final int COUNT_MAX = 100;
final int SLEEP_TIME = 1000; //ms

def issue = event.issue
log.warn(issue)

if (["B", "C"].any{it == issue.issueType.name})
{
Thread.start {
log.warn(issue.issueType.name)
def subtasks = issue.parentObject.subTaskObjects
log.warn(subtasks)
def aIssue = subtasks.find{it.issueType.name == "A"}

int count = 0;

while (!aIssue)
{
if (count == COUNT_MAX)
{
log.warn ("Watchdog reached")
return
}
Thread.sleep(SLEEP_TIME);
subtasks = issue.parentObject.subTaskObjects
aIssue = subtasks.find{it.issueType.name == "A"}
log.warn (count);
count++;
}
log.warn(aIssue)

def linkType = issueLinkTypeManager.issueLinkTypes.findByName("Blocks")
log.warn(linkType)

ComponentAccessor.issueLinkManager.createIssueLink(aIssue.id, issue.id, linkType.id, (issue.issueType.name == "B" ? 0L : 1L), loggedInUser)
}

}

 

The first time I tried without a Thread.start. I thinked that every listener execution was running on a different Thread. I was wrong since it run and blocked between each post-function on the transition. The thread works, my post-function are running smoothly but it looks like the Thread can not access the updated index. It is really really strange...

Reading this: https://community.atlassian.com/t5/Answers-Developer-Questions/Post-Function-Order-Trying-to-Set-Assignee-Based-on-Field/qaq-p/512759

I had an idea to verify my script.

I created a self-transition to the status where I put the post-function posted on the original question and add a fast-transition at the end of all post-function at the create transition of issue.

When the transition is automatically made it fails. When I do it manually by clicking after creation, it works...

After few more test I keep asking myself "why the Thread never found the subtasks when it should?" and I finally find it, and as always I said to myself "You're moron".
Like you can see in every script I posted, I get the issue once. When subtasks are note available. Then in a thread I wait and ask the same MutableIssue to give me its subtasks and of course it give me the same answer! I never reload the MutableIssue...
So here is an implementation working, in a postfunction:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.link.IssueLinkTypeManager

def loggedInUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def issueLinkTypeManager = ComponentAccessor.getComponent(IssueLinkTypeManager)
def issueManager = ComponentAccessor.issueManager

// Due to asynchronous indexing that need to be done to retrieve subTasks
// This post-function need to be asynchronous of the other post function
Thread.start {
def reloadedIssue = issue;
def subtasks = reloadedIssue.subTaskObjects
def aIssue = subtasks.find{it.issueType.name == "A"}
def bIssue = subtasks.find{it.issueType.name == "B"}
def cIssue = subtasks.find{it.issueType.name == "C"}
final int MAX_COUNT = 100;
int count = 0;
final int TIME_SLEEP = 1000; //ms

while (!aIssue || !bIssue || !cIssue)
{
if (count == MAX_COUNT)
return
Thread.sleep(TIME_SLEEP);

// We need to reload the MutableObject
reloadedIssue = issueManager.getIssueObject(issue.key)
subtasks = reloadedIssue.subTaskObjects
aIssue = subtasks.find{it.issueType.name == "A"}
bIssue = subtasks.find{it.issueType.name == "B"}
cIssue = subtasks.find{it.issueType.name == "C"}
count++;
}
def linkType = issueLinkTypeManager.issueLinkTypes.findByName("Blocks")

ComponentAccessor.issueLinkManager.createIssueLink(aIssue.id, bIssue.id, linkType.id, 0L, loggedInUser)
ComponentAccessor.issueLinkManager.createIssueLink(aIssue.id, cIssue.id, linkType.id, 1L, loggedInUser)

 

Like Fernando Bordallo likes this

Thanks for updating the thread with your findings! They'll surely come in handy to the next one following your steps :)

Suggest an answer

Log in or Sign up to answer
TAGS
Community showcase
Posted in Jira Core

How to manage many similar workflows?

I have multiple projects that use variations of the same base workflow. The variations depend on the requirements of the project or issue type. The variations mostly come in the form of new statuses ...

3,894 views 11 5
Join discussion

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you