Issue transition in plugin fails when put in a different thread

Andris Bērziņš
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.
July 25, 2013

I have made a plugin that automatically transitions issue from one state to another after creation when certain users create the issue.

Originally the problem was that this transition failed in onIssueEvent code - my guess was because the issue hadn't finished creating and therefore was not eligible for transition. There are more details on this here: https://answers.atlassian.com/questions/191921/automatically-transitioning-issue-on-issuecreated-event

I had fixed it by putting the transition code in a separate thread and running it after a delay - it worked and issue was created successfully. However after I added a condition for workflow transition, this no longer works.

I did some testing and it seems that these transitions do not work when they are run in a different thread. Same transition worked perfectly when I executed it the main thread but failed when executed in a thread. Here is a sample code with the problem:

// function that makes the transition - this works fine when called directly
public static boolean ChangeIssueState(Issue opIssue, int ipNewState, User opUser)
{
	System.out.println(String.format("	ChangeIssueState [%s] to state: %s. Run by %s", 
			opIssue.getKey(),
			String.valueOf(ipNewState),
			opUser.getName()));
	
	IssueService issueService = ComponentAccessor.getIssueService();
	
	IssueInputParameters issueInputParameters = issueService.newIssueInputParameters();
	issueInputParameters.setRetainExistingValuesWhenParameterNotProvided(Boolean.TRUE);
	TransitionValidationResult transitionValidationResult = issueService.validateTransition(opUser, opIssue.getId(), ipNewState, issueInputParameters);
	
	if(transitionValidationResult.isValid())
	{
		IssueResult transitionResult = issueService.transition(opUser, transitionValidationResult);
		if(transitionResult.isValid()) 
		{
			System.out.println("	Transition Complete");
			
			return true;
		}
		else 
		{
			System.out.println("	Transition Failed");
		}
	}
	else 
	{
		System.out.println(String.format("	Invalid Transition: %s. Reasons: %s",
				transitionValidationResult.getErrorCollection().getErrors(),
				transitionValidationResult.getErrorCollection().getReasons()));
	}	
	
	return false;
}

// class that makes it possible to run the transition from a different thread
public static class ThreadedTransition implements Runnable
{
	private Issue ocIssue;
	private int icNewState;
	private User ocUser;
	private long icDelay; // ms
	
	public ThreadedTransition(Issue opIssue, int ipNewState, User opUser, long ipDelay)
	{
		ocIssue = opIssue;
		icNewState = ipNewState;
		ocUser = opUser;
		icDelay = ipDelay; 
	}

	@Override
	public void run() {
		System.out.println("[TRANSITION THREAD] sleeping..");
		try {
			Thread.sleep(icDelay);
		} catch (InterruptedException e) { }
		System.out.println("[TRANSITION THREAD] executing..");
		boolean bResult = Funcs.ChangeIssueState(ocIssue, icNewState, ocUser);

		System.out.println("[TRANSITION THREAD] finished: " + String.valueOf(bResult));
	}
}

// this is how I call the functions:
// this one fails:
new Thread(new Funcs.ThreadedTransition(issue, transition, ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser(), 5000)).start();
// this one works just fine:
new Thread(new Funcs.ThreadedTransition(issue, transition, ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser(), 5000)).run();

// output received for both of these:
/*

First call:

	[TRANSITION THREAD] sleeping..
	[TRANSITION THREAD] executing..
			ChangeIssueState [DK-10] to state: 11. Run by bandris
			Invalid Transition: {}. Reasons: []
	[TRANSITION THREAD] finished: false

Second call (output in the middle is from other parts of my plugin which simply prints out newly created issue information):

	[TRANSITION THREAD] sleeping..
	[TRANSITION THREAD] executing..
			ChangeIssueState [DK-10] to state: 11. Run by bandris
	EVENT: 13
	KEY:   DK-10
	TIME:  Thu Jul 25 11:35:29 EEST 2013
					All done
			Transition Complete
	[TRANSITION THREAD] finished: true

*/

Any help on how to automatically transition issue from one state to another right after creation would be appreciated. Thanks!

4 answers

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

1 vote
RambanamP
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.
July 25, 2013

did you tried by writing listener? you can place your code in issue create event .

another one is using script runner plugin, check this

https://jamieechlin.atlassian.net/wiki/display/GRV/Built-In+Scripts#Built-InScripts-Fast-tracktransitionanissue

Andris Bērziņš
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.
August 26, 2013

Yes. Everything already is in an issue create event. That, however, fails because the issue hasn't finished creating and therefore does not transition from there. That's why I tried another (delayed) thread.

I'll check out the script runner plugin, thanks for the link.

0 votes
Andris Bērziņš
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.
August 26, 2013

Yes, it is run in a listener. There is more info about it in the link in my question.

0 votes
Radu Dumitriu
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.
July 25, 2013

Yes, this is perfectly normal.

1/ There's some setup to be run on the thread. At minimum, you may wish to setup the user (it is kept on a thread local variable)

2/ Starting a thread like this seems at least dangerous. What if the time passes (or you have a spurious wakeup) and you go right into the ChangeIssueState ? What if the issue object gets already modified in the meantime ?

What are you trying to do is profoundly questionable. I advise you to keep the code into the same thread and place your postfunction as the last postfunction on the create transition.

RambanamP
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.
July 25, 2013

i don't think it will work even if the post function configure at the end of create transition, i tried but not successed:(

Nic Brough -Adaptavist-
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 25, 2013

Radu - the code is trying to issue a transition on an issue. I've never seen a successful implementation of that in a post-function (had a lot of work from rescuing systems where it's been attempted)

My instincts are screaming that it must be done outside the current transition, which means a listener. (They're also muttering that the new thread feels wrong, but I'm not a developer)

Radu Dumitriu
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.
July 25, 2013

We did it in JJupin :)

(it was a lot of pain, btw, but it's possible.)

Nic Brough -Adaptavist-
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 25, 2013

I've not used that. I wasn't saying it's not possible, just that I've never seen it work properly!

I am curious though - how do you get over the problem that the transition isn't finished when you're running the next one?

Florin Manaila
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.
July 25, 2013

@Nic AFAIK, listeners run in the same thread and are triggered by the "Trigger xxxxx event to be processed by listeners" post function from the transition, so they won't actually run outside the transition.

See comments on this answer: https://answers.atlassian.com/questions/178598/can-i-redirect-my-ui-through-a-listener-plugin?page=1#178970

Radu Dumitriu
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.
July 25, 2013

@Nic. We enforced some rules and postponed the actual update of the status on the issue. I must tell you that we have some advantage here: when you run JJupin/SIL scripts, you actually run them on copies of the issues, not on issue themselves, therefore ....

Nic Brough -Adaptavist-
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 25, 2013

@Florin - I know they run in the same thread. When I say they're "outside the transition", I'm meaning that as far as the workflow updates (on both the Jira issue data and the os_workflow stuff) is complete. So the transition has ended, and the listener is hanging off the end of it with a completed transition in terms of data. Whereas, a post-function is still inside the transition and hence it's incomplete.

@Radu - Ah, very clever. So the secondary update is not actually running inside the transition on the main issue. I like that trick!

0 votes
Nic Brough -Adaptavist-
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 25, 2013

Is this being run in a listener, or somewhere else?

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

TAGS
AUG Leaders

Atlassian Community Events