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

Next challenges

Recent achievements

  • Global
  • Personal

Recognition

  • Give kudos
  • Received
  • Given

Leaderboard

  • Global

Trophy case

Kudos (beta program)

Kudos logo

You've been invited into the Kudos (beta program) private group. Chat with others in the program, or give feedback to Atlassian.

View group

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

Why do my listeners on delete events interfere to delete issues? Edited

Hi all!
I have a big trouble with deleting issues. I only can't delete issue that has subtasks. I have some listeners that set up on some delete events (IssueDeletedEvent, IssueLinkDeletedEvent and PreDeleteEvent). Processes in them are not simple but clearly - update custom field in subtask only or update custom field in task/subtask. Listener starts its work if the event was thrown by subtask.
When I try to delete subtask is no problem, but when I try to delete task (that has subtasks of course) - appears window with information that timeout was exceeded.

When I disable code part that responsible for update custom field value all works fine.

May be who met this problem and knows how to resolve this?

And what order of deleting issue? A can't find this information in web, it will very helpful for me.
Thanks!

/*

Event: IssueLinkDeleted

Note:
Update two custom fields cfOne and cfTwo
fields are collections with options
Field values in epic contain all field values in tasks
Field values in task contain all field values in subtask
Field values mutable only in subtasks
Create and delete link events set up only to subtasks

All ids was replaced by patterns

*/


import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.customfields.option.Option
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.link.IssueLinkManager
import com.atlassian.jira.issue.link.IssueLink
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import org.apache.log4j.Level
import org.apache.log4j.Logger

class Managers {
static final CustomFieldManager CUSTOM_FIELD_MANAGER = ComponentAccessor.getCustomFieldManager()
static final IssueLinkManager ISSUE_LINK_MANAGER = ComponentAccessor.getIssueLinkManager()
static final IssueManager ISSUE_MANAGER = ComponentAccessor.getIssueManager()
}

class Ids {

static final Long ONE_CF_ID = 11111L // custom field
static final Long TWO_CF_ID = 11111L // custom field

static final String SUBTASK_ISSUE_TYPE_ID = "11111"
static final Long EPIC_LINK_ID = 11111L
static final Long SUB_TASK_ISSUE_LINK_TYPE_ID = 11111L

}


Logger log = Logger.getLogger("!!!")
log.setLevel(Level.DEBUG)

IssueLink issueLink = event.getIssueLink()
Issue epic = null;

if (issueLink.getIssueLinkType().getId() == Ids.SUB_TASK_ISSUE_LINK_TYPE_ID) {
// link between task and subtask (subtask is removed)
Issue task = issueLink.getSourceObject();
epic = getEpicByTask(task);
} else if (issueLink.getIssueLinkType().getId() == Ids.EPIC_LINK_ID) {
// link between epic and task (task is removed)
epic = issueLink.getSourceObject();
}
if (epic) {
log.debug("EPIC_KEY = ${epic.getKey()}")
Set<Option> cfOneNewValues = updateTasksAndGetAllOptionsFromTasks(epic, Ids.ONE_CF_ID, log)
Set<Option> cfTwoNewValues = updateTasksAndGetAllOptionsFromTasks(epic, Ids.TWO_CF_ID, log)
updateEpic(epic, Ids.ONE_CF_ID, cfOneNewValues)
updateEpic(epic, Ids.TWO_CF_ID, cfTwoNewValues)
}
log.debug("script end")


private Issue getEpicByTask(Issue task) {
if (task) {
List<IssueLink> inwards = Managers.ISSUE_LINK_MANAGER.getInwardLinks(task.getId())
for (IssueLink link : inwards) {
log.debug(link)
Long currentLinkId = link.getIssueLinkType().getId()
if (currentLinkId == Ids.EPIC_LINK_ID) {
return link.getSourceObject()
}
}
}
return null;
}

private Set<Option> updateTasksAndGetAllOptionsFromTasks(Issue epic, Long cfId, Logger log) {
Set<Option> options = new HashSet<>()
List<IssueLink> links = Managers.ISSUE_LINK_MANAGER.getOutwardLinks(epic.getId())
for (IssueLink link : links) {
Long currentLinkId = link.getIssueLinkType().getId()
if (currentLinkId == Ids.EPIC_LINK_ID) {
Issue task = link.getDestinationObject()
log.debug("FOUND TASK ${task}")
CustomField cfObj = Managers.CUSTOM_FIELD_MANAGER.getCustomFieldObject(cfId)
Set<Option> prevVal = task.getCustomFieldValue(cfObj) as Set<Option>
Set<Option> newVal = getFieldOptionsFromSubtasks(task, cfId, Ids.SUB_TASK_ISSUE_LINK_TYPE_ID, log)
log.debug("NEW TASK VALUE BY SUBTASK ${newVal}")
if (prevVal != newVal) {
cfObj.updateValue(null, task, new ModifiedValue(prevVal, newVal), new DefaultIssueChangeHolder())
}
options.addAll(newVal)
}
}
return options
}


private Set<Option> getFieldOptionsFromSubtasks(Issue issue, Long cfId, Long linkId, Logger log) {
Set<Option> options = new HashSet<>()
List<IssueLink> links = Managers.ISSUE_LINK_MANAGER.getOutwardLinks(issue.getId())
for (IssueLink link : links) {
Long currentLinkId = link.getIssueLinkType().getId()
if (currentLinkId == linkId) {
Issue child = link.getDestinationObject()
Set<Option> cfValues = child.getCustomFieldValue(Managers.CUSTOM_FIELD_MANAGER.getCustomFieldObject(cfId)) as Set<Option>
if (cfValues) {
options.addAll(cfValues)
}
}
}
return options
}

private void updateEpic(Issue epic, Long cfId, Set<Option> values) {
CustomField customField = Managers.CUSTOM_FIELD_MANAGER.getCustomFieldObject(cfId)
Set<Option> prevVal = epic.getCustomFieldValue(customField) as Set<Option>
if (prevVal != values) {
customField.updateValue(null, epic, new ModifiedValue(prevVal, values), new DefaultIssueChangeHolder())
}
}

2 answers

I didn't ahve this problem in the past so I can'T point you to a solution directly but this sounds like there is an exception thrown somewhere in your code if you delete a task with subtasks, which leads to your timeout. Most likely your listeners on your subtasks somehow assume logically that there is a (parent-)task present and if you try to delete it this assumptions fails (by throwing an exception that the "task-value" cant be NULL, or something similar. 

To troubleshoot and find the problem I would enable logging for your listeners (https://docs.adaptavist.com/sfj/set-logging-to-help-debug-your-scripts-11993359.html), trigger the timeout and then check your logs at the time of your test for exceptions related to your problem.

I have been using logging and I have no errors or exception there. I also thought that a parent of subtask doesn't exist more and the problem in that, but when listener starts - the parent exists (I had checked that by logs).

mhh that is strange. Do you mind sharing your code? Maybe a second pair of eyes sees the error.

/*

Event: IssueLinkDeleted

Note:
Update two custom fields cfOne and cfTwo
fields are collections with options
Field values in epic contain all field values in tasks
Field values in task contain all field values in subtask
Field values mutable only in subtasks
Create and delete link events set up only to subtasks

All ids was replaced by patterns

*/


import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.customfields.option.Option
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.link.IssueLinkManager
import com.atlassian.jira.issue.link.IssueLink
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import org.apache.log4j.Level
import org.apache.log4j.Logger

class Managers {
static final CustomFieldManager CUSTOM_FIELD_MANAGER = ComponentAccessor.getCustomFieldManager()
static final IssueLinkManager ISSUE_LINK_MANAGER = ComponentAccessor.getIssueLinkManager()
static final IssueManager ISSUE_MANAGER = ComponentAccessor.getIssueManager()
}

class Ids {

static final Long ONE_CF_ID = 31510L // custom field
static final Long TWO_CF_ID = 35916L // custom field

static final String SUBTASK_ISSUE_TYPE_ID = "11111"
static final Long EPIC_LINK_ID = 11111L
static final Long SUB_TASK_ISSUE_LINK_TYPE_ID = 11111L

}


Logger log = Logger.getLogger("!!!")
log.setLevel(Level.DEBUG)

IssueLink issueLink = event.getIssueLink()
Issue epic = null;

if (issueLink.getIssueLinkType().getId() == Ids.SUB_TASK_ISSUE_LINK_TYPE_ID) {
// link between task and subtask (subtask is removed)
Issue task = issueLink.getSourceObject();
epic = getEpicByTask(task);
} else if (issueLink.getIssueLinkType().getId() == Ids.EPIC_LINK_ID) {
// link between epic and task (task is removed)
epic = issueLink.getSourceObject();
}
if (epic) {
log.debug("EPIC_KEY = ${epic.getKey()}")
Set<Option> cfOneNewValues = updateTasksAndGetAllOptionsFromTasks(epic, Ids.ONE_CF_ID, log)
Set<Option> cfTwoNewValues = updateTasksAndGetAllOptionsFromTasks(epic, Ids.TWO_CF_ID, log)
updateEpic(epic, Ids.ONE_CF_ID, cfOneNewValues)
updateEpic(epic, Ids.TWO_CF_ID, cfTwoNewValues)
}
log.debug("script end")


private Issue getEpicByTask(Issue task) {
if (task) {
List<IssueLink> inwards = Managers.ISSUE_LINK_MANAGER.getInwardLinks(task.getId())
for (IssueLink link : inwards) {
log.debug(link)
Long currentLinkId = link.getIssueLinkType().getId()
if (currentLinkId == Ids.EPIC_LINK_ID) {
return link.getSourceObject()
}
}
}
return null;
}

private Set<Option> updateTasksAndGetAllOptionsFromTasks(Issue epic, Long cfId, Logger log) {
Set<Option> options = new HashSet<>()
List<IssueLink> links = Managers.ISSUE_LINK_MANAGER.getOutwardLinks(epic.getId())
for (IssueLink link : links) {
Long currentLinkId = link.getIssueLinkType().getId()
if (currentLinkId == Ids.EPIC_LINK_ID) {
Issue task = link.getDestinationObject()
log.debug("FOUND TASK ${task}")
CustomField cfObj = Managers.CUSTOM_FIELD_MANAGER.getCustomFieldObject(cfId)
Set<Option> prevVal = task.getCustomFieldValue(cfObj) as Set<Option>
Set<Option> newVal = getFieldOptionsFromSubtasks(task, cfId, Ids.SUB_TASK_ISSUE_LINK_TYPE_ID, log)
log.debug("NEW TASK VALUE BY SUBTASK ${newVal}")
if (prevVal != newVal) {
cfObj.updateValue(null, task, new ModifiedValue(prevVal, newVal), new DefaultIssueChangeHolder())
}
options.addAll(newVal)
}
}
return options
}


private Set<Option> getFieldOptionsFromSubtasks(Issue issue, Long cfId, Long linkId, Logger log) {
Set<Option> options = new HashSet<>()
List<IssueLink> links = Managers.ISSUE_LINK_MANAGER.getOutwardLinks(issue.getId())
for (IssueLink link : links) {
Long currentLinkId = link.getIssueLinkType().getId()
if (currentLinkId == linkId) {
Issue child = link.getDestinationObject()
Set<Option> cfValues = child.getCustomFieldValue(Managers.CUSTOM_FIELD_MANAGER.getCustomFieldObject(cfId)) as Set<Option>
if (cfValues) {
options.addAll(cfValues)
}
}
}
return options
}

private void updateEpic(Issue epic, Long cfId, Set<Option> values) {
CustomField customField = Managers.CUSTOM_FIELD_MANAGER.getCustomFieldObject(cfId)
Set<Option> prevVal = epic.getCustomFieldValue(customField) as Set<Option>
if (prevVal != values) {
customField.updateValue(null, epic, new ModifiedValue(prevVal, values), new DefaultIssueChangeHolder())
}
}
/*

Event: IssueLinkDeleted

Note:
Update two custom fields cfOne and cfTwo
fields are collections with options
Field values in epic contain all field values in tasks
Field values in task contain all field values in subtask
Field values mutable only in subtasks
Create and delete link events set up only to subtasks

All ids was replaced by patterns

*/


import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.customfields.option.Option
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.link.IssueLinkManager
import com.atlassian.jira.issue.link.IssueLink
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import org.apache.log4j.Level
import org.apache.log4j.Logger

class Managers {
static final CustomFieldManager CUSTOM_FIELD_MANAGER = ComponentAccessor.getCustomFieldManager()
static final IssueLinkManager ISSUE_LINK_MANAGER = ComponentAccessor.getIssueLinkManager()
static final IssueManager ISSUE_MANAGER = ComponentAccessor.getIssueManager()
}

class Ids {

static final Long ONE_CF_ID = 31510L // custom field
static final Long TWO_CF_ID = 35916L // custom field

static final String SUBTASK_ISSUE_TYPE_ID = "11111"
static final Long EPIC_LINK_ID = 11111L
static final Long SUB_TASK_ISSUE_LINK_TYPE_ID = 11111L

}


Logger log = Logger.getLogger("!!!")
log.setLevel(Level.DEBUG)

IssueLink issueLink = event.getIssueLink()
Issue epic = null;

if (issueLink.getIssueLinkType().getId() == Ids.SUB_TASK_ISSUE_LINK_TYPE_ID) {
// link between task and subtask (subtask is removed)
Issue task = issueLink.getSourceObject();
epic = getEpicByTask(task);
} else if (issueLink.getIssueLinkType().getId() == Ids.EPIC_LINK_ID) {
// link between epic and task (task is removed)
epic = issueLink.getSourceObject();
}
if (epic) {
log.debug("EPIC_KEY = ${epic.getKey()}")
Set<Option> cfOneNewValues = updateTasksAndGetAllOptionsFromTasks(epic, Ids.ONE_CF_ID, log)
Set<Option> cfTwoNewValues = updateTasksAndGetAllOptionsFromTasks(epic, Ids.TWO_CF_ID, log)
updateEpic(epic, Ids.ONE_CF_ID, cfOneNewValues)
updateEpic(epic, Ids.TWO_CF_ID, cfTwoNewValues)
}
log.debug("script end")


private Issue getEpicByTask(Issue task) {
if (task) {
List<IssueLink> inwards = Managers.ISSUE_LINK_MANAGER.getInwardLinks(task.getId())
for (IssueLink link : inwards) {
log.debug(link)
Long currentLinkId = link.getIssueLinkType().getId()
if (currentLinkId == Ids.EPIC_LINK_ID) {
return link.getSourceObject()
}
}
}
return null;
}

private Set<Option> updateTasksAndGetAllOptionsFromTasks(Issue epic, Long cfId, Logger log) {
Set<Option> options = new HashSet<>()
List<IssueLink> links = Managers.ISSUE_LINK_MANAGER.getOutwardLinks(epic.getId())
for (IssueLink link : links) {
Long currentLinkId = link.getIssueLinkType().getId()
if (currentLinkId == Ids.EPIC_LINK_ID) {
Issue task = link.getDestinationObject()
log.debug("FOUND TASK ${task}")
CustomField cfObj = Managers.CUSTOM_FIELD_MANAGER.getCustomFieldObject(cfId)
Set<Option> prevVal = task.getCustomFieldValue(cfObj) as Set<Option>
Set<Option> newVal = getFieldOptionsFromSubtasks(task, cfId, Ids.SUB_TASK_ISSUE_LINK_TYPE_ID, log)
log.debug("NEW TASK VALUE BY SUBTASK ${newVal}")
if (prevVal != newVal) {
cfObj.updateValue(null, task, new ModifiedValue(prevVal, newVal), new DefaultIssueChangeHolder())
}
options.addAll(newVal)
}
}
return options
}


private Set<Option> getFieldOptionsFromSubtasks(Issue issue, Long cfId, Long linkId, Logger log) {
Set<Option> options = new HashSet<>()
List<IssueLink> links = Managers.ISSUE_LINK_MANAGER.getOutwardLinks(issue.getId())
for (IssueLink link : links) {
Long currentLinkId = link.getIssueLinkType().getId()
if (currentLinkId == linkId) {
Issue child = link.getDestinationObject()
Set<Option> cfValues = child.getCustomFieldValue(Managers.CUSTOM_FIELD_MANAGER.getCustomFieldObject(cfId)) as Set<Option>
if (cfValues) {
options.addAll(cfValues)
}
}
}
return options
}

private void updateEpic(Issue epic, Long cfId, Set<Option> values) {
CustomField customField = Managers.CUSTOM_FIELD_MANAGER.getCustomFieldObject(cfId)
Set<Option> prevVal = epic.getCustomFieldValue(customField) as Set<Option>
if (prevVal != values) {
customField.updateValue(null, epic, new ModifiedValue(prevVal, values), new DefaultIssueChangeHolder())
}
}
/*

Event: IssueLinkDeleted

Note:
Update two custom fields cfOne and cfTwo
fields are collections with options
Field values in epic contain all field values in tasks
Field values in task contain all field values in subtask
Field values mutable only in subtasks
Create and delete link events set up only to subtasks

All ids was replaced by patterns

*/


import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.customfields.option.Option
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.link.IssueLinkManager
import com.atlassian.jira.issue.link.IssueLink
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import org.apache.log4j.Level
import org.apache.log4j.Logger

class Managers {
static final CustomFieldManager CUSTOM_FIELD_MANAGER = ComponentAccessor.getCustomFieldManager()
static final IssueLinkManager ISSUE_LINK_MANAGER = ComponentAccessor.getIssueLinkManager()
static final IssueManager ISSUE_MANAGER = ComponentAccessor.getIssueManager()
}

class Ids {

static final Long ONE_CF_ID = 11111L // custom field
static final Long TWO_CF_ID = 11111L // custom field

static final String SUBTASK_ISSUE_TYPE_ID = "11111"
static final Long EPIC_LINK_ID = 11111L
static final Long SUB_TASK_ISSUE_LINK_TYPE_ID = 11111L

}


Logger log = Logger.getLogger("!!!")
log.setLevel(Level.DEBUG)

IssueLink issueLink = event.getIssueLink()
Issue epic = null;

if (issueLink.getIssueLinkType().getId() == Ids.SUB_TASK_ISSUE_LINK_TYPE_ID) {
// link between task and subtask (subtask is removed)
Issue task = issueLink.getSourceObject();
epic = getEpicByTask(task);
} else if (issueLink.getIssueLinkType().getId() == Ids.EPIC_LINK_ID) {
// link between epic and task (task is removed)
epic = issueLink.getSourceObject();
}
if (epic) {
log.debug("EPIC_KEY = ${epic.getKey()}")
Set<Option> cfOneNewValues = updateTasksAndGetAllOptionsFromTasks(epic, Ids.ONE_CF_ID, log)
Set<Option> cfTwoNewValues = updateTasksAndGetAllOptionsFromTasks(epic, Ids.TWO_CF_ID, log)
updateEpic(epic, Ids.ONE_CF_ID, cfOneNewValues)
updateEpic(epic, Ids.TWO_CF_ID, cfTwoNewValues)
}
log.debug("script end")


private Issue getEpicByTask(Issue task) {
if (task) {
List<IssueLink> inwards = Managers.ISSUE_LINK_MANAGER.getInwardLinks(task.getId())
for (IssueLink link : inwards) {
log.debug(link)
Long currentLinkId = link.getIssueLinkType().getId()
if (currentLinkId == Ids.EPIC_LINK_ID) {
return link.getSourceObject()
}
}
}
return null;
}

private Set<Option> updateTasksAndGetAllOptionsFromTasks(Issue epic, Long cfId, Logger log) {
Set<Option> options = new HashSet<>()
List<IssueLink> links = Managers.ISSUE_LINK_MANAGER.getOutwardLinks(epic.getId())
for (IssueLink link : links) {
Long currentLinkId = link.getIssueLinkType().getId()
if (currentLinkId == Ids.EPIC_LINK_ID) {
Issue task = link.getDestinationObject()
log.debug("FOUND TASK ${task}")
CustomField cfObj = Managers.CUSTOM_FIELD_MANAGER.getCustomFieldObject(cfId)
Set<Option> prevVal = task.getCustomFieldValue(cfObj) as Set<Option>
Set<Option> newVal = getFieldOptionsFromSubtasks(task, cfId, Ids.SUB_TASK_ISSUE_LINK_TYPE_ID, log)
log.debug("NEW TASK VALUE BY SUBTASK ${newVal}")
if (prevVal != newVal) {
cfObj.updateValue(null, task, new ModifiedValue(prevVal, newVal), new DefaultIssueChangeHolder())
}
options.addAll(newVal)
}
}
return options
}


private Set<Option> getFieldOptionsFromSubtasks(Issue issue, Long cfId, Long linkId, Logger log) {
Set<Option> options = new HashSet<>()
List<IssueLink> links = Managers.ISSUE_LINK_MANAGER.getOutwardLinks(issue.getId())
for (IssueLink link : links) {
Long currentLinkId = link.getIssueLinkType().getId()
if (currentLinkId == linkId) {
Issue child = link.getDestinationObject()
Set<Option> cfValues = child.getCustomFieldValue(Managers.CUSTOM_FIELD_MANAGER.getCustomFieldObject(cfId)) as Set<Option>
if (cfValues) {
options.addAll(cfValues)
}
}
}
return options
}

private void updateEpic(Issue epic, Long cfId, Set<Option> values) {
CustomField customField = Managers.CUSTOM_FIELD_MANAGER.getCustomFieldObject(cfId)
Set<Option> prevVal = epic.getCustomFieldValue(customField) as Set<Option>
if (prevVal != values) {
customField.updateValue(null, epic, new ModifiedValue(prevVal, values), new DefaultIssueChangeHolder())
}
}
/*

Event: IssueLinkDeleted

Note:
Update two custom fields cfOne and cfTwo
fields are collections with options
Field values in epic contain all field values in tasks
Field values in task contain all field values in subtask
Field values mutable only in subtasks
Create and delete link events set up only to subtasks

All ids was replaced by patterns

*/


import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.customfields.option.Option
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.link.IssueLinkManager
import com.atlassian.jira.issue.link.IssueLink
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import org.apache.log4j.Level
import org.apache.log4j.Logger

class Managers {
static final CustomFieldManager CUSTOM_FIELD_MANAGER = ComponentAccessor.getCustomFieldManager()
static final IssueLinkManager ISSUE_LINK_MANAGER = ComponentAccessor.getIssueLinkManager()
static final IssueManager ISSUE_MANAGER = ComponentAccessor.getIssueManager()
}

class Ids {

static final Long ONE_CF_ID = 11111L // custom field
static final Long TWO_CF_ID = 11111L // custom field

static final String SUBTASK_ISSUE_TYPE_ID = "11111"
static final Long EPIC_LINK_ID = 11111L
static final Long SUB_TASK_ISSUE_LINK_TYPE_ID = 11111L

}


Logger log = Logger.getLogger("!!!")
log.setLevel(Level.DEBUG)

IssueLink issueLink = event.getIssueLink()
Issue epic = null;

if (issueLink.getIssueLinkType().getId() == Ids.SUB_TASK_ISSUE_LINK_TYPE_ID) {
// link between task and subtask (subtask is removed)
Issue task = issueLink.getSourceObject();
epic = getEpicByTask(task);
} else if (issueLink.getIssueLinkType().getId() == Ids.EPIC_LINK_ID) {
// link between epic and task (task is removed)
epic = issueLink.getSourceObject();
}
if (epic) {
log.debug("EPIC_KEY = ${epic.getKey()}")
Set<Option> cfOneNewValues = updateTasksAndGetAllOptionsFromTasks(epic, Ids.ONE_CF_ID, log)
Set<Option> cfTwoNewValues = updateTasksAndGetAllOptionsFromTasks(epic, Ids.TWO_CF_ID, log)
updateEpic(epic, Ids.ONE_CF_ID, cfOneNewValues)
updateEpic(epic, Ids.TWO_CF_ID, cfTwoNewValues)
}
log.debug("script end")


private Issue getEpicByTask(Issue task) {
if (task) {
List<IssueLink> inwards = Managers.ISSUE_LINK_MANAGER.getInwardLinks(task.getId())
for (IssueLink link : inwards) {
log.debug(link)
Long currentLinkId = link.getIssueLinkType().getId()
if (currentLinkId == Ids.EPIC_LINK_ID) {
return link.getSourceObject()
}
}
}
return null;
}

I add listener code. Want to add that this problem is meeting in another listeners and each has some delete event and lines contained function with update custom field values. If I remove line that responsible for update custom field then I can delete a task

I tried but unfortunately I cant find the Error. Maybe you should reconsider your approach like Nic mentioned.

 a

0 votes

If you're going to delete issues (recommendation - don't, certainly not automatically, but that's not the point of your question), you must stagger the issue/subtask delete.

Sub-tasks have to have a parent issue, stripping their parent away breaks in many "interesting" ways.  You must delete them before touching the parent.

Suggest an answer

Log in or Sign up to answer
TAGS
Community showcase
Published in Marketplace Apps & Integrations

New Cloud Apps Roundup - Spring 2021

Atlassian's marketplace partners have had a very productive start to 2021! Since our last roundup, our developer community has added over 160 new cloud apps to the Atlassian Marketplace to help you...

89 views 1 12
Read article

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