How to update Jira component without removing existing?

April February 24, 2017

Hi there,

I have a script to read a selection of custom fields and set a component, but I can only set one per issue with it.

I need a way to read what is there, and add my new one, but have not figured out how to do this.

The current script looks like this:

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
import org.apache.log4j.Level
import org.apache.log4j.Logger
Logger.getLogger("com.onresolve.scriptrunner").setLevel(Level.INFO)
def issue = event.issue as Issue
def project = issue.getProjectObject()
def projectComponentManager = ComponentAccessor.getProjectComponentManager()
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def subtypeCf = customFieldManager.getCustomFieldObjectByName("SFsubtype")
def subtypeCf1 = issue.getCustomFieldValue(subtypeCf)
def casetypeCf = customFieldManager.getCustomFieldObjectByName("SFcasetype")
def categoryCf = customFieldManager.getCustomFieldObjectByName("SFcategory")
def casetypeCf1 = issue.getCustomFieldValue(casetypeCf)
def categoryCf1 = issue.getCustomFieldValue(categoryCf)
def sf = issue.getCustomFieldValue(subtypeCf)
def component
if (casetypeCf1) {
log.info "SF value is "+sf+" for issue "+issue

//check for the new Salesforce values
switch (sf) {
case sf = "Compliance":
            component = projectComponentManager.findByComponentName(project.getId(), "Compliance")
            log.info "SF value is component "+component+" for issue "+issue
            break
case sf = "Corporate Actions":
            component = projectComponentManager.findByComponentName(project.getId(), "Corporate Actions")
            log.info "SF value is component "+component+" for issue "+issue
            break
			
default: component = projectComponentManager.findByComponentName(project.getId(), "Unknown")
            log.info "SF value is component "+component+" for issue "+issue
}

if (component == projectComponentManager.findByComponentName(project.getId(), "Unknown"))
{def sfToString = "${categoryCf1}, ${casetypeCf1}, ${subtypeCf1}"

//if that fails, check for historical values
switch (sfToString) {
case sfToString = "null, Accounting, Corporate Actions":
	component = projectComponentManager.findByComponentName(project.getId(), "Corporate Actions")
	break
case sfToString = "null, Compliance, Compliance":
	component = projectComponentManager.findByComponentName(project.getId(), "Compliance")
	break
default: component = projectComponentManager.findByComponentName(project.getId(), "Unknown")
}
}

//now set the component
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)
}

//else do nothing
else
log.info "SF value is null for "+ issue.key +"; nothing to do"

 

Poking around here, I did come across a clue:

Collection components = issue.getComponents();
   Iterator componentIterator = components.iterator();
     while (componentIterator.hasNext()) {
          GenericValue component = (GenericValue)componentIterator.next();
          String componentName = component.getString("name");
          String componentId = component.getString("id"); }

 

But, GenericValue appears to be deprecated.

How do I get this list? Do I want to find IDs or names? Then would I iterate through the results to add my new component as well as the existing, or is there some easier way to get this, like 

components = components + newComponent

Thanks!

1 answer

1 accepted

1 vote
Answer accepted
Vasiliy Zverev
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.
February 26, 2017

See my comments. I also refactored your code

package com.acme.scriptrunner.scripts

import com.atlassian.jira.bc.project.component.ProjectComponent
import com.atlassian.jira.bc.project.component.ProjectComponentManager
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.UpdateIssueRequest
import org.apache.log4j.Level
import org.apache.log4j.Logger

Logger.getLogger("com.onresolve.scriptrunner").setLevel(Level.INFO)
MutableIssue issue = event.issue as MutableIssue; //mutable issue for update 
long projectId = issue.getProjectObject().getId()
ProjectComponentManager projectComponentManager = ComponentAccessor.getProjectComponentManager()
CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager()

def subtypeCf1 = issue.getCustomFieldValue(customFieldManager.getCustomFieldObjectByName("SFsubtype"))
def casetypeCf1 = issue.getCustomFieldValue(customFieldManager.getCustomFieldObjectByName("SFcasetype"))
def categoryCf1 = issue.getCustomFieldValue(customFieldManager.getCustomFieldObjectByName("SFcategory"))
def sf = issue.getCustomFieldValue(customFieldManager.getCustomFieldObjectByName("SFsubtype")) //dublicate for subtypeCf1
ProjectComponent component;

if (casetypeCf1) {
    log.info "SF value is "+sf+" for issue "+issue

//check for the new Salesforce values
    switch (sf) {
        case "Compliance":
            component = projectComponentManager.findByComponentName(projectId, "Compliance")
            log.info "SF value is component "+component+" for issue "+issue
            break;
        case "Corporate Actions":
            component = projectComponentManager.findByComponentName(projectId, "Corporate Actions")
            log.info "SF value is component "+component+" for issue "+issue
            break

        default: component = projectComponentManager.findByComponentName(projectId, "Unknown")
            log.info "SF value is component "+component+" for issue "+issue
    }

    if (component == projectComponentManager.findByComponentName(projectId, "Unknown"))
    {def sfToString = "${categoryCf1}, ${casetypeCf1}, ${subtypeCf1}"

//if that fails, check for historical values
        switch (sfToString) {
            case "null, Accounting, Corporate Actions":
                component = projectComponentManager.findByComponentName(projectId, "Corporate Actions")
                break
            case "null, Compliance, Compliance":
                component = projectComponentManager.findByComponentName(projectId, "Compliance")
                break
            default: component = projectComponentManager.findByComponentName(projectId, "Unknown")
        }
    }
    
    //add component to component list and update issue
    Collection<ProjectComponent> issueComponents = new ArrayList<>();    
    if(!issueComponents.contains(component)){
        issueComponents.add(component)
        issue.setComponentObjects(issueComponents)
        ComponentAccessor.getIssueManager().updateIssue(
                ComponentAccessor.getJiraAuthenticationContext().getUser()
                , issue
                ,UpdateIssueRequest.builder().eventDispatchOption(EventDispatchOption.ISSUE_UPDATED).sendMail(false).build()
        )
    }   
 
}

//else do nothing
else
    log.info "SF value is null for "+ issue.key +"; nothing to do"
April February 26, 2017

Thanks so much!

I just tried it out. Unfortunately, it still forces only one component.

I think we have to figure out how to iterate through the existing to add to the array, but I still haven't figured out what to say instead of the "GenericValue" in the only example I found.

Collection components = issue.getComponents();
   Iterator componentIterator = components.iterator();
     while (componentIterator.hasNext()) {
          GenericValue component = (GenericValue)componentIterator.next();

Thanks again smile

 

April February 26, 2017

Got it!

Don't need that darned GenericValue smile

//add component to component list and update issue
    Collection issueComponents = issue.getComponents()
   if(!issueComponents.contains(component)){
        issueComponents.add(component)
        log.info "IssueComponents AFTER value is "+issueComponents
       issue.setComponent(issueComponents)
        ComponentAccessor.getIssueManager().updateIssue(
                ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
                , issue
                ,UpdateIssueRequest.builder().eventDispatchOption(EventDispatchOption.ISSUE_UPDATED).sendMail(false).build()
        )
    }

(Updated)

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events