Scripted field - return issue status of linked issues

Fairly self-explanatory but all the Questions on Community revolve around custom fields and/or calculating Estimates for the same based on Links. I just want to very simply pull the status of the Linked Issue (based on Link Type) and copy it into this Scripted Field. 

Keeps displaying [ ] though, regardless of whether I choose the Custom or Text templates.

Code and screenshot below.

 

package com.onresolve.jira.groovy.test.scriptfields.scripts

import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.link.IssueLink;
import com.atlassian.jira.issue.link.IssueLinkManager;
import com.atlassian.jira.issue.IssueFieldConstants;
import com.atlassian.jira.issue.fields.IssueLinksSystemField;
import com.opensymphony.workflow.InvalidInputException;
import webwork.action.ActionContext;

def issue = issue as Issue
def issueLinkManager = ComponentAccessor.getIssueLinkManager()

issueLinkManager.getOutwardLinks(issue.id).each {issueLink ->
    if (issueLink.issueLinkType.name == "Base") { 
        def linkedIssue = issueLink.destinationObject
        def Basestatus = linkedIssue.getStatus().getName();


return Basestatus }}

Null.PNG

3 answers

Hello Lacey.

This, I would like to diagnose.

Could you run this script and tell me what you see?

import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.link.IssueLink;
import com.atlassian.jira.issue.link.IssueLinkManager;
import com.atlassian.jira.issue.IssueFieldConstants;
import com.atlassian.jira.issue.fields.IssueLinksSystemField;
import com.opensymphony.workflow.InvalidInputException;
import webwork.action.ActionContext;

def issue = issue as Issue
def issueLinkManager = ComponentAccessor.getIssueLinkManager()

issueLinkManager.getOutwardLinks(issue.id).each {issueLink ->
    if (issueLink.issueLinkType.name == "Base") { 
        def linkedIssue = issueLink.destinationObject
        def Basestatus = linkedIssue.getStatus()
        if(!Basestatus){
                return "this is null"
}else{
return Basestatus
}
}
}

That way I would know if the getStatus is working or not.

If it doesn't return "this is null", try this:

package com.onresolve.jira.groovy.test.scriptfields.scripts

import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.link.IssueLink;
import com.atlassian.jira.issue.link.IssueLinkManager;
import com.atlassian.jira.issue.IssueFieldConstants;
import com.atlassian.jira.issue.fields.IssueLinksSystemField;
import com.opensymphony.workflow.InvalidInputException;
import webwork.action.ActionContext;

def issue = issue as Issue
def issueLinkManager = ComponentAccessor.getIssueLinkManager()

issueLinkManager.getOutwardLinks(issue.id).each {issueLink ->
    if (issueLink.issueLinkType.name == "Base") { 
        def linkedIssue = issueLink.destinationObject
        def Basestatus = linkedIssue.getStatus().getName();


log.debug(Basestatus)
return Basestatus }}

and after you run it, go to the "logs" tab in the preview and see what it gets shown there.

Hopefully this will give you more insight into what is failing.

Cheers!

DYelamos

First did not return anything. Result still []

I inserted and ran the second, the Logs tab in preview didn't do anything, it displayed null as it has been. The Searcher is a Free Text Searcher, if it matters. Same null if Text or Custom template.

This has all been on the UAT instance to avoid interferring with Production.

I then created the field and ran your above scripts in my Prod instance, just to see what would happen. Output below, but Logs tab still null. It's worth noting that I DID NOT REINDEX after adding the field in Production. I added then immediately went to scripting.

This output occurs if it's Text or Custom template.

[com.atlassian.jira.issue.link.IssueLinkImpl@6f3725de[id=79652,sourceId=143482,destinationId=144198,issueLinkType=10810]]

 

Okay, as you can see there, Lacey, you are getting an IssueLinkImpl object. That puzzles me because you shouldn't be. Can you do this?

def issue = issue as Issue
def issueLinkManager = ComponentAccessor.getIssueLinkManager()

issueLinkManager.getOutwardLinks(issue.id).each {issueLink ->
if (issueLink.issueLinkType.name == "Base") {
def linkedIssue = issueLink.destinationObject
def Basestatus = linkedIssue.getStatus().getName();
return Basestatus.class }}

What does that show? I am sorry I'm asking you to debug but we got a hackaton here in Adaptavist these 2 days and I'm very busy. If you can wait for the weekend I can give this a look in my branch and give you something that works.

Cheers!

Dyelamos 

Still getting 

[com.atlassian.jira.issue.link.IssueLinkImpl@1638a57d[id=79756,sourceId=143452,destinationId=143629,issueLinkType=10811]] 

in production. I gave up on UAT since it's not giving ANYTHING let alone this.

 

 

Please do let me know if you have any other solutions for this, Daniel :) 

Lacey it will take me a bit to investigate, since these issues are a bit weird. In the meantime, is this instance of yours running on an MSQL database? 

We run on Oracle. Here's a screenshot of Sys-Info (minus addresses ;) )

 

DBINFO.PNG

 

Just following up on this because I am needy :) 

Hey Lacey.

Apologies for the long delay, I'm going to diagnose this on my own instance right now. I hope to have an answer for you in a bit.

Also something that struck me as odd during this. 

the ".each" closure performs a loop on each element. 

If you have a return and your if solution is valid more than one time, that might cause some issues.

In your closure you should collect the statuses of each link into a list, and then return that list as a string, not return every single status per field. 

If you want, feel free to investigate on what I've said, I will get something working before mid-day today if I'm lucky.

Cheers!

Dyelamos

Hey Lacey:

Could you try this:

import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.link.IssueLink;
import com.atlassian.jira.issue.link.IssueLinkManager;
import com.atlassian.jira.issue.IssueFieldConstants;
import com.atlassian.jira.issue.fields.IssueLinksSystemField;
import com.opensymphony.workflow.InvalidInputException;
import webwork.action.ActionContext;

def issue = issue as Issue
def issueLinkManager = ComponentAccessor.getIssueLinkManager()
def baseStatus = new ArrayList<String>()
issueLinkManager.getInwardLinks(issue.id).each {issueLink ->
if (issueLink.issueLinkType.name == "Base") {
baseStatus.add(issueLink.destinationObject.getStatus().getName())
}
}

return baseStatus.toString()

The main change is that you were using getOutwardLinks.

Altough it would make sense that your Main issue has OUTWARD links that go to its subtask, as a matter of fact, they are INWARD links. 

So the proper getter should be getInwardLinks.

This actually worked in my instance(I tried a simplified version) so give it a try and tell me how it goes.

Cheers!

Dyelamos

That is still giving a blank result... What search template do you have on the field, and which Template for the script?

Search Template: Free Text Searcher

Script Template: Text (multi-line)

 

Also, these Base link type issues are created as a part of Clone action on the original issue (where Clone link type is replaced by Base). For the customer ticket, for which we're generating this field, the link is Outward. For the Base ticket, the linked issue, the link is Inward. So confusing :( 

Hello Lacey.

This seems extremely odd, since I have tested this script myself and it worked perfectly, displaying the list as a text searcher and a text template.

If you think you have found a bug, please open a bug report at our support portal and we'll take a closer look there.

As a last resort, could you please log this:

log.debug(issueLinkManager.getInwardLinks(issue.id))

This is just so that we make sure that you actually got links in your issue.

Cheers!

Dyelamos

I mean are you sure you have links in your issues? This has ate at me for the whole morning, I tried to reproduce it for like 2 hours and it still works fine for me. I am really not sure what could be going wrong.

100% positive. I'm pulling them from a dashboard where it visibly shows the linked issues, and it's systematically applied whenever someone clones the original issue...

 

  1. Link Type
  2. Issue Screen showing link
  3. output of script provided

 

Link-Type.PNGissue_screen-withLINK.pngscript_and_log.PNG

Oops wrong screenshot of code. I updated it to what you gave me and this is what I got... a complete null, even in the log.

Capture-1.PNG

 

This is very odd Lacey. At this point I can only think that either you are getting the wrong issue Object, or that there are no links in the issue, or that the user that is executing the script is lacking permissions to see that issue. Do you have all of those corners covered?

No; there's nothing that I wouldn't be allowed to see on either of these projects, as shown in the screenshots. I can see both issues just fine. And as shown in the screenshots, there are links in the issue.

 

As for getting the wrong issue Object, how would that be possible given we are using the same script? 

 

Could there be a problem in our Database somehow?

 

Okay Lacey. Let's go back to basics.

I saw that you made a very weird casting on the first time of your script, so I took it out, the problem could have been there.

Do this:

import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.link.IssueLink;
import com.atlassian.jira.issue.link.IssueLinkManager;
import com.atlassian.jira.issue.IssueFieldConstants;
import com.atlassian.jira.issue.fields.IssueLinksSystemField;
import com.opensymphony.workflow.InvalidInputException;
import webwork.action.ActionContext;

def issueLinkManager = ComponentAccessor.getIssueLinkManager()
def baseStatus = new ArrayList<String>()
issueLinkManager.getInwardLinks(issue.id).each {issueLink ->
if (issueLink.issueLinkType.name == "Base") {
baseStatus.add(issueLink.destinationObject.getStatus().getName())
}
}
log.debug(issue.key)
return baseStatus.toString()

This should return the correct key for your issue in the logs.

If that still doesn't show anything i'd be very very surprised.

Cheers

DYelamos

It correctly shows the key for issue in the logs. There is still no result, despite there being a Base link type on the issue. :( 

Log tab in Previw panel:

2017-07-28 14:56:09,762 DEBUG [customfield.GroovyCustomField]: MU-6909

Atlassian-JIRA Log:

2017-07-28 14:56:09,762 http-bio-443-exec-2475 DEBUG Lacey87143 896x2946385x1 iksqw5 10.255.250.124,10.255.249.199 /rest/scriptrunner-jira/latest/scriptfields/17851/preview [c.o.scriptrunner.customfield.GroovyCustomField] MU-6909

0 vote

Hi Lacey,

Is "Base" an outward or inward link? Perhaps you could replace:

issueLinkManager.getInwardLinks(issue.id)

with:

issueLinkManager.getOutwardLinks(issue.id)

also to get outward and inward links you can use:

issueLinkManager.getIssueLinks(issue.id)

Hope this helps and let us know how you get on with that.

Adam 

"Base" is the link Type. That's what I'm not getting here... I'm pulling by the Link Type, right? 

 

If I need to define the entire name, outward i.e. "Customer Ticket [DO NOT SELECT system-generated link type]" that wouldn't make sense with what Adapatavist has in the documentation... 

I can see the problem here. You're correct that your using the link type name to get the "Base" ones but that is after you have got the inward links. From the screenshots it looks like your using the outward links so your code won't pick up that link. 

You'll have to either use: 

issueLinkManager.getOutwardLinks(issue.id)

or to get both inward and outward use:

issueLinkManager.getIssueLinks(issue.id)

There are also a few issues with your script which I've cleaned up and put into an example for you which gets the first "Base" link and displays it. You were trying to return the status in an "each" block which will just skip onto the next item rather than return the status. So in that case nothing will be returned.

Also note that the template I'm using is "Text Field (multi-line)" and this example seems to work for me.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue

def issue = issue as Issue
def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def baseLink = issueLinkManager.getIssueLinks(issue.id).find { issueLink -> issueLink.issueLinkType.name == "Base" }

if (baseLink) {
def linkedIssue = baseLink.destinationObject
def baseStatus = linkedIssue.getStatus().getName()


return baseStatus
}

return null

I guess that will give you a start. 

Still nothing..... And it definitely has a Base link type.

 

Filter_Results.PNGNull-Result.PNG

That's odd it's like the database is out of sync with the data you are seeing. I've seen a similar issue to this before which may be related.

Are you able to query the database, if so can you run the following query and put the output here for us to look at: https://developer.atlassian.com/jiradev/jira-platform/jira-architecture/database-schema#Databaseschema-Subtasks

That should show us what issue link types are actually stored.

:( It's there in the database...

 

Link_Table-Export_SCREENSHOT.PNG

0 vote

Hi Lacey,

That's odd but I realised there is a mistake in the script I sent you. Apologies for that.

Ok to get to the root cause of this once and for all can you please try run the following script in Admin -> Script Console and copy the output here. That should show us exactly what links issue TF-447 has.

import com.atlassian.jira.component.ComponentAccessor

def issueManager = ComponentAccessor.getIssueManager()
def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def issueKey = "TF-447"
def issue = issueManager.getIssueObject(issueKey)
def inwardLinks = issueLinkManager.getInwardLinks(issue.id)
def outwardLinks = issueLinkManager.getOutwardLinks(issue.id)

def links = ""
inwardLinks.each {
links += "Inward link - id: ${it.id}, name: ${it.issueLinkType.name}<br/>"
}

outwardLinks.each {
links += "Outward link - id: ${it.id}, name: ${it.issueLinkType.name}<br/>"
}

links

Thanks for continuing to plug away on this :)

The script console did the right thing - on TF-447 the links were edited yesterday to remove the Base issue, so result was blank. TF-442 has a link and gave a result.

 

Console-Output.PNG

No problem. Can you use the following script in your scripted field. This time we use the id to get the link.

Let's see if it works for that issue.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue

def issue = issue as Issue
def issueLinkManager = ComponentAccessor.getIssueLinkManager()

def outwardLinks = issueLinkManager.getOutwardLinks(issue.id)
def baseLink = outwardLinks.find { issueLink -> issueLink.issueLinkType.id == 10810L }

log.warn "Base link is ${baseLink?.issueLinkType?.name}"

if (baseLink) {
def linkedIssue = baseLink.destinationObject
def baseStatus = linkedIssue.getStatus().getName()


return baseStatus
}

return null

 Can you attach what message you see in the logs after you view the scripted field on the view issue screen?

It worked on Preview and on Issue screen, but we have log warn/errors on it.

I did a screenshot since only allowed formats are png/jpg et al...

 

LogResults.PNG

It looks like when we get the status of the linked issue it does not have one, which is rather odd.

After this line:

def linkedIssue = baseLink.destinationObject

can you add:

log.warn linkedIssue.key

Just to see that it is the correct issue being returned.

Prior to adding that line, we were getting failures on the Script Fields page

2017-08-04 13:04:38,293 ERROR [customfield.GroovyCustomField]: ************************************************************************************* 2017-08-04 13:04:38,293 ERROR [customfield.GroovyCustomField]: ************************************************************************************* 2017-08-04 13:04:38,293 ERROR [customfield.GroovyCustomField]: Script field failed on issue: MU-7032, field: Base Status java.lang.NullPointerException: Cannot get property 'name' on null object at Script106.run(Script106.groovy:10) 2017-08-04 13:04:38,293 ERROR [customfield.GroovyCustomField]: Script field failed on issue: MU-7032, field: Base Status java.lang.NullPointerException: Cannot get property 'name' on null object at Script106.run(Script106.groovy:10)

The log is just showing WARNs now, and no execution errors on the script

2017-08-04 13:26:20,484 http-nio-80-exec-4 WARN admin 806x4105808x2 1fy4sz0 172.16.209.235 /rest/api/2/issue [c.o.scriptrunner.customfield.GroovyCustomField] Base link is null
2017-08-04 13:26:20,562 http-nio-80-exec-4 WARN admin 806x4105808x2 1fy4sz0 172.16.209.235 /rest/api/2/issue [c.o.scriptrunner.customfield.GroovyCustomField] Base link is null
2017-08-04 13:26:38,743 http-bio-443-exec-3202 WARN Vinod.Sangwan 806x4105816x2 1eyjwjj 10.255.250.119,10.255.249.199 /rest/tempo-rest/1.0/worklogs/POLSUP-3 [c.o.scriptrunner.customfield.GroovyCustomField] Base link is null

I'm not entirely sure what could be the cause here but it looks when we do

baseLink.issueLinkType.name

 the name issueLinkType is null. Perhaps there is something amiss with the database your using? I'm not sure what is happening here.

When you try with a different link type, you have created do you get the same problem? How about with one of the built-in JIRA link types?

Well, the ones in the log that show a warn are legitimately without a Link Type of Base. It's just throwing that error for any issue viewed that doesn't have it.

I did a search generically and got results for Base. I then did

 

and t.linkname = 'Base'

 

and got the right results.

Link-Search-SQL.PNG

Hi Lacey,

To be honest we've been through almost everything that could be a likely cause on this. It seems to me that there is something missing when you get that link type which uses the Atlassian API so there's not much more insight on this.

Just wondering and sorry if we've already suggested to you, but does this work for other link types that are not Base ones? How about the built-in JIRA system link types?

That may narrow down the problem slightly.

Thanks,
Adam

Suggest an answer

Log in or Sign up to answer
How to earn badges on the Atlassian Community

How to earn badges on the Atlassian Community

Badges are a great way to show off community activity, whether you’re a newbie or a Champion.

Learn more
Community showcase
Published Jul 10, 2018 in Marketplace Apps

If you’re an Atlassian app developer, you’ll want to know about Atlas Camp!

This September 6-7, hundreds of Atlassian App developers will flock to Barcelona Spain to build skills, discover product roadmaps, meet face-to-face with the Atlassian team, and learn how to extend t...

181 views 0 4
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