Groovy custom listener to update components field

Anand Unadkat
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.
October 16, 2013
package com.custom
 
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.CustomFieldManager 
import com.atlassian.jira.project.Project
import com.atlassian.jira.bc.project.component.ProjectComponent
import com.atlassian.jira.event.issue.AbstractIssueEventListener
import com.atlassian.jira.event.issue.IssueEvent
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.crowd.embedded.api.User
import com.atlassian.event.api.EventListener
import com.atlassian.jira.util.ImportUtils
import org.apache.log4j.Category
 
class UpdateFieldComponent extends AbstractIssueEventListener {
    Category log = Category.getInstance(UpdateFieldComponent.class)
 
    UpdateFieldComponent () {
        log.setLevel(org.apache.log4j.Level.DEBUG)
    }
 
    @EventListener
    void workflowUpdated(IssueEvent event) {
        log.debug "Event: ${event.getEventTypeId()} fired for ${event.issue} and caught by UpdateFieldComponent" 
        
        CustomFieldManager customFieldManager = componentManager.getCustomFieldManager();
        
        if(issue.getCustomFieldObjectByName("Type of Request").contains("G1 Block")){
        Project project = issue.getProjectObject()
        ProjectComponent component = ComponentAccessor.getProjectComponentManager().findByComponentName(project.getId(), "G1 Block")
        issue.setComponentObjects([component])
        } else {
        Project project = issue.getProjectObject()
        ProjectComponent component = ComponentAccessor.getProjectComponentManager().findByComponentName(project.getId(), "1 - Inbox")
        issue.setComponentObjects([component])
        }
       
    }
 
}

Hi,

I have created a Groovy custom listener which will update the components field accoring to a custom field. I have been able to add it to script runner but it is not updating the component field. The event i have selected it to fire is Issue update.

Thanks for your help!

9 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

0 votes
Answer accepted
Anand Unadkat
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.
October 27, 2013

Hi,

I have finally got it to work. Here is the code if other people viewing need help:

package com.custom

import com.atlassian.jira.event.issue.AbstractIssueEventListener
import com.atlassian.jira.event.issue.IssueEvent
import org.apache.log4j.Category
import com.atlassian.jira.bc.project.component.ProjectComponent
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.IssueInputParameters
import com.atlassian.jira.security.JiraAuthenticationContext
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.user.util.UserManager
import com.atlassian.jira.issue.changehistory.ChangeHistoryManager
import com.atlassian.jira.issue.changehistory.ChangeHistoryItem
import com.atlassian.jira.bc.project.component.ProjectComponentManager
import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.project.Project
import com.atlassian.jira.user.util.UserManager
import com.atlassian.jira.bc.project.component.ProjectComponentImpl
 
class UpdateFieldComponent extends AbstractIssueEventListener {
    Category log = Category.getInstance(UpdateFieldComponent.class)
 
    UpdateFieldComponent () {
        log.setLevel(org.apache.log4j.Level.DEBUG)
    }
 
    @Override
    void issueUpdated(IssueEvent event) {
    log.debug "Event: ${event.getEventTypeId()} fired for ${event.issue} and caught by UpdateFieldComponent"
     def cf = ComponentAccessor.customFieldManager.getCustomFieldObjectByName("Type of Request")
     def val = event.issue.getCustomFieldValue(cf).value
        if(val == "cf value"){
     MutableIssue myIssue = event.issue
     Project project = event.issue.getProjectObject()
     ProjectComponent component = ComponentAccessor.getProjectComponentManager().findByComponentName(project.getId(), "component name")
     IssueManager issueManager = ComponentAccessor.getIssueManager()
     UserManager userManager = ComponentAccessor.getUserManager()
     myIssue.setComponentObjects([component])
     issueManager.updateIssue(userManager.getUser("user"), myIssue, EventDispatchOption.ISSUE_UPDATED, false)
     log.debug("--- add component. ---")
        } else {
     MutableIssue myIssue = event.issue
     Project project = event.issue.getProjectObject()
     ProjectComponent component = ComponentAccessor.getProjectComponentManager().findByComponentName(project.getId(), "component name")
     IssueManager issueManager = ComponentAccessor.getIssueManager()
     UserManager userManager = ComponentAccessor.getUserManager()
     myIssue.setComponentObjects([component])
     issueManager.updateIssue(userManager.getUser("user"), myIssue, EventDispatchOption.ISSUE_UPDATED, false)
     log.debug("--- add component. ---")
        }
    log.debug("--- End of method. ---")
           
    }
}

Max Paw December 1, 2015

Can't get it. Everything after if is the same thing that after else what is the point of that if?

0 votes
A October 22, 2013

Hi Tanner,

So I finally got it to display errors. I am using similar code to yours to update the components field. The thing is when an Issue is created, the components field is set already. What I want to do is after the issue is created and the user chooses a CustomField, I want it to update the existing Components. So the code that I am using is:

ProjectComponent projectComponent = ComponentAccessor.getProjectComponentManager().findByComponentName (event.issue.getProjectObject().getId(), "Blocks/Limits")

// set up for update
MutableIssue myIssue = event.issue
IssueManager issueManager = ComponentAccessor.getIssueManager()
UserManager userManager = ComponentAccessor.getUserManager()
Collection <ProjectComponent> comps = []
comps.add(projectComponent)
// update
myIssue.setComponentObjects(comps)
issueManager.updateIssue(myIssue.getAssignee(), myIssue, EventDispatchOption.ISSUE_UPDATED, true)
And the error it get is:
java.lang.RuntimeException: No such property: comps for class: com.custom.UpdateFieldComponent
Tanner Wortham
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.
October 22, 2013

i'm not quite sure. it doesn't like your collection for some reason. you'll have to track down that problem on your own, but if you're interested in not losing the rest of the components, simply change your comps instantiation to be the currently component list instead of the empty set.

0 votes
Tanner Wortham
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.
October 21, 2013

Am I supposed to look at any other logs?

your standard log is all you'll need. you know you're in the right place when you see a bunch of entries about the operation of JIRA.

Also the issue that I am firing it Issue Update. It is not set in the workflow, is that why it may not be working?

not according to your code above. your code shows that it fires of workflow updated, not issue updated. void issueUpdated (IssueEvent event) is the method used for updating an issue. as far as where you configure it, you should be configuring it in the admin module under Script Runner and finally by clicking Script Listeners.


0 votes
Anand Unadkat
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.
October 21, 2013

Hi Tanner,

Thanks for staying with me. I am looking at the atlassian logs. Am I supposed to look at any other logs? Also the issue that I am firing it Issue Update. It is not set in the workflow, is that why it may not be working? So the issue is in state "New", I update the issue by setting a custom field hence choosing "Issue updated" and it doesn't work.

Thanks for your help till now.

0 votes
Anand Unadkat
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.
October 21, 2013

Hi Tanner,

I added a few more log.debug, still nothing in the log. Do you have any other solutions that I can use? Thanks a lot for your help! May be try my script in your local instance and change the components according to your setting

package com.custom

import com.atlassian.jira.event.issue.AbstractIssueEventListener
import com.atlassian.jira.event.issue.IssueEvent
import org.apache.log4j.Category
import com.atlassian.jira.bc.project.component.ProjectComponent
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.IssueInputParameters
import com.atlassian.jira.security.JiraAuthenticationContext
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.user.util.UserManager
import com.atlassian.jira.issue.changehistory.ChangeHistoryManager
import com.atlassian.jira.issue.changehistory.ChangeHistoryItem
import com.atlassian.jira.bc.project.component.ProjectComponentManager
import com.atlassian.jira.bc.issue.IssueService
 
class UpdateFieldComponent extends AbstractIssueEventListener {
    Category log = Category.getInstance(UpdateFieldComponent.class)
 
    UpdateFieldComponent () {
        log.setLevel(org.apache.log4j.Level.DEBUG)
    }
 
    @Override
    void workflowUpdated(IssueEvent event) {
    log.debug "Event: ${event.getEventTypeId()} fired for ${event.issue} and caught by UpdateFieldComponent" 
        
     cf = ComponentAccessor.customFieldManager.getCustomFieldObjectByName("Type of Request")
     val = issue.getCustomFieldValue(cf)
        
        if(val.contains("G1 Block")){
    //setup for update
     ProjectComponent component = ComponentAccessor.getProjectComponentManager().findByComponentName(project.getId(), "G1 Block")
     MutableIssue myIssue = event.issue
     IssueManager issueManager = ComponentAccessor.getIssueManager()

    
    //update issue
        myIssue.setComponentObjects([component])
     issueManager.updateIssue(myIssue, EventDispatchOption.ISSUE_UPDATED, true)
        } else {
    //setup for update
     ProjectComponent component = ComponentAccessor.getProjectComponentManager().findByComponentName(project.getId(), "G1 Block")
     MutableIssue myIssue = event.issue
     IssueManager issueManager = ComponentAccessor.getIssueManager()
    
    //update issue
     myIssue.setComponentObjects([component])
     issueManager.updateIssue(myIssue, EventDispatchOption.ISSUE_UPDATED, true)
        }
    log.debug("--- Made it to the end of create method. ---")
            
    }
 
}

? I can understand if you can't.

Tanner Wortham
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.
October 21, 2013

since you're not getting any log entries even with those extra log entries, i can only imagine it's one of the two scenerios i pointed out before.

  • the script above is a listener. maybe it's not firing because you're not triggering it with the right event.
  • you're looking at the wrong log. put some more log.debug lines in your code that aren't in conditionals to verify.

that's the best i can do for you. i hope that helps.

0 votes
A October 16, 2013

There is no error, nothing logged in the logs either, uploading it to script runner works fine too. Is my script correct?

Thanks a lot!

Tanner Wortham
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.
October 16, 2013

hard to say. a few things come to mind:

  • the script above is a listener. maybe it's not firing because you're not triggering it with the right event.
  • you're looking at the wrong log. put some more log.debug lines in your code that aren't in conditionals to verify.
  • without any errors or logs entries, you're bumping around in the dark.
0 votes
A October 16, 2013
package com.custom


import com.atlassian.jira.event.issue.AbstractIssueEventListener
import com.atlassian.jira.event.issue.IssueEvent
import org.apache.log4j.Category
import com.atlassian.jira.bc.project.component.ProjectComponent
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.IssueInputParameters
import com.atlassian.jira.security.JiraAuthenticationContext
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.user.util.UserManager
import com.atlassian.jira.issue.changehistory.ChangeHistoryManager
import com.atlassian.jira.issue.changehistory.ChangeHistoryItem
import com.atlassian.jira.bc.project.component.ProjectComponentManager
import com.atlassian.jira.bc.issue.IssueService
 
class UpdateFieldComponent extends AbstractIssueEventListener {
    Category log = Category.getInstance(UpdateFieldComponent.class)
 
    UpdateFieldComponent () {
        log.setLevel(org.apache.log4j.Level.DEBUG)
    }
 
    @Override
    void workflowUpdated(IssueEvent event) {
        log.debug "Event: ${event.getEventTypeId()} fired for ${event.issue} and caught by UpdateFieldComponent" 
        
     cf = ComponentAccessor.customFieldManager.getCustomFieldObjectByName("Type of Request")
     val = issue.getCustomFieldValue(cf)
        
        if(val.contains("G1 Block")){
    //setup for update
        ProjectComponent component = ComponentAccessor.getProjectComponentManager().findByComponentName(project.getId(), "G1 Block")
     MutableIssue myIssue = event.issue
     IssueManager issueManager = ComponentAccessor.getIssueManager()


    
    //update issue
        myIssue.setComponentObjects([component])
     issueManager.updateIssue(myIssue, EventDispatchOption.ISSUE_UPDATED, true)
        } else {
    //setup for update
        ProjectComponent component = ComponentAccessor.getProjectComponentManager().findByComponentName(project.getId(), "G1 Block")
     MutableIssue myIssue = event.issue
     IssueManager issueManager = ComponentAccessor.getIssueManager()
    
    //update issue
        myIssue.setComponentObjects([component])
     issueManager.updateIssue(myIssue, EventDispatchOption.ISSUE_UPDATED, true)
        }
    log.debug("--- Made it to the end of create method. ---")
            
    }
 
}

Hi Tanner,

This is my script now and it is still not working.

Tanner Wortham
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.
October 16, 2013

what's the error?

0 votes
Tanner Wortham
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.
October 16, 2013

here's my own code to update the component by setting it as the union of its children. as i scan over your code, two things stick out at me:

  1. it looks like you're not using MutableIssue to set your new component.
  2. you're not finalizing the set with IssueManager as you see i did on line 124.
package com.custom

import com.atlassian.jira.event.issue.AbstractIssueEventListener
import com.atlassian.jira.event.issue.IssueEvent
import org.apache.log4j.Category
import com.atlassian.jira.bc.project.component.ProjectComponent
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.IssueInputParameters
import com.atlassian.jira.security.JiraAuthenticationContext
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.user.util.UserManager
import com.atlassian.jira.issue.changehistory.ChangeHistoryManager
import com.atlassian.jira.issue.changehistory.ChangeHistoryItem
import com.atlassian.jira.bc.project.component.ProjectComponentManager
import com.atlassian.jira.bc.issue.IssueService

class ComponentListener extends AbstractIssueEventListener {
    Category log = Category.getInstance(ComponentListener.class)
 
    @Override
    void issueCreated (IssueEvent event) {
    	log.setLevel(org.apache.log4j.Level.WARN)

	if (event.issue.isSubTask()) { makeUpdate (event, "add") }
	else {  
		// find correct Other component
		ProjectComponent projectComponent = ComponentAccessor.getProjectComponentManager().findByComponentName (event.issue.getProjectObject().getId(), "Other")

		// set up for update
		MutableIssue myIssue = event.issue
		IssueManager issueManager = ComponentAccessor.getIssueManager()
		UserManager userManager = ComponentAccessor.getUserManager()
		Collection &lt;ProjectComponent&gt; comps = []
		comps.add(projectComponent)
		
		// update
		myIssue.setComponentObjects(comps)
		issueManager.updateIssue(userManager.getUser("automation"), myIssue, EventDispatchOption.ISSUE_UPDATED, false)

	}

	log.debug("--- Made it to the end of create method. ---")

    }    
    
    @Override
    void issueUpdated (IssueEvent event) {

	// understand the update made to the issue
	ChangeHistoryManager changeHistoryManager = ComponentAccessor.getChangeHistoryManager()
	List &lt;ChangeHistoryItem&gt; changeHistoryItems = changeHistoryManager.getAllChangeItems(event.issue)
	ChangeHistoryItem lastItem = changeHistoryItems.get(changeHistoryItems.size()-1)
	log.debug ("issue: ${event.issue} || last item: ${lastItem.getField()}")

	// going to make the change if it was a component/parent change and not done by automation
	if (!lastItem.getUser().equals("automation")) {
		if (lastItem.getField().equals("Component")) {
			makeUpdate(event, "update")
		} else if (lastItem.getField().equals("Parent Issue")) {
			makeUpdate(event, "update")
			makeUpdate(event, "parent")  // need 2nd update for previous parent
		}
	} else { log.debug ("issue: ${event.issue} || We ended up in this useless stub.") }

	log.debug ("--- Made it to the end of the update method. ---")

    }
    
    @Override
    void issueDeleted (IssueEvent event) {

	if (event.issue.isSubTask()) { 
		makeUpdate(event, "delete")
	} else { log.debug ("We ended up in this useless stub.") }
	log.debug("--- Made it to the end of delete method. ---")    
    }

    // this method does all the heavy lifting 
    void makeUpdate (IssueEvent event, String type) {
	MutableIssue myIssue
	IssueManager issueManager = ComponentAccessor.getIssueManager()
	UserManager userManager = ComponentAccessor.getUserManager()
	
	if (event.issue.isSubTask()) { 
		if (type.equals("parent")) {
			ChangeHistoryManager changeHistoryManager = ComponentAccessor.getChangeHistoryManager()
			List &lt;ChangeHistoryItem&gt; changeHistoryItems = changeHistoryManager.getAllChangeItems(event.issue)
			ChangeHistoryItem lastItem = changeHistoryItems.get(changeHistoryItems.size()-1)
			myIssue = issueManager.getIssueObject(lastItem.getFromValue())
		} else {
			myIssue = event.issue.getParentObject() 
		}
	} else { 
		myIssue = event.issue 
	}
	Collection &lt;Issue&gt; myTasks = myIssue.getSubTaskObjects()
	Collection &lt;ProjectComponent&gt; comps = []

	// make sure we have children
	if (myTasks.size() &gt; 0) {
		myTasks.each { t -&gt; 
			comps = comps.plus(t.getComponentObjects()) 
		}
	
	// no children but keep in mind that new task isn't yet a child
	} else if (!type.equals("add")) {
		ProjectComponent projectComponent = ComponentAccessor.getProjectComponentManager().findByComponentName (myIssue.getProjectObject().getId(), "Other")
		comps = comps.plus(projectComponent)	
	}

	// add requires an additional check since the new task is not yet a child
	if (type.equals("add")) { comps = comps.plus(event.issue.getComponentObjects()) }

	// prepare for update
	comps.unique()
	log.debug ("comps: ${comps}")

	// update
	myIssue.setComponentObjects(comps)	
	issueManager.updateIssue(userManager.getUser("automation"), myIssue, EventDispatchOption.ISSUE_UPDATED, false)
    }	
}

0 votes
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.
October 16, 2013

you need to try something like this

package com.custom  
import com.atlassian.jira.component.ComponentAccessor 
import com.atlassian.jira.project.Project
import com.atlassian.jira.issue.customfields.option.Option;
import com.atlassian.jira.bc.project.component.ProjectComponent
import com.atlassian.jira.event.issue.AbstractIssueEventListener
import com.atlassian.jira.event.issue.IssueEvent
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.crowd.embedded.api.User
import com.atlassian.event.api.EventListener
import com.atlassian.jira.util.ImportUtils
import org.apache.log4j.Category
  
class UpdateFieldComponent extends AbstractIssueEventListener {
    Category log = Category.getInstance(UpdateFieldComponent.class)
  
    UpdateFieldComponent () {
        log.setLevel(org.apache.log4j.Level.DEBUG)
    }
  
    @EventListener
    void workflowUpdated(IssueEvent event) {
        log.debug "Event: ${event.getEventTypeId()} fired for ${event.issue} and caught by UpdateFieldComponent"
         
        CustomFieldManager cfm = ComponentAccessor.getCustomFieldManager();
         def cf=cfm.getCustomFieldObjectByName("Type of Request")		
		 Option cfValue=(Option)issue.getCustomFieldValue(cf);
		if (cfValue.getValue().equals("G1 Block")) {       
			Project project = issue.getProjectObject()
			ProjectComponent component = ComponentAccessor.getProjectComponentManager().findByComponentName(project.getId(), "G1 Block")
			if(component!=null)
				issue.setComponentObjects(Arrays.asList(component))
        } else {
			Project project = issue.getProjectObject()
			ProjectComponent component = ComponentAccessor.getProjectComponentManager().findByComponentName(project.getId(), "1 - Inbox")
			if(component!=null)
				issue.setComponentObjects(Arrays.asList(component))
        }
        
    }
  
}


Anand Unadkat
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.
October 16, 2013

Hi Rambanam,

Thanks for getting back to me. I tried your script and I can upload it to script runner without any problems. But when I create a ticket, then "Update" it with choosing "Type of Request", it doesn't update the components field :(

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