How to set epic link in Jira using Groovy

miller j
Contributor
November 15, 2017

I need to set epic link using groovy if a condition is true. I'm using the following script:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.Issue;
def customFieldManager = ComponentAccessor.getCustomFieldManager()
IssueManager issueManager = ComponentAccessor.getOSGiComponentInstanceOfType(IssueManager.class)
def epiclink = CustomFieldManager.getCustomFieldObject("customfield_10101") 
issue.setCustomFieldValue(epiclink,"TS-14")

If I set the epic link to null it works,

    issue.setCustomFieldValue(epiclink, null)

3 answers

1 accepted

4 votes
Answer accepted
Joshua Yamdogo @ Adaptavist
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.
November 20, 2017

Hi Miller,

I believe you will need to pass the issue object of the Epic in order to link it, not the Epic link's issue key.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder

def customFieldManager = ComponentAccessor.getCustomFieldManager()
def issueManager = ComponentAccessor.getIssueManager()
def epicIssue = issueManager.getIssueObject("TS-14") // Epic issue key here
def epicLink = customFieldManager.getCustomFieldObjectByName("Epic Link")
epicLink.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(epicLink), epicIssue),new DefaultIssueChangeHolder())
miller j
Contributor
November 20, 2017
Joshua Yamdogo @ Adaptavist
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.
November 20, 2017

Glad to help. Thanks for using ScriptRunner!

Christoffer Karlsson October 17, 2018

Hi Joshua Yamdogo @ Adaptavist

When I use the:

epicLink.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(epicLink), epicIssue),new DefaultIssueChangeHolder())

I get these errors in the log:

/rest/scriptrunner/latest/user/exec/ [c.a.g.manager.issuelink.EpicLinkManagerImpl] Cannot set or mutate an ImmutableGenericValue
java.lang.UnsupportedOperationException: Cannot set or mutate an ImmutableGenericValue
at com.atlassian.jira.util.ofbiz.ImmutableGenericValue.set(ImmutableGenericValue.java:63)
at org.ofbiz.core.entity.GenericEntity.set(GenericEntity.java:283)
at com.atlassian.jira.issue.util.DefaultIssueUpdater.doUpdate(DefaultIssueUpdater.java:48)
at sun.reflect.GeneratedMethodAccessor7207.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26)
at com.sun.proxy.$Proxy17.doUpdate(Unknown Source)
... 2 filtered
at java.lang.reflect.Method.invoke(Method.java:498)
at com.atlassian.plugin.osgi.bridge.external.HostComponentFactoryBean$DynamicServiceInvocationHandler.invoke(HostComponentFactoryBean.java:136)
at com.sun.proxy.$Proxy17.doUpdate(Unknown Source)
at com.atlassian.greenhopper.manager.issuelink.EpicLinkManagerImpl.createChangeItem(EpicLinkManagerImpl.java:479)
at com.atlassian.greenhopper.manager.issuelink.EpicLinkManagerImpl.createChangeItem(EpicLinkManagerImpl.java:469)
at com.atlassian.greenhopper.manager.issuelink.EpicLinkManagerImpl.createEpicLinkChangeItemsForChild(EpicLinkManagerImpl.java:403)
at com.atlassian.greenhopper.manager.issuelink.EpicLinkManagerImpl.updateLinksForIssues(EpicLinkManagerImpl.java:246)
at com.atlassian.greenhopper.manager.issuelink.EpicLinkManagerImpl.associateIssuesWithEpic(EpicLinkManagerImpl.java:179)
at com.atlassian.greenhopper.service.issuelink.EpicServiceImpl.addIssuesToEpic(EpicServiceImpl.java:103)
at com.atlassian.greenhopper.customfield.epiclink.EpicLinkCFType.associateIssueWithEpic(EpicLinkCFType.java:686)
at com.atlassian.greenhopper.customfield.epiclink.EpicLinkCFType.createValue(EpicLinkCFType.java:202)
at com.atlassian.greenhopper.customfield.epiclink.EpicLinkCFType.createValue(EpicLinkCFType.java:44)
at com.atlassian.jira.issue.fields.ImmutableCustomField.createValue(ImmutableCustomField.java:693)
at com.atlassian.jira.issue.fields.ImmutableCustomField.updateValue(ImmutableCustomField.java:410)
at com.atlassian.jira.issue.fields.ImmutableCustomField.updateValue(ImmutableCustomField.java:396)
at com.atlassian.jira.issue.fields.OrderableField$updateValue.call(Unknown Source)
at Script360.run(Script360.groovy:64)
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:352)
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:153)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:233)
at javax.script.ScriptEngine$eval.call(Unknown Source)
at com.onresolve.scriptrunner.runner.ScriptRunnerImpl.runScriptAndGetContext(ScriptRunnerImpl.groovy:157)
at com.onresolve.scriptrunner.runner.ScriptRunner$runScriptAndGetContext$8.callCurrent(Unknown Source)
at com.onresolve.scriptrunner.runner.ScriptRunnerImpl.runStringAsScript(ScriptRunnerImpl.groovy:146)
at com.onresolve.scriptrunner.runner.ScriptRunnerImpl.runStringAsScript(ScriptRunnerImpl.groovy)
at com.onresolve.scriptrunner.runner.rest.common.UserScriptEndpoint.exec(UserScriptEndpoint.groovy:173)
... 2 filtered
at java.lang.reflect.Method.invoke(Method.java:498)
at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60)
... 13 filtered
at com.atlassian.plugins.rest.module.RestDelegatingServletFilter$JerseyOsgiServletContainer.doFilter(RestDelegatingServletFilter.java:154)
... 1 filtered
at com.atlassian.plugins.rest.module.RestDelegatingServletFilter.doFilter(RestDelegatingServletFilter.java:68)
... 41 filtered
at com.atlassian.web.servlet.plugin.request.RedirectInterceptingFilter.doFilter(RedirectInterceptingFilter.java:21)
... 53 filtered
at com.atlassian.jira.security.JiraSecurityFilter.lambda$doFilter$0(JiraSecurityFilter.java:66)
... 1 filtered
at com.atlassian.jira.security.JiraSecurityFilter.doFilter(JiraSecurityFilter.java:64)
... 16 filtered
at com.atlassian.plugins.rest.module.servlet.RestSeraphFilter.doFilter(RestSeraphFilter.java:37)
... 19 filtered
at com.atlassian.jira.servermetrics.CorrelationIdPopulatorFilter.doFilter(CorrelationIdPopulatorFilter.java:30)
... 5 filtered
at com.valiantys.jira.plugins.sql.service.servletcontext.ContextListenerServletFilter.doFilter(ContextListenerServletFilter.java:24)
... 8 filtered
at com.atlassian.web.servlet.plugin.request.RedirectInterceptingFilter.doFilter(RedirectInterceptingFilter.java:21)
... 4 filtered
at com.atlassian.web.servlet.plugin.LocationCleanerFilter.doFilter(LocationCleanerFilter.java:36)
... 26 filtered
at com.atlassian.jira.servermetrics.MetricsCollectorFilter.doFilter(MetricsCollectorFilter.java:25)
... 23 filtered
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)

Do you have any idea why?

Worth to note is that it actually seems to have worked when you browse and check the issues and Epic Links in JIRA. But it's ugly that it spams this stuff in the logs :)

Regards
Christoffer

Ruslan Karpov
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
June 11, 2024

In this case you need to cast epicIssue to MutableIssue

1 vote
Amy Niebel
Contributor
September 29, 2018

Hi all, I was able to create a task on the Create transition for an Epic and link to Epic Link. My use case is that I want to automatically create an Estimate task (which has its own workflow) each time I create an Epic and link to it.

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.MutableIssue
import com.atlassian.jira.issue.link.IssueLink
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.IssueFactory
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItem
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.project.ProjectManager
import com.atlassian.jira.project.Project
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.user.util.UserManager
import com.atlassian.jira.util.ImportUtils
import com.opensymphony.workflow.WorkflowContext

import org.apache.log4j.Logger
import org.apache.log4j.Category

def Category log = Category.getInstance("com.onresolve.jira.groovy")
log.setLevel(org.apache.log4j.Level.DEBUG)

// Get project object
Project project = issue.getProjectObject()

IssueManager issueMgr = ComponentAccessor.getIssueManager()
ProjectManager projectMgr = ComponentAccessor.getProjectManager()
CustomFieldManager cfMgr = ComponentAccessor.getCustomFieldManager()

// Get user object
String currentUser = (String) ((WorkflowContext) transientVars.get("context")).getCaller();
ApplicationUser currentUserObj = ComponentAccessor.getUserManager().getUserByKey(currentUser);

def wasIndexing = ImportUtils.indexIssues
ImportUtils.indexIssues = true
IssueFactory issueFactory = ComponentAccessor.getIssueFactory()

// Epic attributes
def epicSummary = issue.getSummary()
def key = issue.getKey()
def epicIssue = issueMgr.getIssueObject(key)

// Create issue
MutableIssue newIssue = issueFactory.getIssue()

newIssue.setSummary("Estimate for: " + epicSummary)
newIssue.setProjectObject(project)
newIssue.setIssueTypeId("11302") //Estimate type
newIssue.description = "-"
newIssue.reporter = issue.getReporter()
def epicLink = cfMgr.getCustomFieldObjects(newIssue).find { it.name == 'Epic Link' }
newIssue.setCustomFieldValue(epicLink, epicIssue)

// Create Issue
issueMgr.createIssueObject(currentUserObj, newIssue)

ImportUtils.indexIssues = wasIndexing
Christoffer Karlsson October 17, 2018

Hi @Amy Niebel

I have a similar script and I also use the:

i.setCustomFieldValue(cfEpicLink, epicIssue)

 But for me, it generates the following errors:

No signature of method: com.atlassian.jira.issue.DocumentIssueImpl.setCustomFieldValue() is applicable for argument types: (com.atlassian.jira.issue.fields.ImmutableCustomField, com.atlassian.jira.issue.IssueImpl) values: [Epic Link, ARTINFO-185] Possible solutions: getCustomFieldValue(com.atlassian.jira.issue.fields.CustomField)

Have you ever noticed this problem?

Regards
Christoffer

ioann god November 21, 2018

i think type-casting of  the 'issue.DocumentIssueImpl to issue.MutableIssue' can resolve it.

Amy Niebel
Contributor
November 26, 2018

@Christoffer Karlsson sorry, no but I see dog code may have a solution?

0 votes
Q October 21, 2019

Joshua Yamdogo @ Adaptavist 

Joshua,

I got following error message, when I try to do epicLink.updateValue

 

java.lang.NullPointerException
 at com.atlassian.jira.issue.link.DefaultIssueLinkManager.getIssueLink(DefaultIssueLinkManager.java:381)
 at com.atlassian.jira.issue.link.DefaultIssueLinkManager.createIssueLink(DefaultIssueLinkManager.java:89)
 at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26)
 at com.sun.proxy.$Proxy147.createIssueLink(Unknown Source)
 at com.atlassian.plugin.osgi.bridge.external.HostComponentFactoryBean$DynamicServiceInvocationHandler.invoke(HostComponentFactoryBean.java:136)
 at com.sun.proxy.$Proxy147.createIssueLink(Unknown Source)
 at com.atlassian.greenhopper.manager.issuelink.EpicLinkManagerImpl.createLink(EpicLinkManagerImpl.java:322)
 at com.atlassian.greenhopper.manager.issuelink.EpicLinkManagerImpl.updateLinksForIssues(EpicLinkManagerImpl.java:238)
 at com.atlassian.greenhopper.manager.issuelink.EpicLinkManagerImpl.associateIssuesWithEpic(EpicLinkManagerImpl.java:179)
 at com.atlassian.greenhopper.service.issuelink.EpicServiceImpl.addIssuesToEpic(EpicServiceImpl.java:103)
 at com.atlassian.greenhopper.customfield.epiclink.EpicLinkCFType.associateIssueWithEpic(EpicLinkCFType.java:686)
 at com.atlassian.greenhopper.customfield.epiclink.EpicLinkCFType.createValue(EpicLinkCFType.java:202)
 at com.atlassian.greenhopper.customfield.epiclink.EpicLinkCFType.createValue(EpicLinkCFType.java:44)
 at com.atlassian.jira.issue.fields.ImmutableCustomField.createValue(ImmutableCustomField.java:693)
 at com.atlassian.jira.issue.fields.ImmutableCustomField.updateValue(ImmutableCustomField.java:410)
 at com.atlassian.jira.issue.fields.ImmutableCustomField.updateValue(ImmutableCustomField.java:396)
 at com.atlassian.jira.issue.fields.OrderableField$updateValue.call(Unknown Source)
 at Script104.run(Script104.groovy:29)

I am using Jira 7.13

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events