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()) } }
可能触发空指针的关键点
issue对象为空:如果自动化规则触发时issue未正确传入,调用issue.getComponents()等所有方法都会抛异常。可以在脚本开头加日志:log.warn("Issue是否为空: " + (issue == null))。- 登录用户为空:
authenticationContext.getLoggedInUser()如果返回null,后续createIssueLink传入null用户会触发异常。加日志:log.warn("当前登录用户: " + authenticationContext.getLoggedInUser())。 - 用户"mouh"不存在:
userManager.getUserByName("mouh")找不到用户时返回null,设置给newIssue.setAssignee()可能触发异常。加日志:log.warn("用户mouh是否存在: " + (userManager.getUserByName("mouh") != null))。 newIssue初始化失败:ComponentAccessor.issueFactory.issue如果未正确初始化,newIssue为null,后续调用setProjectObject()等方法会抛异常。加日志:log.warn("新Issue对象是否为空: " + (newIssue == null))。createIssueLink参数错误:这里是核心问题——createIssueLink的第二个参数需要目标issue的ID(Long类型),但你传了newIssue.getIssueTypeId()(String类型),而且新issue还没保存到Jira,根本没有生成ID,这必然引发异常。
三、修改与排查建议
修复链接创建的参数错误:
必须先保存新issue,再创建链接,正确代码如下:// 先保存新issue到Jira,获取已生成的ID def createdIssue = issueManager.createIssueObject(authenticationContext.getLoggedInUser(), newIssue) // 再创建issue链接,传入正确的目标issue ID issueLinkManager.createIssueLink(issue.getId(), createdIssue.getId(), issueLinkType, sequence, authenticationContext.getLoggedInUser())添加排查日志:
在关键位置插入日志,确认变量状态: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)捕获异常打印堆栈:
把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,提问作者منى
相关产品推荐
相关产品推荐

