Update Object Attribute Insight - Add NOT overwrite - Script advice

Daniel Smith June 5, 2020

Hey there!

We are using Insight in our Jira Server instance to manage our enterprise applications. For each system (object) we've defined three separate object attributes (Guests, Users, Admins) that captures all users that have access to the system.

TEST-SYSTEM OBJECT.png

What we are trying to achieve is adding users to these Insight attributes when a Jira ticket is updated:

FieldsInsight.png

We've managed to leverage the script from the Insight docs - Update Object attribute

However naturally it is updating/overwriting any existing users captured in the Guests/Admins/Users object attribute. We want to add the user so we can get an accurate list of users for our systems.

Does anyone out there have any experience of what we are trying to achieve? How did you manage to ADD a user to existing object attributes without deleting what already exists in the object attributes field? Any script advice much appreciated!

Thank you!!

3 answers

1 accepted

2 votes
Answer accepted
Tobias Ravenstein June 18, 2020

Hi Daniel,

i had a very simular problem which i could not figure out by the documentation on my own, so i just asked the mindville support for some further examples. Helping writing groovy scripts is not part of the support but kindly they send me on example which helped me to solve my issue. I've asked and am allowed to share this here with you also.

My Request:

I want to add a second object to an object attribute on a existing object. How can i expand the current 'list'?

Explanation for the provided script:

In order to assign an Equipment Object ("front man asset) to a User, I reference the User Object on an Equipment Object (the Equipment will have an Attribute of the Type User, to reference User Object Type).

Once I assign an Equipment to a User, I would like the Equipment Object to be referenced back from the User Object.

A User may have already some Equipment Objects assigned, hence referenced.

In the attached script - Line 23, we get the attributeBean from the User Object.

We dhen check if there is an existing reference stored in the attribute:

If it is null (no reference is currently set in this attribute) - then the script will create a new reference and store it in the Attribute.

If a reference already exists, the script will add a new reference to the existing references (Values).

 

And here is the script:

import com.atlassian.jira.component.ComponentAccessor
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.groovy.GroovyLogger
import com.riadalabs.jira.plugins.insight.services.model.ObjectBean
//context: begin
// log, object, currentUser, issue, originalIssue (https://documentation.riada.se/insight/latest/insight-administrator-s-guide/insight-workflow-functions/groovy-script-variables)
def logger = (GroovyLogger) log
def objectBean = (ObjectBean) object
//context: end
def objectFacade = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectFacade.class)
def objectTypeAttributeFacade = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectTypeAttributeFacade.class)
// Object is the Frontman Asset (4699) object type with the attribute 'Assignee' (20882) referencing the `User` (4702) object type
// `User` (4702) object type contain an attribute 'Assigned Equipment' (20958) that need to be set from this Frontman object
def ASSIGNEE_OBJECT_TYPE_ATTRIBUTE_ID = 20882
def EQUIPMENT_OBJECT_TYPE_ATTRIBUTE_ID = 20958
def assigneeAttributeBean = objectBean.objectAttributeBeans.find { objectAttributeBean ->
objectAttributeBean.objectTypeAttributeId == ASSIGNEE_OBJECT_TYPE_ATTRIBUTE_ID
}
assert assigneeAttributeBean != null, "Cannot find object type attribute assigneed `$ASSIGNEE_OBJECT_TYPE_ATTRIBUTE_ID`!"
def referencedUserId = assigneeAttributeBean.objectAttributeValueBeans.first().referencedObjectBeanId
def referencedUser = objectFacade.loadObjectBean(referencedUserId)
def equipmentAttributeBean = referencedUser.objectAttributeBeans.find { objectAttributeBean ->
objectAttributeBean.objectTypeAttributeId == EQUIPMENT_OBJECT_TYPE_ATTRIBUTE_ID
}
if (equipmentAttributeBean == null) {
logger.info("Creating a new reference...")
def assignedEquipmentTypeAttribute = objectTypeAttributeFacade.loadObjectTypeAttributeBean(EQUIPMENT_OBJECT_TYPE_ATTRIBUTE_ID)
def newEquipmentAttributeBean = referencedUser.createObjectAttributeBean(assignedEquipmentTypeAttribute)
def equipmentValueBean = newEquipmentAttributeBean.createObjectAttributeValueBean()
equipmentValueBean.setValue(assignedEquipmentTypeAttribute, objectBean.id)
newEquipmentAttributeBean.objectAttributeValueBeans.add(equipmentValueBean)
objectFacade.storeObjectAttributeBean(newEquipmentAttributeBean)
} else {
def frontManReference = equipmentAttributeBean.objectAttributeValueBeans.find { objectAttributeValueBean ->
objectAttributeValueBean.referencedObjectBeanId == objectBean.id
}
if (frontManReference == null) {
logger.info("Creating a new reference (not found)")
def assignedEquipmentTypeAttribute = objectTypeAttributeFacade.loadObjectTypeAttributeBean(EQUIPMENT_OBJECT_TYPE_ATTRIBUTE_ID)
def existingEquipmentAttributeBean = equipmentAttributeBean.createMutable()
def equipmentValueBean = existingEquipmentAttributeBean.createObjectAttributeValueBean()
equipmentValueBean.setValue(assignedEquipmentTypeAttribute, objectBean.id)
existingEquipmentAttributeBean.objectAttributeValueBeans.add(equipmentValueBean)
objectFacade.storeObjectAttributeBean(existingEquipmentAttributeBean)
} else {
logger.info("Equipment already set!")
}
}
true

Short flow:

  1. Get object
  2. Get object attribute
  3. If empty create new and set value
  4. else load value make it mutable and add(expand) a new value

 

Hope this helps

Regards
Tobias

licensemanagement@bdr.de May 30, 2021

x

Julia Liebchen May 30, 2021

Dear community

I need some help,.. please...!

I'd like to update a current object (via customListener in groovy).

I need set a referenced object for a attribute (that does'nt contain a singleObject).

My object I want to update is an ASSET.
The attribute is called ROOM.

The referencedObject for this attribute is a special object into the ROOM.objectType.
I can figure out the special object by "iqlFacade.findObjectsByIQLAndSchema".
The result represents the object I want to set into the attribute ROOM.

I tried out the very good example above, but my script always break off.
Because the object attribute is empty, I create a new object attribute and want to set the value, but I get something like this: newRoomValueBean = [null(643644)]
I lost the overview.

Could you possibly describe, what the next steps would be?

Do I have to create a new ObjectAttributeValueBean?
Do I have to add the object ROOM to the ASSET-Object?
Is it possible to use setReferencedObjectBeanId, but how does it works?

Thanks in advance and best regards, Julia

Julia Liebchen May 30, 2021

Okay, I've solved it!

I need to use the following procedure to update an available attribute of type referencedObject:

//Searching for InsightObject Room
def availableInsightRoomObjects = iqlFacade.findObjectsByIQLAndSchema(2, "objectType in (ROOM) AND ROOMTYPE = \"SRVC\" AND Location = " + sourceInsightAttributeLocationValue) //Location depends on other referencedObjects of the cfCurrentInsightObject

//Create a new reference for roomAttribute
def assignedRoomTypeAttribute = objectTypeAttributeFacade.loadObjectTypeAttributeBean(destinationInsightAttributeRoomId)

//Create a mutableAttributeBean of assignedTypeAttribute
def mutableRoomAttributeBean = assignedRoomTypeAttribute.createMutable()

//LoadObject from searchResult
def referencedRoom = objectFacade.loadObjectBean(availableInsightRoomObject.id)

//GetName of referencedObject
def newValue = referencedRoom.getName()

//Create new AttributeBean based on: currentInsightObject(customField), existingAttribute, newValue
def newObjectAttributeBean = objectAttributeBeanFactory.createObjectAttributeBeanForObject(cfCurrentInsightObject[0], mutableRoomAttributeBean, newValue);


mutableRoomAttributeBean = objectFacade.storeObjectAttributeBean(newObjectAttributeBean);

Some if/else-Statements will make it a bit prettier. 

Best Regards, Julia

Like # people like this
0 votes
Salim Hammar February 21, 2022

Hello @Daniel Smith  @Kelly Turdanes  @Julia Liebchen  licensemanagement@bdr.de  @Tobias Ravenstein  i need very help

 

This script will serve when i create , update and delete the component these features will apply in any project (with project key) 

 

Actually when i edit a name for the component it's working without issue but when i change the lead the component (edit) it goes on a loop and after i don't access the page component 

 

My opinion the problem it's : "destComponent = projectComponentManager.findByComponentName(project.id, oldComponent.name as String)" because he updated the name only but i don't know for add the other attributes 

that is to say (name , description, lead and assignee) 

You have idea ??

--------------------------------------------------------------------------------

def dest_prj = ['TS', 'TD', 'TK']
import com.atlassian.jira.bc.project.component.MutableProjectComponent
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.bc.project.component.ProjectComponentCreatedEvent
import com.atlassian.jira.event.bc.project.component.ProjectComponentDeletedEvent
import com.atlassian.jira.event.bc.project.component.ProjectComponentUpdatedEvent
import com.atlassian.jira.project.AssigneeTypes
import com.atlassian.jira.project.Project
import com.atlassian.jira.bc.project.component.ProjectComponent

def projectManager = ComponentAccessor.projectManager
def projectComponentManager = ComponentAccessor.projectComponentManager

ProjectComponent component = event.projectComponent
log.info "Deletected ${event.getClass()} for $component.name ($component.id)"
dest_prj.each { String destProjectKey ->
log.info "Getting project object from dest_prj: $destProjectKey"
def project = projectManager.getProjectObjByKey(destProjectKey)
log.info "Project object found: $project"
def destComponent = projectComponentManager.findByComponentName(project.id, component.name)
log.info "Attempted to identify matching destination component in $project using name=$component.name : $destComponent"
if (event instanceof ProjectComponentCreatedEvent) {
if (!destComponent) {
log.info "Attempting to create $component.name into $project"

projectComponentManager.create(component.name, component.description, component.lead, component.assigneeType, project.id)
} else {
log.error "Can't create a copy of $component.name in $destProjectKey project. A component with that name alreay exist."
}
}
if (event instanceof ProjectComponentUpdatedEvent) {
def oldComponent = (event as ProjectComponentUpdatedEvent).oldProjectComponent as ProjectComponent
if (event instanceof ProjectComponentUpdatedEvent) {
destComponent = projectComponentManager.findByComponentName(project.id, oldComponent.name as String)
log.info "Attempted to identify matching destination component in $project using name=$oldComponent.name : $destComponent"
}

if (destComponent) {
log.info "Attempting to update $destComponent.name ($destComponent.id) from $project project using data from $component.name ($component.id)"
destComponent = MutableProjectComponent.copy(destComponent)
destComponent.with {
name = component.name
description = component.description
lead = component.lead
assigneeType = component.assigneeType //or use component.assigneeType
}
projectComponentManager.update(destComponent)
} else {
log.warn "No component found in $destProjectKey with name $oldComponent.name. Can't perform an update."
}
}

if (event instanceof ProjectComponentDeletedEvent) {
log.info "Detected Component Deletion event for $component.name"
if (destComponent) {
log.info "Attempting to detelete $destComponent.name ($destComponent.id) from $project project"
projectComponentManager.delete(destComponent.id)
} else {
log.warn "No component found in $destProjectKey with name $component.name. Can't delete it."
}
}
}

--------------------------------------------------------

0 votes
Kelly Turdanes September 16, 2021

Hi There, 

Appreciate if you can provide script advise please.

I'd like to apply the same logic but for Get object, I'd like to particularly get objects having inboundreference(Name=xxx) then proceed with the rest of the logic flow

  1. Get object 
  2. Get object attribute
  3. If empty create new and set value
  4. else load value make it mutable and add(expand) a new value

Been struggling for a while how to achieve this :)

Thank you

Suggest an answer

Log in or Sign up to answer