Extract Insight Attribute from object

Roy Chapman July 16, 2021

I keep on telling myself that there has to be an easy way to do this, but try as I can I can't find it. Anyhow, here goes;

I have an object called Simulator, this has around 50 attributes, most made up of objects. One of these attributes is also an object called Aircraft. I simply want to return this value. I have tried to create an Insight Object with the following config

Multiple: false
Object Schema: Example CMDB
Filter Scope (IQL): objectType = "Aircraft"
Filter Issue Scope (IQL): Simulator = ${CMDB Simulator}

But this returns nothing.

I have also tried to return this as a Java Script field which I managed to pull from an earlier request and changed

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import org.apache.log4j.Level
log.setLevel(Level.INFO)

Issue issue = issue

def simField = issue.getCustomFieldValue(ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName('CMDB Simulator'))

if(simField){
def commentManager = ComponentAccessor.getCommentManager()
def sdUser = ComponentAccessor.getUserManager().getUserByName('robotuser');

//insight classes & components
Class objectFacadeClass = ComponentAccessor.getPluginAccessor().getClassLoader().findClass("com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectFacade");
Class objectTypeAttributeFacadeClass = ComponentAccessor.getPluginAccessor().getClassLoader().findClass("com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectTypeAttributeFacade");
def objectTypeAttributeFacade = ComponentAccessor.getOSGiComponentInstanceOfType(objectTypeAttributeFacadeClass);
def objectFacade = ComponentAccessor.getOSGiComponentInstanceOfType(objectFacadeClass);

ArrayList <String> userList = new ArrayList<String>();

for(Simulator in simField){
//extract insight key ang get object
def sim=Simulator.toString()
log.info(sim)
def simKey = sim.substring(sim.indexOf('(')+1,sim.indexOf(')'))
def simObject = objectFacade.loadObjectBean(simKey)
//get Aircraft for that Simulator
def aircraft = objectFacade.loadObjectAttributeBean(simObject.getId(), "Aircraft").getObjectAttributeValueBeans()

if(aircraft) {
log.info(aircraft[0])
def aircraftString = aircraft[0].toString()
log.info(aircraftString)
return aircraftString
}
}
log.info(aircraft + "returned!")
}

This script returns the following log messages

2021-07-16 13:01:31,427 INFO [runner.ScriptBindingsManager]: A320n29 - S35 (CMDB-276)
2021-07-16 13:01:31,427 INFO [runner.ScriptBindingsManager]: [1912(287)]
2021-07-16 13:01:31,427 INFO [runner.ScriptBindingsManager]: [1912(287)]

How can I change [1912(287)] into the value?

Which seems to be half way there, but as I say I would hope the process is a lot easier than this.

Any pointers?

2 answers

2 votes
Peter-Dave Sheehan
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
July 21, 2021

Hi Roy

Welcome to the community.

A while back, I posted an article where I shared some methods to extract attributes from objects. Maybe some of it should be able to help you.

I'm a little confused about where you are and what you are trying to do.

Are you trying to assign the Aircraft object to an Issue after the user selects a Simulator object in a custom field?

If so, can you elaborate and specify the name of each custom field (looks like simulator object goes in the "CMDB Simulator" custom field).

You could achieve this using a read-only insight custom field. But this value would only be set after the issue is created (and can't be changed).

If you are looking for a live update on the form, you would have to use behaviours for that.

As for extracting an object or object key from an attribute of another object within scriptrunner (which is groovy script not Java Script as you mentioned), you could try something along these lines:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectFacade
import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectTypeAttributeFacade
import com.riadalabs.jira.plugins.insight.services.model.ObjectBean
@WithPlugin('com.riadalabs.jira.plugins.insight')
@PluginModule ObjectFacade objectFacade
@PluginModule ObjectTypeAttributeFacade objectTypeAttributeFacade

Issue issue = issue

def simField = ComponentAccessor.customFieldManager.getCustomFieldObjectsByName('CMDB Simulator')[0]
def simValue = issue.getCustomFieldValue(simField) as ArrayList<ObjectBean>

if(simValue){
def commentManager = ComponentAccessor.commentManager
def sdUser = ComponentAccessor.getUserManager().getUserByName('robotuser');

ArrayList <String> userList = new ArrayList<String>();

simValue.each{ simObj ->
//simObj is automatically detected to be an ObjectBean
log.info "simulator object on $issue.key is $simObj.objectKey"
def aicraftAttributeBean = objectFacade.loadObjectAttributeBean(simObj.id, 'Aircraft')
def aircraftObjectIds = aicraftAttributeBean.objectAttributeValueBeans*.referencedObjectBeanId //by default all attribute values are arrays even if attribute allows only 1
def aircraftObjects = aircraftObjectIds.collect{objectFacade.loadObjectBean(it)}
log.info "Found aircraft object(s): ${aircraftObjects*.objectKey}"
}
}

Some notes on this...

  • With scriptrunner, you can @PluginModule to easily get those facades
  • getCustomFieldValue() on insight custom fields always return an array of ObjectBeans. You are making things more complicated than they need to be when you revert that return value to string then attempt to parse/substring to find the key then load an objectbean using the facade. You can just iterate over the existing array of objectbean (even if you only have one)
  • getObjectAttributeValueBeans() will always return an array of ObjectAttributeValueBean even for attributes that only allow a single value. Each values can then be a string, number, object reference etc based on the data type of the attribute. So you can call the specific method (getDateValue(), getTextValue()) to get the typed value for that bean. You can always use "getValue()" to return a generic Object or, in your case, we can go directly to the referenceObjectBeanId and load an ObjectBean from the facade using that ID
0 votes
Björn Gullander
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.
August 16, 2021

Hi, 

If I understand you correctly you want a field "Aircraft" which only shows the Aircraft objects that are connected to a Simulator which is set in the "CMDB Simulator" field?

If this is what you want you need to change the "Filter issue scope" of the Aircraft field in this way:

object having inboundReferences(Key = ${CMDB Simulator})

In this way you will get all objects of type Aircraft which have an object reference from the object selected in CMDB Simulator field.

It is also possible to set the Aircraft field automatically by using the same IQL in the "Filter Assign Scope" configuration.

Suggest an answer

Log in or Sign up to answer