Need to create a Scriptrunner listener to set a component

Hi there,

I need to test the values of 3 custom fields, and based on those and the project name, set a component.

I'm trying to start out with the basics, and get a single custom field value + what project I'm in, and so I wrote:

package com.acme.scriptrunner.scripts
import com.atlassian.jira.bc.project.component.ProjectComponent
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.customfields.CustomFieldUtils
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.project.Project
import com.atlassian.jira.issue.Issue

Issue issue = issue
def project = issue.getProjectObject()
def projectComponentManager = ComponentAccessor.getProjectComponentManager()
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def categoryCf = customFieldManager.getCustomFieldObjectByName("PMScategory")
def component = projectComponentManager.findByComponentName(project.getId(), "Core framework")
if (issue.getProjectObject() == "PMS Connectivity" && categoryCf.value == "Core Framework") 
issue.setComponentObjects([component])
else
component = ComponentAccessor.getProjectComponentManager().findByComponentName(project.getId(),"Unknown")
Issue.setComponentObjects([component])

 

This does not work.

Obviously, my knowledge of Groovy syntax would not even cover the head of a pin....

Can you tell what I'm missing?

 

Thanks!

2 answers

Hi April,

For a jira7 instance you should try something like this

import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueInputParametersImpl

def issue = event.issue as Issue
def project = issue.getProjectObject()
def projectComponentManager = ComponentAccessor.getProjectComponentManager()
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def categoryCf = customFieldManager.getCustomFieldObjectByName("TextFieldA")

def component = (issue.getProjectObject().getName() == "JRA" && issue.getCustomFieldValue(categoryCf) == "testA") ?
projectComponentManager.findByComponentName(project.getId(), "Comp1") :
        projectComponentManager.findByComponentName(project.getId(),"Comp2")

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def issueService = ComponentAccessor.getIssueService()

def issueInputParams = new IssueInputParametersImpl().setComponentIds(component?.getId())
IssueService.UpdateValidationResult updateValidationResult =  issueService.validateUpdate(user, issue.id, issueInputParams)
issueService.update(user, updateValidationResult, EventDispatchOption.DO_NOT_DISPATCH, false) // update the issue but do not dispatch any event or send notification

regards

Thanos

Hi Thanos!

That definitely fixes updating the issue.

However, I am trying to use a set of cases, and for some reason, that does not work.

For example, I see in the log I have:

/secure/AjaxIssueAction.jspa [c.o.scriptrunner.runner.ScriptRunnerImpl] SF value is [Accounting, Batch Processing, null] for issue PMS-12735

My code should set the component "Batch Processing," but it is setting "Unknown," which should only be a last resort. In addition, although I see the component on the ticket, it does not appear in search results.

After restarting Jira, I now get this error:

  2016-08-05 17:50:17,781 Caesium-1-2 ERROR anonymous     [c.o.scriptrunner.runner.AbstractScriptListener] Script function failed on event: com.atlassian.jira.event.issue.IssueEvent, file: <inline script>

  java.lang.IllegalStateException: You can not update an issue with an invalid validation result.

      at com.atlassian.jira.bc.issue.DefaultIssueService.update(DefaultIssueService.java:304)

      at com.atlassian.jira.bc.issue.IssueService$update$0.call(Unknown Source)

      at com.acme.scriptrunner.scripts.Script5.run(Script5.groovy:78)

 

Do you see what I am doing wrong?

package com.acme.scriptrunner.scripts

import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueInputParametersImpl

def issue = event.issue as Issue
def project = issue.getProjectObject()
def projectComponentManager = ComponentAccessor.getProjectComponentManager()
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def casetypeCf = customFieldManager.getCustomFieldObjectByName("SFcasetype")
def subtypeCf = customFieldManager.getCustomFieldObjectByName("SFsubtype")
def categoryCf = customFieldManager.getCustomFieldObjectByName("SFcategory")
def component = issue.getComponents()
def casetypeCf1 = issue.getCustomFieldValue(casetypeCf)
def subtypeCf1 = issue.getCustomFieldValue(subtypeCf)
def categoryCf1 = issue.getCustomFieldValue(categoryCf)
def sf = [casetypeCf1,subtypeCf1,categoryCf1]

log.info "SF value is "+sf+" for issue "+issue

switch (sf) {
case "Accounting, Batch Processing, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Batch Processing")
case "Accounting, Corporate Actions, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Corporate Actions")
case "Accounting, Fees &amp; Financing Accruals, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Fees &amp; Financing Accruals")
case "Accounting, Financial Reporting, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Financial Reporting")
case "Accounting, Investor Management, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Investor Management")
case "Accounting, Pricing, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Pricing")
case "Accounting, Trade Import, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Trade Import")
case "Accounting, Trade Management, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Trade Management")
case "Compliance, Compliance, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Compliance")
case "Data Management &amp; Reporting, Reference Data, Security Master":
    component = projectComponentManager.findByComponentName(project.getId(), "Securities")
case "Data Management &amp; Reporting, Reference Data, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Standing Data")
case "Data Management &amp; Reporting, Reporting, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Reporting")
case "Data Management &amp; Reporting, Reporting, Performance Analysis":
    component = projectComponentManager.findByComponentName(project.getId(), "Performance Analysis")
case "Framework, Alert Monitor/Server, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Alert Monitor/Server")
case "Framework, Installers, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Installers")
case "Framework, Scheduler/Workflow Server, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Scheduler/Workflow Server")
case "Framework, System Configuration, null":
    component = projectComponentManager.findByComponentName(project.getId(), "System Configuration")
case "Modeling, Analytics, &amp; Risk, Risk, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Risk Analysis")
case "Operations, Reconcilliations, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Reconcilliation")
case "Order Execution (FIX), Routing &amp; Execution (FIX), ETM":
    component = projectComponentManager.findByComponentName(project.getId(), "ETM")
case "Order Management, null, null":
    component = projectComponentManager.findByComponentName(project.getId(), "Order Management")

default: component = projectComponentManager.findByComponentName(project.getId(), "Unknown")
}

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def issueService = ComponentAccessor.getIssueService()

def issueInputParams = new IssueInputParametersImpl().setComponentIds(component?.getId())
IssueService.UpdateValidationResult updateValidationResult =  issueService.validateUpdate(user, issue.id, issueInputParams)
// update the issue but do not dispatch any event or send notification
issueService.update(user, updateValidationResult, EventDispatchOption.DO_NOT_DISPATCH, false)

 

Thanks,

April

Hi April,

So I wrote a couple of comments in your code, hope that helps

import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueInputParametersImpl

def issue = event.issue as Issue
def project = issue.getProjectObject()
def projectComponentManager = ComponentAccessor.getProjectComponentManager()
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def casetypeCf = customFieldManager.getCustomFieldObjectByName("SFcasetype")
def subtypeCf = customFieldManager.getCustomFieldObjectByName("SFsubtype")

//def listOfComponents = issue.getComponents() - you do not this - just returns a list of the components
def casetypeCf1 = issue.getCustomFieldValue(casetypeCf)
def subtypeCf1 = issue.getCustomFieldValue(subtypeCf)

//in this part you are adding the values in an array, probably not what you want
def sfArray = [casetypeCf1,subtypeCf1] 
log.info "SF value is "+sfArray+" for issue "+issue

//this will create a string (by concat) with the values of the custom fields (supposing are single fields), probably this is what you want
def sfToString = "${casetypeCf1}, ${subtypeCf1}"
log.debug ("To string: ${sfToString}")

//this will create a string by iterating the sfArray and "joining" it's elements with a comma separator - if you want to use the array above (sfArray) then this is the string you have to use in your switch case comparisons 
def toStringJoin = sf.join(", ")
log.debug ("To string joined: ${toStringJoin}")

// use a string for the comparisons in your switch. Do not forget the break after each case :)
def component
switch (sfToString) {
    case "Accounting, Batch Processing":
        component = projectComponentManager.findByComponentName(project.getId(), "Batch Processing")
        break
    case "Accounting, Corporate Actions":
        component = projectComponentManager.findByComponentName(project.getId(), "Corporate Actions")
        break
    default:
        component = projectComponentManager.findByComponentName(project.getId(), "Unknown")
        break
}

def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def issueService = ComponentAccessor.getIssueService()

def issueInputParams = new IssueInputParametersImpl().setComponentIds(component?.getId() as Long)
IssueService.UpdateValidationResult updateValidationResult =  issueService.validateUpdate(user, issue.id, issueInputParams)
assert !updateValidationResult.getErrorCollection().hasAnyErrors()
// update the issue but do not dispatch any event or send notification
def updatedIssue = issueService.update(user, updateValidationResult, EventDispatchOption.DO_NOT_DISPATCH, false)

regards

Thanos

Hi Thanos,

You are awesome!

I did forget the breaks; noticed that after I hit save on the comment. I also had some other missing punctuation smile

The component is being set now, so just a little more tweaking..

Had to check if yet another custom field is null, and only perform all these operations if it has data. After 'def customFieldManager,' I just added:

def customer = customFieldManager.getCustomFieldObjectByName("CRM_CaseNo")

if (customer) { ...do the rest of the stuff }

else if (!customer)

break

Seems to be OK.

So I'm wondering, why is the array bad? Is that a performance thing? I had it in mind that if they added any more fields to this, I could evaluate by index number for some cases, but maybe that sucks?

Also, is there any way to remove a component?

If the users come  back and update their Salesforce case, I'd like to get rid of "Unknown" when I set the correct component.

Oddly, I see I can delete a whole issue, but not a way to get rid of the darned component.

Thanks,

April

Suggest an answer

Log in or Sign up to answer
Atlassian Community Anniversary

Happy Anniversary, Atlassian Community!

This community is celebrating its one-year anniversary and Atlassian co-founder Mike Cannon-Brookes has all the feels.

Read more
Community showcase
Bridget Sauer
Published Thursday in Marketplace Apps

Calling all developers––You're invited to Atlas Camp 2018

 Atlas Camp   is our developer event which will take place in Barcelona, Spain  from the 6th -7th of   September . This is a great opportunity to meet other developers and get n...

255 views 0 6
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