transition issue after transition post-function

Steffen Becker January 23, 2020

On a workflow transition, I run a ScriptRunner script. On a certain condition within this script, I want to transition this issue once again.

This is what I have:

ApplicationUser currentUser = ComponentAccessor.getJiraAuthenticationContext().loggedInUser
IssueService issueService = ComponentAccessor.getIssueService()
def transitionValidationResult = issueService.validateTransition(currentUser, issue.id, transitionId, new IssueInputParametersImpl())
def transitionResult = issueService.transition(currentUser, transitionValidationResult)

 I get no error.

And when I have a look into my issue, I see in the Issue History an entry which says the transition happened - but actually the issue is still in the "old" status.

 

I run this on a Service Desk project.

4 answers

1 accepted

0 votes
Answer accepted
Antoine Berry
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
January 24, 2020

Hi @Steffen Becker ,

That is the code I am using to transition issues : 

import com.atlassian.jira.workflow.WorkflowTransitionUtil
import com.atlassian.jira.util.JiraUtils

WorkflowTransitionUtil workflowTransitionUtil = ( WorkflowTransitionUtil ) JiraUtils.loadComponent( WorkflowTransitionUtilImpl.class );
workflowTransitionUtil.setIssue(issue);


workflowTransitionUtil.setUserkey("user_key")
def transitionId = 11

workflowTransitionUtil.setAction(transitionId);
workflowTransitionUtil.progress();

Maybe that will help.

Steffen Becker January 24, 2020

Thank you it works!

Even though it prints me a warning message: "use ComponentManager.loadComponent"

Antoine Berry
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
January 24, 2020

Maybe this snippet is a bit outdated, but I cannot find the loadComponent method in the javadoc, and jiraUtils' one is not deprecated in the javadoc. Maybe something to keep in mind for future versions though.

If you are satisfied with the answer please mark it as accepted so it can help others too. 

oneagain July 16, 2021

Hello @Antoine Berry 

I try to do the same thing, a post function that clones the issue (Scriptrunner PF) and that will transition the cloned issue, but this snippet does not work for me.

Any idea please ?


java.lang.NullPointerException: Cannot get property 'class' on null object
at Script306.run(Script306.groovy:11)

line 11 is :

WorkflowTransitionUtil workflowTransitionUtil = ( WorkflowTransitionUtil ) JiraUtils.loadComponent(WorkflowTransitionUtilImpl.class);

Like Antoine Berry likes this
oneagain July 16, 2021

I found another snippet here : https://community.atlassian.com/t5/Jira-questions/How-to-transition-an-issue-from-a-groovy-script-in-JIRA/qaq-p/917751

I adapted to my environment :

import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.bc.issue.IssueService;
import com.atlassian.jira.issue.IssueInputParametersImpl;
import org.apache.log4j.Logger;
import org.apache.log4j.Level;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.event.issue.IssueEventBundle;
import com.atlassian.jira.event.issue.IssueEventManager;
import com.atlassian.jira.event.issue.IssueEventBundleFactory;
import com.atlassian.jira.event.issue.IssueEvent;
import com.opensymphony.workflow.WorkflowContext
import com.atlassian.jira.workflow.WorkflowTransitionUtil;
import com.atlassian.jira.workflow.WorkflowTransitionUtilImpl;
import com.atlassian.jira.util.JiraUtils;
import com.opensymphony.workflow.loader.StepDescriptor;
import com.atlassian.jira.*;
import com.atlassian.jira.workflow.WorkflowManager;
import com.atlassian.jira.workflow.JiraWorkflow;
import com.opensymphony.workflow.loader.ActionDescriptor;
import com.atlassian.jira.issue.MutableIssue


import com.atlassian.jira.workflow.WorkflowTransitionUtil
import com.atlassian.jira.util.JiraUtils


def customFieldManagerT = ComponentAccessor.getCustomFieldManager();


def issueEventManager = ComponentAccessor.getIssueEventManager();
int EVENT_ID = 711
def issueManager = ComponentAccessor.getIssueManager()


WorkflowTransitionUtil workflowTransitionUtil = ( WorkflowTransitionUtil ) JiraUtils.loadComponent( WorkflowTransitionUtilImpl.class );
MutableIssue mi = issueManager.getIssueObject(issue.getKey());
workflowTransitionUtil.setIssue(mi);
workflowTransitionUtil.setAction(EVENT_ID);
//workflowTransitionUtil.validate(); i had to comment out these 2 last lines because I had errors and the clone was not created
//workflowTransitionUtil.progress();

 

Even if this time, the post function is executed without errors and does create the clone for the 1st time, the transition of the cloned issue did not change ...

 

Any idea ?

Antoine Berry
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
July 19, 2021

Hi @oneagain ,

I have found a snippet, I think it is worth a try :

import com.atlassian.jira.workflow.WorkflowTransitionUtil
import com.atlassian.jira.workflow.WorkflowTransitionUtilFactory
import com.atlassian.jira.component.ComponentAccessor

WorkflowTransitionUtil workflowTransitionUtil = ComponentAccessor.getComponent(WorkflowTransitionUtilFactory.class).create()
workflowTransitionUtil.setIssue(issue);
workflowTransitionUtil.setUserkey("user_key")

def transitionId = 11
workflowTransitionUtil.setAction(transitionId);
workflowTransitionUtil.progress();
oneagain July 19, 2021

Hello @Antoine Berry 

Thank you but just tested in the postfunction : ko

 

java.lang.IllegalArgumentException: User null doesn't have permission transition for issue null. at com.atlassian.jira.workflow.WorkflowTransitionUtilImpl.retrieveActionDescriptorWithPermissionCheck(WorkflowTransitionUtilImpl.java:142) at com.atlassian.jira.workflow.WorkflowTransitionUtilImpl.getActionDescriptor(WorkflowTransitionUtilImpl.java:133) at com.atlassian.jira.workflow.WorkflowTransitionUtilImpl.hasScreen(WorkflowTransitionUtilImpl.java:361) at com.atlassian.jira.workflow.WorkflowTransitionUtilImpl.progress(WorkflowTransitionUtilImpl.java:338) at com.atlassian.jira.workflow.WorkflowTransitionUtil$progress$2.call(Unknown Source) at Script153.run(Script153.groovy:11)

 

Fyi, the post function is the "Clones an issue, and links [ScriptRunner]" and in the additional action I added a small snippet to empty a specific field, which works, but not the part that should transition the newly cloned/created issue.

 

Based on this last error, it seems it is not able to transition a null issue, so it does not exist at this time. But how is he able to empty the field I asked ?

Like Antoine Berry likes this
oneagain July 19, 2021

I also tried this script from adaptavist : https://library.adaptavist.com/entity/transition-an-issue-using-issue-input-parameters

And it is dedicated for post function so I thought it would work.

So I removed the non necessary part to go like this :

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


final actionName = 'Done'


def issueService = ComponentAccessor.issueService

def workflowManager = ComponentAccessor.workflowManager


def workflowActionId = workflowManager.getWorkflow(issue).allActions.findByName(actionName)?.id

def issueInputParameters = issueService.newIssueInputParameters()


def transitionValidationResult = issueService.validateTransition(currentUser, issue.id, workflowActionId, issueInputParameters)
assert transitionValidationResult.valid: transitionValidationResult.errorCollection

def transitionResult = issueService.transition(currentUser, transitionValidationResult)
assert transitionResult.valid: transitionResult.errorCollection

But it failed, also with error like "null issue" :

 

java.lang.AssertionError: Errors: {}
Error Messages: [You can not transition a null issue.]. Expression: transitionValidationResult.valid
at Script189.run(Script189.groovy:19)
at com.onresolve.scriptrunner.runner.AbstractScriptRunner.runScriptAndGetContext(AbstractScriptRunner.groovy:174)
at com.onresolve.scriptrunner.runner.AbstractScriptRunner$runScriptAndGetContext$3.callCurrent(Unknown Source)
at com.onresolve.scriptrunner.runner.AbstractScriptRunner.runScriptAndGetContext(AbstractScriptRunner.groovy:293)
at com.onresolve.scriptrunner.runner.ScriptRunner$runScriptAndGetContext$9.call(Unknown Source)
at com.onresolve.scriptrunner.canned.jira.utils.ConditionUtils.doAdditional(ConditionUtils.groovy:112)
at com.onresolve.scriptrunner.canned.jira.utils.ConditionUtils$doAdditional.call(Unknown Source)
at com.onresolve.scriptrunner.workflow.DefaultWorkflowScriptExecutor.doAdditional(DefaultWorkflowScriptExecutor.groovy:29)
at com.onresolve.scriptrunner.workflow.WorkflowScriptExecutor$doAdditional$0.call(Unknown Source)
at com.onresolve.scriptrunner.canned.jira.utils.AbstractCloneIssue.cloneIssue(AbstractCloneIssue.groovy:270)
at com.onresolve.scriptrunner.canned.jira.utils.AbstractCloneIssue.execute(AbstractCloneIssue.groovy:184)
at com.onresolve.scriptrunner.canned.jira.utils.CopyIssueWithAttachments.super$4$execute(CopyIssueWithAttachments.groovy)
at com.onresolve.scriptrunner.canned.jira.utils.CopyIssueWithAttachments.execute(CopyIssueWithAttachments.groovy:29)
at com.onresolve.scriptrunner.canned.jira.workflow.postfunctions.CloneIssue.super$5$execute(CloneIssue.groovy)
at com.onresolve.scriptrunner.canned.jira.workflow.postfunctions.CloneIssue.execute(CloneIssue.groovy:158)
at com.onresolve.scriptrunner.canned.jira.workflow.postfunctions.CloneIssue$execute$0.callCurrent(Unknown Source)
at com.onresolve.scriptrunner.canned.jira.workflow.AbstractWorkflowCannedScript.execute(AbstractWorkflowCannedScript.groovy:23)
at com.onresolve.scriptrunner.canned.jira.workflow.AbstractWorkflowCannedScript$execute$2.call(Unknown Source)
at com.onresolve.scriptrunner.jira.workflow.AbstractScriptWorkflowFunction$_run_closure2.doCall(AbstractScriptWorkflowFunction.groovy:89)
at com.onresolve.scriptrunner.jira.workflow.AbstractScriptWorkflowFunction$_run_closure2.doCall(AbstractScriptWorkflowFunction.groovy)
at com.onresolve.scriptrunner.runner.diag.DiagnosticsManagerImpl$DiagnosticsExecutionHandlerImpl$_execute_closure1.doCall(DiagnosticsManagerImpl.groovy:359)
at com.onresolve.scriptrunner.runner.diag.DiagnosticsManagerImpl$DiagnosticsExecutionHandlerImpl$_execute_closure1.doCall(DiagnosticsManagerImpl.groovy)
at com.onresolve.scriptrunner.runner.ScriptExecutionRecorder.withRecording(ScriptExecutionRecorder.groovy:13)
at com.onresolve.scriptrunner.runner.ScriptExecutionRecorder$withRecording.call(Unknown Source)
at com.onresolve.scriptrunner.runner.diag.DiagnosticsManagerImpl$DiagnosticsExecutionHandlerImpl.execute(DiagnosticsManagerImpl.groovy:357)
at com.onresolve.scriptrunner.runner.diag.DiagnosticsExecutionHandler$execute$2.call(Unknown Source)
at com.onresolve.scriptrunner.jira.workflow.AbstractScriptWorkflowFunction.run(AbstractScriptWorkflowFunction.groovy:82)
Like Antoine Berry likes this
1 vote
oneagain September 3, 2021

Hello, just to complete this thread, I finally ended with this :

(I was actually missing the part doAfterCreate = {} with the help of Adaptavist)

 

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

doAfterCreate = { // the step you want sub-tasks to be transitioned tofinal actionName = 'Done' def issueService = ComponentAccessor.issueService def workflowManager = ComponentAccessor.workflowManagerdef workflowActionId = workflowManager.getWorkflow(issue).allActions.findByName(actionName)?.id def issueInputParameters = issueService.newIssueInputParameters() def transitionValidationResult = issueService.validateTransition(currentUser, issue.id, workflowActionId, issueInputParameters) assert transitionValidationResult.valid: transitionValidationResult.errorCollection def transitionResult = issueService.transition(currentUser, transitionValidationResult) assert transitionResult.valid: transitionResult.errorCollection }
1 vote
oneagain July 19, 2021

Tried this also, it works from the SR console, for 1 existing issue (already created)

but not in a post function to be applied on the soon-to-be cloned issue ... :(

 

import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.bc.issue.IssueService;
import com.atlassian.jira.issue.IssueInputParametersImpl;
import org.apache.log4j.Logger;
import org.apache.log4j.Level;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.event.issue.IssueEventBundle;
import com.atlassian.jira.event.issue.IssueEventManager;
import com.atlassian.jira.event.issue.IssueEventBundleFactory;
import com.atlassian.jira.event.issue.IssueEvent;
import com.opensymphony.workflow.WorkflowContext
import com.atlassian.jira.workflow.WorkflowTransitionUtil;
import com.atlassian.jira.workflow.WorkflowTransitionUtilImpl;
import com.atlassian.jira.util.JiraUtils;
import com.opensymphony.workflow.loader.StepDescriptor;
import com.atlassian.jira.*;
import com.atlassian.jira.workflow.WorkflowManager;
import com.atlassian.jira.workflow.JiraWorkflow;
import com.opensymphony.workflow.loader.ActionDescriptor;
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.workflow.WorkflowTransitionUtil
import com.atlassian.jira.util.JiraUtils
import com.atlassian.sal.api.user.UserManager
import com.atlassian.jira.user.util.UserManager
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.bc.issue.IssueService.TransitionValidationResult;
//final transitionId = 761
final id = 21
def issueId= "TEST-15"
//Issue issue = getIssueByID(issueId)
def issueManager = ComponentAccessor.getIssueManager()
def issue = issueManager.getIssueObject(issueId)
def boolean transitionIssue(Issue issue, int Id) {
boolean result = false;
IssueService issueService = ComponentAccessor.getIssueService();
IssueService.IssueResult transResult;
UserManager userManager = ComponentAccessor.getUserManager()
ApplicationUser user = userManager.getUserByName("valiantys")
TransitionValidationResult validationResult = issueService.validateTransition(user, issue.getId(), Id, issueService.newIssueInputParameters());
if (validationResult.isValid()) {
transResult = issueService.transition(user, validationResult);
log.warn("Transition has been made")
} else {
log.error("There was an issue with this transition : " + validationResult.getErrorCollection())
}
}

transitionIssue(issue,id)
0 votes
Marina Veselić September 18, 2023

Hi!

The accepted answer was useful and we used it a lot. However the class WorkflowTransitionUtil became deprecated in Jira 9.x and Scriptrunner 8.x. The workaround suggested by the official documentation suggests using IssueService.transition() which reintroduces the old problem suggested in the original post. At least for us in the case of transitioning an issue in the post function. For us, also, there is no error, the log says the transition was completed successfully, but the issue remains in the old status.

Is there an answer for this problem without using WorkflowTransitionUtil?

Cheers,
Marina

Stefan Stadler March 11, 2024

I would be interested in this as well. Same problem here and since WorkflowTransitionUtil is deprecated, there is no visible solution to us.

Thanks for any help!

Stefan

Like Antoine Berry likes this

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events