How to update Jira component without removing existing?

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
Accepted answer
Vasiliy Zverev Community Champion Feb 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"

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

 

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
Community showcase
Published Oct 31, 2018 in Marketplace Apps

Marketplace Spotlight: Zephyr

Hello Atlassian Community! Each month, we run a series of Spotlights to highlight Marketplace vendors and apps that our team thinks this Community would find valuable. In last month's Spotlig...

355 views 0 1
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