I'm trying to add additional attribute values to an existing attribute using a groovy script post function. The following script adds the value we want but overwrites the existing values that we want to keep. How do I stop it from removing the existing values? Is there a way I can add anything to my script?
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.fields.CustomField;
/* Get Insight Object Facade from plugin accessor */
Class objectFacadeClass = ComponentAccessor.getPluginAccessor().getClassLoader().findClass("com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectFacade");
def objectFacade = ComponentAccessor.getOSGiComponentInstanceOfType(objectFacadeClass);
/* Get Insight Object Attribute Facade from plugin accessor */
Class objectTypeAttributeFacadeClass = ComponentAccessor.getPluginAccessor().getClassLoader().findClass("com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectTypeAttributeFacade");
def objectTypeAttributeFacade = ComponentAccessor.getOSGiComponentInstanceOfType(objectTypeAttributeFacadeClass);
/* Get the factory that creates Insight Attributes */
Class objectAttributeBeanFactoryClass = ComponentAccessor.getPluginAccessor().getClassLoader().findClass("com.riadalabs.jira.plugins.insight.services.model.factory.ObjectAttributeBeanFactory");
def objectAttributeBeanFactory = ComponentAccessor.getOSGiComponentInstanceOfType(objectAttributeBeanFactoryClass);
/* This is the custom field with the value you want to add to an object attribute */
CustomField jiraCustomField = ComponentAccessor.getCustomFieldManager().getCustomFieldObject(14932); // Change 12345 to the correct value
/* This is the custom field where the object/s you want to set the value */
CustomField insightCustomField = ComponentAccessor.getCustomFieldManager().getCustomFieldObject(14930); // Change 23456 to the correct value
def insightObjects = issue.getCustomFieldValue(insightCustomField); // "issue" variable is always accessible in post function scripts.
/* This is the priority object type attribute and the one we want to modify */
def objectTypeAttributeBean = objectTypeAttributeFacade.loadObjectTypeAttributeBean(379);
if (insightObjects != null) {
insightObjects.each{insightObject ->
/* Create the new attribute bean based on the value */
def newValue = issue.getCustomFieldValue(jiraCustomField);
def newObjectAttributeBean = objectAttributeBeanFactory.createObjectAttributeBeanForObject(insightObject, objectTypeAttributeBean, newValue[0].getName());
/* Load the attribute bean */
def objectAttributeBean = objectFacade.loadObjectAttributeBean(insightObject.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 = objectFacade.storeObjectAttributeBean(newObjectAttributeBean);
} catch (Exception vie) {
log.warn("Could not update object attribute due to validation exception:" + vie.getMessage());
}
}
}
/* Done! :) */
return true;
Here is another version that should work better:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.fields.CustomField
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
import com.riadalabs.jira.plugins.insight.services.model.factory.ObjectAttributeBeanFactory
/* Get Insight Facades and Factories from plugin accessor */
def objectFacade = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectFacade)
def objectTypeAttributeFacade = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectTypeAttributeFacade)
def objectAttributeBeanFactory = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectAttributeBeanFactory)
/* This is the custom field with the value you want to add to an object attribute */
CustomField jiraCustomField = ComponentAccessor.getCustomFieldManager().getCustomFieldObject(14932) // Change 12345 to the correct value
/* This is the custom field where the object/s you want to set the value */
CustomField insightCustomField = ComponentAccessor.getCustomFieldManager().getCustomFieldObject(14930) // Change 23456 to the correct value
def insightObjects = issue.getCustomFieldValue(insightCustomField) // "issue" variable is always accessible in post function scripts.
/* This is the priority object type attribute and the one we want to modify */
def objectTypeAttributeBean = objectTypeAttributeFacade.loadObjectTypeAttributeBean(379)
if (insightObjects != null) {
insightObjects.each { ObjectBean insightObject ->
def newValue = issue.getCustomFieldValue(jiraCustomField)
/* Load the attribute bean */
def objectAttributeBean = objectFacade.loadObjectAttributeBean(insightObject.id, objectTypeAttributeBean.id)
if (!objectAttributeBean) {
/* If attribute doesn't exist create one */
objectAttributeBean = objectAttributeBeanFactory.createObjectAttributeBeanForObject(insightObject, objectTypeAttributeBean, newValue[0].name)
} else {
/* If attribute exists, check if the value is not already present and add it if needed */
if(objectAttributeBean.objectAttributeValueBeans.any{it.value == newValue[0].name }) {
/* Value already present, return null to end this each iteration */
return null
}
//created a version of the objectAttributeBean that can be modified
objectAttributeBean = objectAttributeBean.createMutable()
//extract the current list of values
def values = objectAttributeBean.objectAttributeValueBeans
//create a valueBean for the new entry
def objectAttributeValueBean = objectAttributeBean.createObjectAttributeValueBean()
objectAttributeValueBean.setValue(objectTypeAttributeBean,newValue[0].name)
//add the new entry to the list of values
values.add(objectAttributeValueBean)
//update the objectAttribute with the new list of values.
objectAttributeBean.setObjectAttributeValueBeans(values)
}
/* Store the object attribute into Insight. */
try {
objectAttributeBean = objectFacade.storeObjectAttributeBean(objectAttributeBean)
} catch (Exception vie) {
log.warn("Could not update object attribute due to validation exception:$vie.message")
}
}
}
Thank you! I tried your modifications and I get an error on line 39 objectAttributeBean.objectAttributeValueBeans.add(objectAttributeValueBean)
java.lang.UnsupportedOperationException
java.base/java.util.AbstractList.add(Unknown Source) java.base/java.util.AbstractList.add(Unknown Source) java_util_List$add.call(Unknown Source) org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115) org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:127) script_5cb834065217c5f3fa91b1c89d2c3889$_run_closure1.doCall(script_5cb834065217c5f3fa91b1c89d2c3889.groovy:39) java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) java.base/java.lang.reflect.Method.invoke(Unknown Source) org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:101) groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323) org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:263) groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1041) groovy.lang.Closure.call(Closure.java:405) groovy.lang.Closure.call(Closure.java:421) org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2331) org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2316) org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2357) org.codehaus.groovy.runtime.dgm$186.invoke(Unknown Source) org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:244) org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53) org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115) org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:127) script_5cb834065217c5f3fa91b1c89d2c3889.run(script_5cb834065217c5f3fa91b1c89d2c3889.groovy:24)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hello Marlee
Welcome to the community.
First off, I don't know why the documentation recommends using the classLoader to get riadalabs classes.
In my experience, the following works just as well:
import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectFacade
def objectFacade = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectFacade)
Anyway, re-ordering and modifying your code, I came up with this (untested):
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.fields.CustomField
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
import com.riadalabs.jira.plugins.insight.services.model.factory.ObjectAttributeBeanFactory
/* Get Insight Facades and Factories from plugin accessor */
def objectFacade = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectFacade)
def objectTypeAttributeFacade = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectTypeAttributeFacade)
def objectAttributeBeanFactory = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectAttributeBeanFactory)
/* This is the custom field with the value you want to add to an object attribute */
CustomField jiraCustomField = ComponentAccessor.getCustomFieldManager().getCustomFieldObject(14932) // Change 12345 to the correct value
/* This is the custom field where the object/s you want to set the value */
CustomField insightCustomField = ComponentAccessor.getCustomFieldManager().getCustomFieldObject(14930) // Change 23456 to the correct value
def insightObjects = issue.getCustomFieldValue(insightCustomField) // "issue" variable is always accessible in post function scripts.
/* This is the priority object type attribute and the one we want to modify */
def objectTypeAttributeBean = objectTypeAttributeFacade.loadObjectTypeAttributeBean(379)
if (insightObjects != null) {
insightObjects.each { ObjectBean insightObject ->
def newValue = issue.getCustomFieldValue(jiraCustomField)
/* Load the attribute bean */
def objectAttributeBean = objectFacade.loadObjectAttributeBean(insightObject.id, objectTypeAttributeBean.id)
if (!objectAttributeBean) {
/* If attribute doesn't exist create one */
objectAttributeBean = objectAttributeBeanFactory.createObjectAttributeBeanForObject(insightObject, objectTypeAttributeBean, newValue[0].name)
} else {
/* If attribute exists, check if the value is not already present and add it if needed */
if(objectAttributeBean.objectAttributeValueBeans.any{it.value == newValue[0].name }) {
/* Value already present, return null to end this each iteration */
return null
}
def objectAttributeValueBean = objectAttributeBean.createObjectAttributeValueBean()
objectAttributeValueBean.setValue(objectTypeAttributeBean,newValue[0].name)
objectAttributeBean.objectAttributeValueBeans.add(objectAttributeValueBean)
}
/* Store the object attribute into Insight. */
try {
objectAttributeBean = objectFacade.storeObjectAttributeBean(objectAttributeBean)
} catch (Exception vie) {
log.warn("Could not update object attribute due to validation exception:$vie.message")
}
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Unfortunately that did not work. The problem for that version is line 18:
def insightObjects = issue.getCustomFieldValue(insightCustomField) // "issue" variable is always accessible in post function scripts.
java.lang.NullPointerException
com.atlassian.jira.issue.IssueImpl.getCustomFieldValue(IssueImpl.java:951) com.atlassian.jira.issue.Issue$getCustomFieldValue.call(Unknown Source) org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115) org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:127) script_245f4e6aec3ad726767ce9aa19374716.run(script_245f4e6aec3ad726767ce9aa19374716.groovy:18)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Try this version with a bit more error trapping.
Make sure you change the 2 customfFieldId variables to match your custom fields. The script currently contains 14932 and 14930
Watch your logs while it runs and capture any details in there:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.fields.CustomField
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
import com.riadalabs.jira.plugins.insight.services.model.factory.ObjectAttributeBeanFactory
assert issue, "There is no 'issue' variable in the current context. Are you sure you added your script to a workflow post function?"
/* Get Insight Facades and Factories from plugin accessor */
def objectFacade = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectFacade)
def objectTypeAttributeFacade = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectTypeAttributeFacade)
def objectAttributeBeanFactory = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectAttributeBeanFactory)
def customFieldManager = ComponentAccessor.customFieldManager
/* This is the custom field with the value you want to add to an object attribute */
def jiraCustomFieldId = 14932 // Change 12345 to the correct value
CustomField jiraCustomField = customFieldManager.getCustomFieldObject(jiraCustomFieldId)
assert jiraCustomField, "There is no custom field matching id: $jiraCustomFieldId"
/* This is the custom field where the object/s you want to set the value */
def insightCustomFieldId = 14930// Change 12345 to the correct value
CustomField insightCustomField = customFieldManager.getCustomFieldObject(insightCustomFieldId)
assert insightCustomField, "There is no custom field matching id: $insightCustomFieldId"
def insightObjects = issue.getCustomFieldValue(insightCustomField) // "issue" variable is always accessible in post function scripts.
if(!insightObjects){
log.warn "There are no values in $insightCustomField.name. Nothing to do here."
return
}
/* This is the priority object type attribute and the one we want to modify */
def attributeId = 379
def objectTypeAttributeBean = objectTypeAttributeFacade.loadObjectTypeAttributeBean(attributeId)
assert objectTypeAttributeBean, "Could not load attribute with id=$attributeId. Please verify the script and make sure this is the correct attribute id"
insightObjects.each { ObjectBean insightObject ->
def newValue = issue.getCustomFieldValue(jiraCustomField)
/* Load the attribute bean */
def objectAttributeBean = objectFacade.loadObjectAttributeBean(insightObject.id, objectTypeAttributeBean.id)
if (!objectAttributeBean) {
/* If attribute doesn't exist create one */
objectAttributeBean = objectAttributeBeanFactory.createObjectAttributeBeanForObject(insightObject, objectTypeAttributeBean, newValue[0].name)
} else {
/* If attribute exists, check if the value is not already present and add it if needed */
if (objectAttributeBean.objectAttributeValueBeans.any { it.value == newValue[0].name }) {
/* Value already present, return null to end this each iteration */
return null
}
//created a version of the objectAttributeBean that can be modified
objectAttributeBean = objectAttributeBean.createMutable()
//extract the current list of values
def values = objectAttributeBean.objectAttributeValueBeans
//create a valueBean for the new entry
def objectAttributeValueBean = objectAttributeBean.createObjectAttributeValueBean()
objectAttributeValueBean.setValue(objectTypeAttributeBean, newValue[0].name)
//add the new entry to the list of values
values.add(objectAttributeValueBean)
//update the objectAttribute with the new list of values.
objectAttributeBean.setObjectAttributeValueBeans(values)
}
/* Store the object attribute into Insight. */
try {
objectAttributeBean = objectFacade.storeObjectAttributeBean(objectAttributeBean)
} catch (Exception vie) {
log.warn("Could not update object attribute due to validation exception:$vie.message")
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Your script ran successfully against issue DLO-33
ArrayList
[User, B(DFA-2410)]
WARN : Could not update object attribute due to validation exception:ValidationInsightException: Validation errors were found: rlabs-insight-attribute-327: ErrorMessage{i18nKey='rlabs.insight.i18n.constraint.violation.ObjectAttributeValueBean.Null.value', parameters=[], additionalMessage=null};
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Here is yet another version with more logs.
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.fields.CustomField
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
import com.riadalabs.jira.plugins.insight.services.model.factory.ObjectAttributeBeanFactory
assert issue, "There is no 'issue' variable in the current context. Are you sure you added your script to a workflow post function?"
/* Get Insight Facades and Factories from plugin accessor */
def objectFacade = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectFacade)
def objectTypeAttributeFacade = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectTypeAttributeFacade)
def objectAttributeBeanFactory = ComponentAccessor.getOSGiComponentInstanceOfType(ObjectAttributeBeanFactory)
def customFieldManager = ComponentAccessor.customFieldManager
/* This is the custom field with the value you want to add to an object attribute */
def jiraCustomFieldId = 14932// Change 12345 to the correct value
CustomField jiraCustomField = customFieldManager.getCustomFieldObject(jiraCustomFieldId)
assert jiraCustomField, "There is no custom field matching id: $jiraCustomFieldId"
/* This is the custom field where the object/s you want to set the value */
def insightCustomFieldId = 14930// Change 12345 to the correct value
CustomField insightCustomField = customFieldManager.getCustomFieldObject(insightCustomFieldId)
assert insightCustomField, "There is no custom field matching id: $insightCustomFieldId"
def insightObjects = issue.getCustomFieldValue(insightCustomField) // "issue" variable is always accessible in post function scripts.
if(!insightObjects){
log.warn "There are no values in $insightCustomField.name. Nothing to do here."
return
}
/* This is the priority object type attribute and the one we want to modify */
def attributeId = 379
def objectTypeAttributeBean = objectTypeAttributeFacade.loadObjectTypeAttributeBean(attributeId)
assert objectTypeAttributeBean, "Could not load attribute with id=$attributeId. Please verify the script and make sure this is the correct attribute id"
def newValue = issue.getCustomFieldValue(jiraCustomField)
log.info "$jiraCustomField.name value for $issue.key is $newValue (${newValue.getClass()})"
log.info "$insightCustomField.name value for $issue.key is $insightObjects"
insightObjects.each { ObjectBean insightObject ->
log.info "Processing $insightObject to see if $newValue needs to be added"
/* Load the attribute bean */
def objectAttributeBean = objectFacade.loadObjectAttributeBean(insightObject.id, objectTypeAttributeBean.id)
if (!objectAttributeBean) {
/* If attribute doesn't exist create one */
objectAttributeBean = objectAttributeBeanFactory.createObjectAttributeBeanForObject(insightObject, objectTypeAttributeBean, newValue[0].name)
log.info "$objectTypeAttributeBean.name is empty for $insightObject creating a new value for ${newValue[0].name}"
} else {
/* If attribute exists, check if the value is not already present and add it if needed */
if (objectAttributeBean.objectAttributeValueBeans.any { it.value == newValue[0].name }) {
log.info "$objectTypeAttributeBean.name for $insightObject already contains ${newValue[0].name}"
/* Value already present, return null to end this each iteration */
return null
}
//created a version of the objectAttributeBean that can be modified
objectAttributeBean = objectAttributeBean.createMutable()
//extract the current list of values
def values = objectAttributeBean.objectAttributeValueBeans
//create a valueBean for the new entry
def objectAttributeValueBean = objectAttributeBean.createObjectAttributeValueBean()
objectAttributeValueBean.setValue(objectTypeAttributeBean, newValue[0].name)
log.info "Adding ${newValue[0].name} to $objectTypeAttributeBean.name for $insightObject"
//add the new entry to the list of values
values.add(objectAttributeValueBean)
//update the objectAttribute with the new list of values.
objectAttributeBean.setObjectAttributeValueBeans(values)
}
/* Store the object attribute into Insight. */
try {
objectAttributeBean = objectFacade.storeObjectAttributeBean(objectAttributeBean)
} catch (Exception vie) {
log.warn("Could not update object attribute due to validation exception:$vie.message")
}
}
Can you also provide the configuration for attribute with id = 327.
Per your error log, this attribute failed validation (but that's not the attribute we are attempting to modify -- you initially supplied attribute Id 379).
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.