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

How to Throw a Custom Issue Event from a Custom Listener

jldubz July 14, 2015

I have been exploring how to automatically resolve a created issue as long as it meets a specific set of criteria. (ex. duplicate ticket is already open for the issue etc) This has been more complicated to accomplish than we originally thought, but we have been making progress up until now.  I am using a groovy script listener to process an Issue Created event, look up similar issues and then decide if the issue needs to be resolved as duplicate if there are similar issues.  Everything works up to the issue transition phase.

The logs tell me that "It seems that you have tried to perform a workflow operation (Resolve this issue) that is not valid for the current state of this issue (DESK-16). The likely cause is that somebody has changed the issue recently, please look at the issue history for details."

I have done my due diligence and validated that the issue I am referencing is in a status that allows this transition/step, but no matter what I do I cannot get the issue the transition immediately after it is created.  I played with timing by delaying the operation by a few seconds, but that doesn't fix it.  I also decided to attempt this operation outside of the issue creation event and it works perfectly fine.  By throwing an event in a workflow transition, not issue creation, the transition is performed as expected.  Code to perform the transition, taken out of context:

// Transition Issue						
def issueService = ComponentAccessor.getIssueService();
IssueInputParameters transitionParams = issueService.newIssueInputParameters();
//Construct the transition details
transitionParams.setResolutionId("3");    //Resolution "Duplicate"
transitionParams.setComment(comment);    //Comment to leave
transitionParams.setStatusId("4");    //Status of "Resolved"
transitionParams.setSkipScreenCheck(true);
int transitionId = 801;    //Action "Resolve this issue"
		
//Check the validity of the constructed transition
log.info("Checking Transition...");
TransitionValidationResult transitionValidation = issueService.validateTransition(appUser, triggeringIssue.getId(), transitionId, transitionParams);
if (transitionValidation.isValid()) {    //The transition is valid
		
	//Create a worker thread that waits for 2 seconds before performing the transition.
	ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
	Runnable runnableUpdate = new Runnable() {
		@Override
		public void run() {				
			IssueResult transitionResult = issueService.transition(appUser, transitionValidation);
			log.info("Issue ${triggeringIssue} Transitioned");
		}
	};
			
	worker.schedule(runnableUpdate, 2, TimeUnit.SECONDS);
	log.info("Worker Created");
		
} else {    //Transition is invalid
		
	ErrorCollection errors = transitionValidation.getErrorCollection();
	if (errors.hasAnyErrors()) {
		Collection<String> errorMessages = errors.getErrorMessages();
		for (Iterator<String> errorsIter = errorMessages.iterator(); errorsIter.hasNext();) {
				
			log.info(errorsIter.next());
		}
	}
	log.info("Current Issue Status: ${triggeringIssue.getStatusObject().getName()}");
			log.info("Triggering User Name: ${triggeringUser.getName()}");
			log.info("App User Name: ${appUser.getName()}");
			log.info("Transition is Invalid");
					
}

 

In an effort to try and make this work, I tried throwing a custom event instead of transitioning the issue from within the Issue Creation to try and separate the steps.  (Maybe the issue hasn't actually been created yet until the Issue Created event finishes)  I then created a new listener to process the new custom event and perform the transition from there.  The "Issue Created Listener" gets the issue created event, processes it, and throws my custom test event perfectly fine, but the new listener does not get this event.  I have opened up the "Test Event Listener" to listen for all event from all projects and then continue only if the eventID matches my custom event.  I can see it logging that it catches all events EXCEPT for the custom event I am throwing from the other listener.  When the custom "Test Event" is thrown from a workflow transition, the listener works as expected.  Code to throw custom event:

log.info("Constructing New Event...");
IssueEventManager issueEventMan = ComponentAccessor.getIssueEventManager();
//IssueEvent newEvent = new IssueEvent(triggeringIssue, event.getParams(), triggeringUser, 10000L);
IssueEventBundleFactory issueEventFactory = (IssueEventBundleFactory) ComponentAccessor.getComponent(IssueEventBundleFactory.class);
Comment eventComment = (Comment) ComponentAccessor.getComponent(Comment.class);
IssueEventBundle eventBundle =  issueEventFactory.createWorkflowEventBundle(10000L, triggeringIssue, appUser, eventComment, null, event.getParams(), true, "");
//IssueEventBundle eventBundle = issueEventFactory.wrapInBundle(newEvent);
				
//Create a worker thread that waits for 2 seconds before throwing the new event
ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
Runnable runnableUpdate = new Runnable() {
	@Override
	public void run() {
						
		//Fire new event
		log.info("New Event Thrown");
		issueEventMan.dispatchEvent(eventBundle);
	}
};
					
worker.schedule(runnableUpdate, 2, TimeUnit.SECONDS);
log.info("Worker Created");

 

Logs:

[com.opticalphusion.DuplicateIssueListener] Event: 1 fired for DESK-32 and caught by com.opticalphusion.DuplicateIssueListener
[com.opticalphusion.NewCustomerIssueListener] Event: 1 fired for DESK-32 and caught by com.opticalphusion.NewCustomerIssueListener
[com.opticalphusion.NewCustomerIssueListener] Checking JQuery Statement...
[com.opticalphusion.NewCustomerIssueListener] JQuery Statement is Valid
[com.opticalphusion.NewCustomerIssueListener] Looking for Similar Issues...
[com.opticalphusion.NewCustomerIssueListener] Similar Issues Found! DocumentIssueImpl[issueKey=DESK-5]
[com.opticalphusion.DuplicateIssueListener] Event: 6 fired for DESK-32 and caught by com.opticalphusion.DuplicateIssueListener
[com.opticalphusion.NewCustomerIssueListener] Linking Issues...
[com.opticalphusion.NewCustomerIssueListener] Constructing New Event...
[com.opticalphusion.NewCustomerIssueListener] Worker Created
[com.opticalphusion.NewCustomerIssueListener] New Event Thrown

So you can see that both listeners are processing the "Issue Created" event and the secondary listener is seeing the "Issue Linked" event, but event 10000 is not caught by anything.

Am I missing something in order to make my groovy listener "hear" the event I am throwing from another groovy listener?  Is there a way to log all events that are thrown so I can make sure the event is ACTUALLY happening?

Thank you very much!

3 answers

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

1 vote
JamieA
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 14, 2015

Doing it from the Create transition is super-tricky. Also, doing it in a thread is sub-optimal because the UI won't display the correct status.

I would try using the Fast-track built-in listener... or workflow function. Just try it without any condition. If that works, you could add your duplication detection to the Condition field. At least I'd like to see if that works, to rule out any other issues.

 

jldubz July 15, 2015

I did encounter the thread issue you are talking about when I was originally testing it outside of the Create transition, and I was able to get around it using a Runnable and scheduled worker thread. I originally investigated using the built-in listeners and scripts, but my condition to detect duplication is too complex and doesn't fit the expected use. The condition I need to use is dynamic and depended on the value of 3 custom text fields/drop downs in the issue that is being created. I need to perform a JQL search with a formula similar to the following: (pseudocode) def jqlSearch = 'project = DESK AND issuetype = "IT Help" AND status = "Waiting for support" AND "Serial Number" ~ ${triggeringIssue.serialnumber} AND "Location" ~ ${triggeringIssue.Location} AND "Device Type" ~ ${triggeringIssue.DeviceType}'; This will identify any issues that have the same location, device type, and serial number; as that is what will qualify the created issue as a duplicate. I do not believe I can perform such a query from within the condition section available to me for the built in scripts. Is this correct? The fast-track built-in listener is capable of transitioning the issue. I validated this, but it also does not receive the custom event that is thrown by my custom listener. If I can get my custom event (10000) to dispatch from my custom groovy listener then I think we can get this to work with either my other custom listener or the Fast-Track Built-In one. It just looks like the event isn't being thrown at all. In conclusion, IssueEventManager.dispatchEvent(eventBundle); is not working from within my groovy custom listener. Thank you.

1 vote
Darren Pegg
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 14, 2015

Looks very cool !!  Just a shot in the dark.. Is there any compulsory fields that need a value upon Resolving?

 

 

jldubz July 14, 2015

No. The only required field is the resolution code which I am setting. Otherwise, there are no required fields, no validators or conditions that require any fields nor any checks to make sure a field is set. To ensure that wasn't the problem I used transitionParams.setSkipScreenCheck(true); which is supposed to bypass any checks for required fields during a transition. (https://developer.atlassian.com/static/javadoc/jira/6.4.1/reference/com/atlassian/jira/issue/IssueInputParameters.html#setSkipScreenCheck(boolean)) To further validate that this is not the reason that the transition isn't allowed, the transition works perfectly fine outside of the initial Issue Created transition that occurs. It is almost as if the issue is in some sort of limbo state before it actually hits the first status in the workflow, but everything in the database says that it has finished the creation process. Thanks for the thought.

Darren Pegg
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 14, 2015

I guess its not an indexing issue either,.. @Nic Brough [Adaptavist] any thoughts buddy?

0 votes
jldubz July 14, 2015

FYI Taking the event dispatch method out of the Runnable and making it inline with the event listener changes nothing.

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