You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jira自动化规则出现Null Pointer Exception:如何定位异常代码行?

定位Jira自动化脚本空指针异常的方法

一、通用定位手段

  • 加细粒度日志:在可能触发空指针的代码行前后,打印变量状态,确认哪个对象为null。
  • 捕获异常打堆栈:用try-catch包裹可疑代码块,打印完整异常堆栈,Jira日志里会显示具体行号。
  • 分段注释排查:逐步注释代码块,缩小范围找到触发异常的逻辑段。

二、你的脚本排查重点

先贴出你的脚本代码:

package SuperFeature

import com.atlassian.jira.bc.project.component.ProjectComponent
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.Issue
import org.apache.log4j.Logger
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.util.ImportUtils
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.index.IssueIndexManager
import com.atlassian.jira.issue.index.IssueIndexingService
import com.atlassian.jira.event.issue.IssueEventManager
import com.atlassian.jira.event.issue.IssueEvent
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.link.IssueLinkManager
import com.atlassian.jira.issue.link.IssueLinkTypeManager
import com.atlassian.jira.event.issue.link.IssueLinkCreatedEvent
import com.atlassian.jira.event.issue.link.IssueLinkDeletedEvent
import org.apache.log4j.Level
import org.apache.log4j.Logger
import com.atlassian.jira.issue.link.IssueLinkType

def log = Logger.getLogger('atlassian-jira.log')

log.warn("MOUNA: ")
log.warn("MOUNA COMPONENT NUMBERS : "+ issue.getComponents().size())

List<String> componentList = new ArrayList<String>()

def authenticationContext = ComponentAccessor.jiraAuthenticationContext

if (issue.getComponents().size()==0){
    log.warn("MOUNA CAMELIA COMPONENTS")
    issue.update {
        String text= "Issue does not have any components\n"
        setCustomFieldValue('Execution Summary', text)
    }
}else if(issue.getFixVersions().size()==0){
    log.warn("MOUNA CAMELIA VERSIONS")
    issue.update {
        String text= "Issue does not have any fix versions\n"
        setCustomFieldValue('Execution Summary', text)
    }
}else{
    log.warn("MOUNA CAMELIA ELSE")
    int componentSize=issue.getComponents().size()
    for(ProjectComponent component : issue.getComponents()) {
        componentList.add(component.getName())
    }
    issue.update {
        String text= "The super feature "+issue+" will be split into "+componentSize+
        " features, one for each component:\n"
        for(String component: componentList){
            text = text +"-"+ component+"\n"; 
        }
        setCustomFieldValue('Execution Summary', text)
    }
    // Issue issue
    def issueManager = ComponentAccessor.issueManager
    def issueFactory = ComponentAccessor.issueFactory
    def subTaskManager = ComponentAccessor.subTaskManager
    def issueLinkManager = ComponentAccessor.issueLinkManager
    def userManager = ComponentAccessor.userManager
    MutableIssue newIssue= ComponentAccessor.issueFactory.issue
    newIssue.setProjectObject(issue.getProjectObject())
    newIssue.setSummary("MOUNA CAMELIA")
    newIssue.issueTypeId= 10070
    int issueLinkType= 10070
    int sequence =1
    newIssue.setAssignee(userManager.getUserByName("mouh"))
    newIssue.setDescription(issue.getDescription())
    for(String component: componentList){
        log.warn("MOUNA CAMELIA component"+ component +" NEW ISSUE "+ newIssue)
        log.warn("MOUNA CAMELIA Component "+ component+" issue.getId() "+ issue.getId()+" issueLinkType "+issueLinkType+" sequence "+ sequence+" auth "+authenticationContext.getLoggedInUser())                    
        issueLinkManager.createIssueLink(issue.getId(), newIssue.getIssueTypeId(), issueLinkType, sequence, authenticationContext.getLoggedInUser())
    }
}

可能触发空指针的关键点

  1. issue对象为空:如果自动化规则触发时issue未正确传入,调用issue.getComponents()等所有方法都会抛异常。可以在脚本开头加日志:log.warn("Issue是否为空: " + (issue == null))。
  2. 登录用户为空:authenticationContext.getLoggedInUser()如果返回null,后续createIssueLink传入null用户会触发异常。加日志:log.warn("当前登录用户: " + authenticationContext.getLoggedInUser())。
  3. 用户"mouh"不存在:userManager.getUserByName("mouh")找不到用户时返回null,设置给newIssue.setAssignee()可能触发异常。加日志:log.warn("用户mouh是否存在: " + (userManager.getUserByName("mouh") != null))。
  4. newIssue初始化失败:ComponentAccessor.issueFactory.issue如果未正确初始化,newIssue为null,后续调用setProjectObject()等方法会抛异常。加日志:log.warn("新Issue对象是否为空: " + (newIssue == null))。
  5. createIssueLink参数错误:这里是核心问题——createIssueLink的第二个参数需要目标issue的ID(Long类型),但你传了newIssue.getIssueTypeId()(String类型),而且新issue还没保存到Jira,根本没有生成ID,这必然引发异常。

三、修改与排查建议

  1. 修复链接创建的参数错误:
    必须先保存新issue,再创建链接,正确代码如下:

    // 先保存新issue到Jira,获取已生成的ID
    def createdIssue = issueManager.createIssueObject(authenticationContext.getLoggedInUser(), newIssue)
    // 再创建issue链接,传入正确的目标issue ID
    issueLinkManager.createIssueLink(issue.getId(), createdIssue.getId(), issueLinkType, sequence, authenticationContext.getLoggedInUser())
    
  2. 添加排查日志:
    在关键位置插入日志,确认变量状态:

    def log = Logger.getLogger('atlassian-jira.log')
    // 检查基础对象
    log.warn("Issue对象: " + issue)
    log.warn("Issue是否为空: " + (issue == null))
    
    def authenticationContext = ComponentAccessor.jiraAuthenticationContext
    log.warn("当前登录用户: " + authenticationContext.getLoggedInUser())
    
    // 检查用户存在性
    def userManager = ComponentAccessor.userManager
    def assigneeUser = userManager.getUserByName("mouh")
    log.warn("用户mouh查询结果: " + assigneeUser)
    newIssue.setAssignee(assigneeUser)
    
    // 检查新Issue对象
    MutableIssue newIssue= ComponentAccessor.issueFactory.issue
    log.warn("新创建的MutableIssue: " + newIssue)
    
  3. 捕获异常打印堆栈:
    把else块内的逻辑用try-catch包裹,打印完整异常信息到Jira日志:

    else{
        log.warn("MOUNA CAMELIA ELSE")
        try {
            int componentSize=issue.getComponents().size()
            for(ProjectComponent component : issue.getComponents()) {
                componentList.add(component.getName())
            }
            issue.update {
                String text= "The super feature "+issue+" will be split into "+componentSize+
                " features, one for each component:\n"
                for(String component: componentList){
                    text = text +"-"+ component+"\n"; 
                }
                setCustomFieldValue('Execution Summary', text)
            }
            // 后续创建issue和链接的代码...
        } catch (Exception e) {
            log.error("执行异常详情:", e) // 完整堆栈会显示具体出错行号
        }
    }
    

内容的提问来源于stack exchange,提问作者منى

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 17:25:54