使用Scriptrunner HAPI API更新Jira组件时遇参数数量错误求助
问题场景
使用Scriptrunner的HAPI API操作Jira issue时触发以下错误:
Script function failed on Automation for Jira rule:IllegalArgumentException: wrong number of arguments
参考官方文档编写的简化代码:
Collection < ProjectComponent > updatedComponentList = issue.getComponents() updatedComponentList.removeAll(component) issue.set { setComponents(updatedComponentList) }
完整代码如下:
package SuperFeature import com.atlassian.jira.issue.Issue import org.apache.log4j.Logger import com.atlassian.jira.project.version.Version import com.atlassian.jira.bc.project.component.ProjectComponent import com.atlassian.jira.bc.project.component.ProjectComponentManager import com.atlassian.jira.security.JiraAuthenticationContext import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.label.LabelManager import SuperFeature.Configuration_SuperFeature import com.adaptavist.hapi.jira.issues.delegate.AbstractIssuesDelegate def log = Logger.getLogger('atlassian-jira.log') List < ProjectComponent > finalComponentList = new ArrayList < ProjectComponent > () int componentSize = issue.getComponents().size() int generatedIssuesCounter= 0 for (ProjectComponent component: issue.getComponents()) { String componentName = component.getName() def shortenedComponentName = componentName.substring(componentName.indexOf("-") + 1) def projectName = componentName.substring(0, componentName.indexOf("-")) if(Configuration_SuperFeature.projectNames.contains(projectName)){ def newIssueproject = ComponentAccessor.projectManager.getProjectObjByKey(projectName) List < ProjectComponent > newList = new ArrayList < > (newIssueproject.getComponents()); def found = newList.any { it.getName().equals(shortenedComponentName) } if (found) { finalComponentList.add(component) generatedIssuesCounter++ } } } createFeature(issue, finalComponentList) void createFeature(Issue issue, Collection < ProjectComponent > componentList) { JiraAuthenticationContext authenticationContext = ComponentAccessor.getJiraAuthenticationContext(); long issueLinkType = Configuration_SuperFeature.hierarchyIssueLinkType as long long sequence = Configuration_SuperFeature.sequence as long long myissueID = issue.getId() as long // the key of the project under which the version will get created final String projectKey = Configuration_SuperFeature.projectKey // the start date - optional final Date startDate = null // the release date - optional final Date releaseDate = null // a description for the new version - optional final String description = null // id of the version to schedule after the given version object - optional final Long scheduleAfterVersion = null // true if this is a released version final boolean released = false def project = ComponentAccessor.projectManager.getProjectObjByKey(projectKey) assert project: "Could not find project with key $projectKey" ProjectComponentManager projectComponentManager = ComponentAccessor.getProjectComponentManager() Collection < ProjectComponent > updatedComponentList = issue.getComponents() for (ProjectComponent component: componentList) { String componentName = component.getName() def shortenedComponentName = componentName.substring(componentName.indexOf("-") + 1) def projectName = componentName.substring(0, componentName.indexOf("-")) def newIssueproject = ComponentAccessor.projectManager.getProjectObjByKey(projectName) List < String > newIssueProjectVersionIDs = new ArrayList < String > () newIssueProjectVersionIDs = newIssueproject.getVersions().collect { it.getName() } def customField = ComponentAccessor.getCustomFieldManager().getCustomFieldObject(Configuration_SuperFeature.investmentAreaCustomField); def value = issue.getCustomFieldValue(customField); def matchedVersions = issue.getFixVersions().intersect(newIssueproject.getVersions(), Version.NAME_COMPARATOR) ProjectComponent newComponent = projectComponentManager.findByComponentName(newIssueproject.getId(), shortenedComponentName) def componentArray = new String[1] componentArray[0]=newComponent.getName() def versionCreator = ComponentAccessor.versionManager.&createVersion.rcurry(startDate, releaseDate, description, newIssueproject.id, scheduleAfterVersion, released) def mynewVersions = issue.fixVersions.intersect(newIssueproject.versions, Version.NAME_COMPARATOR).collect { versionCreator it.name + '-Inbox' } // long newIssueCreatedID = newissue.getId() as long // def labelManager = ComponentAccessor.getComponent(LabelManager) // labelManager.addLabel(authenticationContext.getLoggedInUser(), newIssueCreatedID, "SF-Child", false) // updatedComponentList.removeAll(component) // projectComponentManager.updateIssueProjectComponents(issue, updatedComponentList) updatedComponentList.removeAll(component) // issue.setComponents(updatedComponentList) // issue.update { // setComponents(updatedComponentList) // } issue.set { setComponents(updatedComponentList) } Issue newissue = Issues.create(projectName, 'Feature') { setSummary("["+shortenedComponentName+"] "+issue.getSummary()) setDescription("This feature has been generated as child of a super feature. Please use this text area to add child feature specific information.") setReporter(authenticationContext.getLoggedInUser()) setCustomFieldValue(customField.getFieldName(), value) setFixVersions(mynewVersions as String[]) setComponents (componentArray as String[]) setLabels(["SF-Child"] as String []) } newissue.link(Configuration_SuperFeature.hierarchyIssueLinkType, issue) } }
错误原因分析
removeAll方法参数类型不匹配:
代码中updatedComponentList.removeAll(component)一行,component是单个ProjectComponent对象,但Collection.removeAll()方法要求参数是Collection类型(即一组元素),传入单个对象会触发参数数量/类型不匹配的IllegalArgumentException。原生Issue对象误用HAPI的
set方法:
原生Jira的Issue对象并不支持issue.set { ... }这种HAPI风格的语法,这是HAPI委托对象的专属用法,直接调用会导致动态方法调用错误。不可修改集合的操作错误:
issue.getComponents()返回的是Jira内部的不可修改集合,直接调用remove或removeAll会触发UnsupportedOperationException,需要先转为可修改的集合类型。
修正方案
1. 修正集合移除操作
将updatedComponentList.removeAll(component)改为updatedComponentList.remove(component),因为要移除单个组件,使用Collection.remove()方法即可;同时初始化集合时转为可修改的ArrayList:
// 转为可修改的ArrayList Collection<ProjectComponent> updatedComponentList = new ArrayList<>(issue.getComponents()) // 移除单个组件 updatedComponentList.remove(component)
2. 正确使用HAPI更新issue
替换错误的issue.set { ... }语法,使用HAPI的Issues.update()方法来更新issue:
Issues.update(issue.key) { setComponents(updatedComponentList) }
完整修正后的关键代码片段
// 初始化可修改的组件集合 Collection<ProjectComponent> updatedComponentList = new ArrayList<>(issue.getComponents()) for (ProjectComponent component: componentList) { // ... 其他代码 ... // 移除单个组件 updatedComponentList.remove(component) // 使用HAPI正确更新issue组件 Issues.update(issue.key) { setComponents(updatedComponentList) } // ... 创建新issue的代码 ... }
内容的提问来源于stack exchange,提问作者منى

