Groovy : Set Remaining time on subtask to 0

i am recently using the script runner plugin to autoclose suktasks when the parent issue is closed.

Can you tell me the lines to add to force the "Remaning Time" on subtasks to 0 at the same time ?

Thank you.

6 answers

1 accepted

2 votes
Accepted answer
Henning Tietgens Community Champion Mar 03, 2014

You can try this.

import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.config.SubTaskManager
import com.atlassian.jira.issue.IssueInputParameters
import com.atlassian.jira.issue.MutableIssue
import org.apache.log4j.Category
import static org.apache.log4j.Level.DEBUG

log = Category.getInstance("com.onresolve.jira.groovy.AutoCloseChildIssues")
log.debug "debug statements"

IssueService issueService = ComponentAccessor.getIssueService()
SubTaskManager subTaskManager = ComponentAccessor.getSubTaskManager();

if (subTaskManager.subTasksEnabled) {

    MutableIssue issue = issue  // this is only for the IDE
    log.debug (" " +
    def currentUser = ComponentAccessor.getUserUtil().getUser("muleuser")

    issue.getSubTaskObjects().each { subtask ->
        IssueInputParameters issueInputParameters = issueService.newIssueInputParameters();
        issueInputParameters.setComment("*Réouverte*, car la demande mère a été réouverte.")

        IssueService.TransitionValidationResult transitionValidationResult = issueService.validateTransition(currentUser,, 3, issueInputParameters);
        if (transitionValidationResult.isValid()){
            IssueService.IssueResult transitionResult = issueService.transition(currentUser, transitionValidationResult);
            if (!transitionResult.isValid()) {
                transitionResult.errorCollection.errorMessages.each {log.error "Error Message: $it"}
                transitionResult.errorCollection.errors.each {log.error "Error: $it"}
                transitionResult.errorCollection.reasons.each {log.error "Reason: $it"}
        } else {
            transitionValidationResult.errorCollection.errorMessages.each {log.error "Error Message: $it"}
            transitionValidationResult.errorCollection.errors.each {log.error "Error: $it"}
            transitionValidationResult.errorCollection.reasons.each {log.error "Reason: $it"}


There is a nice documentation on how to use the issueService. If it doesn't work there could be a problem with the transition screen. Take a look here, especially setSkipScreenCheck().

You are really Good, it works fine.

Another question : if I want set the estimate to 2h for example ?

I wrote setRemainingEstimate(2h) but i doesnt work

Henning Tietgens Community Champion Mar 03, 2014

Try setRemainingEstimate('2h')

Henning Tietgens Community Champion Mar 04, 2014

You have to make sure you're using a String as parameter, than it should work like documented here. Could you enter 2h manually while entering an estimate?

If it doesn't work you could calculate a long of 2h in your timetracking default units ( APKeys.JIRA_TIMETRACKING_DEFAULT_UNIT) and use this as parameter.

Yes, i can write 2h in the field "remaining estimate".

I also try issueInputParameters.setRemainingEstimate(1100L);

but no result

Henning Tietgens Community Champion Mar 04, 2014

Mmh. Setting to 0 works but not to any other value? What did you get if you call issueInputParameters.getRemainingEstimate() after setting the remaining estimate (before the transition)?

log.error "getRemainingEstimate(): ${issueInputParameters.getRemainingEstimate()}"

Are there any other errors in the log?

i found this error :

2014-03-05 13:42:34,087 ajp-bio-8009-exec-31 ERROR leprince.t 821x55358x1 1v714k4 /secure/WorkflowUIDispatcher.jspa [atlassian.event.internal.AsynchronousAbleEventDispatcher] There was an exception thrown trying to dispatch event 'com.atlassian.jira.event.issue.IssueEvent@122580a1[issue=PROJWMS-16227,comment=<null>,worklog=<null>,changelog=[GenericEntity:ChangeGroup][id,3359167][author,leprince.t][created,2014-03-05 13:42:24.05][issue,420304],eventTypeId=5,sendMail=true,params={eventsource=workflow, baseurl=},subtasksUpdated=false]' from the invoker 'SingleParameterMethodListenerInvoker{method=public void com.stef.jira.plugin.listener.JiraIssueListener.onIssueEvent(com.atlassian.jira.event.issue.IssueEvent), listener=com.stef.jira.plugin.listener.JiraIssueListener@2eedaaf4}'.
java.lang.RuntimeException: java.lang.StackOverflowError

Henning Tietgens Community Champion Mar 04, 2014

Do you have any recursion in your code? Could you post the complete stack trace?

(sample catalina.out.txt) contains all lines after the error line i sent before

Henning Tietgens Community Champion Mar 05, 2014

There is a recursion in this code part:


The numbers at the end are the line numbers in the source file. Maybe you should add some debug output to these lines to see why your code is calling itself over and over again. This leads to the stack overflow.

Ok thanks i will check that. we keep in touch

I tried on another jira instance, but it still doesnt work

Henning Tietgens Community Champion Mar 12, 2014

Any errors in the log?

0 votes
Henning Tietgens Community Champion Feb 24, 2014

Use issueService and issueInputParameters.setRemainingEstimate()

I had created a simliar script for this a few months ago. Maybe this can help you.

Usage: Create a JQL-Query that matchs the subtasks, you want to edit. Copy that query

Replace ("INSERT HERE YOUR JQL QUERY") with the created Query.

Run the script

import com.atlassian.jira.issue.Issue;

import com.atlassian.jira.issue.IssueManager;

import com.atlassian.jira.issue.MutableIssue;

import com.atlassian.jira.component.ComponentAccessor;

import com.atlassian.jira.issue.fields.CustomField;

import com.atlassian.jira.bc.JiraServiceContextImpl;

import com.atlassian.jira.bc.filter.SearchRequestService;


import com.atlassian.jira.component.ComponentAccessor;



import com.atlassian.jira.user.ApplicationUser;

import com.atlassian.jira.web.bean.PagerFilter;

import com.atlassian.query.Query;


SearchResults getissuesByJQL(String jql) throws Exception


        SearchService serchService = ComponentAccessor.getComponentOfType(SearchService.class);

        SearchService.ParseResult parseResult = serchService.parseQuery(ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser(), jql);


        if (!parseResult.isValid())


            throw new Exception("jql is not valid. jql was "+jql);



        Query query = parseResult.getQuery();

           SearchResults sr =, query, PagerFilter.getUnlimitedFilter());

            return sr;






void setEstimateToNull(String key) {
IssueManager im = ComponentAccessor.getIssueManager();
        MutableIssue issue = im.getIssueObject(key);



for (Issue issue : getissuesByJQL("INSERT HERE YOUR JQL QUERY").getIssues())




Hi Henning and Julian,

Many thanks for your asnwer.

Henning, here is my script, can you help me to apply what you said ?

import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.IssueService
import com.atlassian.jira.issue.comments.CommentManager
import com.opensymphony.workflow.WorkflowContext
import org.apache.log4j.Category
import com.atlassian.jira.config.SubTaskManager
import com.atlassian.jira.workflow.WorkflowTransitionUtil;
import com.atlassian.jira.workflow.WorkflowTransitionUtilImpl;
import com.atlassian.jira.util.JiraUtils;
import org.apache.log4j.Category
def Category log = Category.getInstance("com.onresolve.jira.groovy.PostFunction")
log.debug "debug statements"
log = Category.getInstance("com.onresolve.jira.groovy.AutoCloseChildIssues")
String currentUser = ComponentManager.getInstance().getUserUtil().getUser("muleuser").getName()

WorkflowTransitionUtil workflowTransitionUtil = ( WorkflowTransitionUtil ) JiraUtils.loadComponent( WorkflowTransitionUtilImpl.class );
SubTaskManager subTaskManager = ComponentManager.getInstance().getSubTaskManager();
Collection subTasks = issue.getSubTaskObjects()
if (subTaskManager.subTasksEnabled && !subTasks.empty) {
    subTasks.each {
        log.debug (" " +
        workflowTransitionUtil.setAction (3)    // 3 == REOPEN ISSUE
        // Add a comment so people have a clue why the child has been closed
        CommentManager commentManager = (CommentManager) ComponentManager.getComponentInstanceOfType(CommentManager.class);
        String comment = "*Réouverte*, car la demande mère a été réouverte.";
        commentManager.create(it, currentUser, comment, true);
        // validate and transition issue


i dont know how to use issueService and issueInputParameters.setRemainingEstimate()

Suggest an answer

Log in or Sign up to answer
Community showcase
Published Nov 29, 2018 in Jira

How to set up an incident workflow from the VP of Engineering at Sentry

Hey Atlassian community, I help lead engineering at Sentry, an open-source error-tracking and monitoring tool that integrates with Jira. We started using Jira Software Cloud internally last year, a...

1,088 views 0 8
Read article

Atlassian User Groups

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

Find a group

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

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you