Come for the products,
stay for the community

The Atlassian Community can help you and your team get more value out of Atlassian products and practices.

Atlassian Community about banner
4,293,730
Community Members
 
Community Events
165
Community Groups

Scriptrunner - Update Insight Object attribute value if it was empty before

Edited

Hi Community!

I want to update Insight object attribute in workflow post function. I have many object type e.g.: Monitor, Laptop, Phone. Every object type has the attribute: Status (The type of the Status attribute is Status). In the ticket there is an asset list, e.g.: monitor1, laptop1, laptop2.

I want update the attribute Status of all objects in the ticket regardless of their type. I have a working solution if the object Status value is not null (earlier somehow was set), but it's not working, if the attribute is empty:

assetList.each{asset ->
def insightObject = iqlFacade.findObjectsByIQLAndSchema(schemaId, "key = " + asset.getObjectKey()).first();
def attributeId = insightObject.objectAttributeBeans.find {
objectTypeAttributeFacade.loadObjectTypeAttributeBean(it.objectTypeAttributeId).name == "Status"
}?.objectTypeAttributeId;

def objectTypeAttributeBean = objectTypeAttributeFacade.loadObjectTypeAttributeBean(attributeId);
def newStatusAttributeBean = asset.createObjectAttributeBean(objectTypeAttributeBean);
def newObjectAttributeBean = objectAttributeBeanFactory.createObjectAttributeBeanForObject(insightObject, objectTypeAttributeBean, "NewStatusName");

def objectAttributeBean = objectFacade.loadObjectAttributeBean(insightObject.getId(), objectTypeAttributeBean.getId());
if (objectAttributeBean != null) {
newObjectAttributeBean.setId(objectAttributeBean.getId());
}
objectAttributeBean = objectFacade.storeObjectAttributeBean(newObjectAttributeBean);
}

I can get the ObjectTypeId from the asset and create a new ObjectTypeBean:

def objectTypeId = asset.getObjectTypeId();
def objectTypeBean = objectTypeFacade.loadObjectTypeBean(objectTypeId);

??????
def attributeId = objectTypeBean.getAttributeId.where(name == "Status"); //here I want to get the the current asset attribute id, where the attribute name is Status
??????

But I don't know, how to get the attributeId of the current object type Status attribute by the name of the attribute!

5 answers

1 accepted

Okay, here is my 'lazyUpdate' function. 'simpleAttributes' is a simple "Key: attribute name, value: list of values for that attribute" map. Just call this function with the object and map, and as long as the attribute names match, it should update in most cases. In my case, I didn't have to update object references, so you may need to extend this function a little for that.

You should have instantiated the relevant facades: 

  • attrMgr: ObjectTypeAttributeFacade
  • attrFty: ObjectAttributeBeanFactory
  • objMgr: ObjectFacade

 

Map lazyUpdate(ObjectBean object, Map<String,List> simpleAttributes) {

/* Get metadata on attributes from object metadata (ie. the object type) */
List<ObjectTypeAttributeBean> objectTypeAttributeBeans = attrMgr.findObjectTypeAttributeBeans(object.getObjectTypeId())

List objectTypeAttributeNames = objectTypeAttributeBeans.collect{it.getName().toLowerCase()}

/* Proceed only with attributes that match keys in the map */
simpleAttributes.findAll {
it.key.toLowerCase() in objectTypeAttributeNames

}.collectEntries { attr, values ->

/* This is the object type attribute and the one we want to modify */
ObjectTypeAttributeBean objectTypeAttributeBean = objectTypeAttributeBeans.find {
it.getName().toLowerCase() == attr.toLowerCase()
}

/* Create the new attribute bean based on the value */
def newObjectAttributeBean = attrFty.createObjectAttributeBeanForObject(object, objectTypeAttributeBean, values.getAt(0) as String)

/* Load the attribute bean */
def objectAttributeBean = objMgr.loadObjectAttributeBean(object.getId(), objectTypeAttributeBean.getId());
if (objectAttributeBean != null) {
/* If attribute exist reuse the old id for the new attribute */
newObjectAttributeBean.setId(objectAttributeBean.getId());
}

/* Store the object attribute into Insight. */
try {
objectAttributeBean = objMgr.storeObjectAttributeBean(newObjectAttributeBean);
} catch (Exception vie) {
log.warn("Could not update object attribute due to validation exception:" + vie.getMessage());
}
[objectTypeAttributeBean.getName(),objectAttributeBean.getObjectAttributeValueBeans()*.getValue()]
}
}

Hi,

Thank you for your help, I didn't used this function, but it helped a lot!

This line was the key, what I needed, after that my code is working fine.

List<ObjectTypeAttributeBean> objectTypeAttributeBeans = attrMgr.findObjectTypeAttributeBeans(object.getObjectTypeId())

 Thanks again! I'm very happy now! :)

Six

Hey, so the issue is that you can't reliably ask an object for its attribute types because objects only store information on attributes that have values. Objects won't tell you about attributes that don't have a value.

The way to work with Insight attributes is:

  1. Get the object type ID from the object
  2. Get the object type from the object type ID
  3. Get the attributes from the object type

It looks simpler to get the attributes from the object but if you ever want to change objects, that's not going to be enough. You have to get the attributes from the object type.

Hope that helps!

Hi,

Thank you for your reply!

Yes, that's what I tried to do, just I don't know how to do that by the name of the attribute. Can you help me?

Six

Try always getting first the objectAttributeBean and based on that (to see if it is null) then the attribute.

See the following piece of code:

 



//Gets the Device Type -> DeviceTypeAttribute and related fields
def DeviceTypeAttributeOAB = objectFacade.loadObjectAttributeBean(objectId, objectTypeAttributeName)
def DeviceTypeAttribute = DeviceTypeAttributeOAB ? DeviceTypeAttributeOAB.getObjectAttributeValueBeans()[0] : null; //Loads the ObjectAttributeValueBeans of the DEVICE_TYPE or null

Try always getting first the objectAttributeBean and based on that (to see if it is null) then the attribute.

See the following piece of code:

 



//Gets the Device Type -> DeviceTypeAttribute and related fields
def DeviceTypeAttributeOAB = objectFacade.loadObjectAttributeBean(objectId, objectTypeAttributeName)
def DeviceTypeAttribute = DeviceTypeAttributeOAB ? DeviceTypeAttributeOAB.getObjectAttributeValueBeans()[0] : null; //Loads the ObjectAttributeValueBeans of the DEVICE_TYPE or null

 

Hi @Six 

Does the following code works for you to get the attribute id ?

def attribute = objectFacade.loadObjectAttributeBean(asset.getId(), "Status")

log.warn "attribute id: "+attribute.objectTypeAttributeId

Regards,

John Chin 

Hi @John Chin

It's not working, I get the following error:
"java.lang.NullPointerException: Cannot get property 'objectTypeAttributeId' on null object".

I think the problem is the same as in my solution: The current asset has no Status attribute (because it's empty yet). :(
(I have tried the solution with an attribute which has value and that case it's working.)

Six

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
SERVER
TAGS
Community showcase
Posted in Jira Service Management

Jira Service Management Documentation Opportunities

Hello everyone, Hope everyone is safe! A few months ago we posted an article sharing all the new articles and documentation that we, the AMER Jira Service Management team created. As mentioned ...

217 views 0 6
Join discussion

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you