The Atlassian Community Forums are currently in read-only mode. We will be relaunching on a new platform on September 22 (read more here). We apologize for the extended downtime. For concerns or questions, please email communitymanagers@atlassian.com. See you on the other side, on the new Atlassian Community Forums! :)

×

Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Insight Automation - Unable to resolve classes

Claire Berry
Contributor
May 2, 2023

Hi, 

I have created some Insight Automation which executes a Groovy script. The script works fine when used in scriptrunner script console. But when I add it to an Insight Automation rule, it does not work. 

I checked the server logs and found that the issue is it is unable to resolve some local and scriptrunner classes. 

Can anyone please tell me how I import these types of classes to work here?

Below is the errors:

Error when executing groovy script: /opt/atlassian/application-data/jira/shared/custom-jira-functions/insight-automation/ukicmdb/map-insight-user-to-jira-user.groovy

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:

/shared/custom-jira-functions/insight-automation/ukicmdb/map-insight-user-to-jira-user.groovy: 9: unable to resolve class shared.User

 @ line 9, column 1.

   import shared.User

   ^

 

/shared/custom-jira-functions/insight-automation/ukicmdb/map-insight-user-to-jira-user.groovy: 8: unable to resolve class shared.Insight

 @ line 8, column 1.

   import shared.Insight

   ^

 

/shared/custom-jira-functions/insight-automation/ukicmdb/map-insight-user-to-jira-user.groovy: 10: unable to resolve class shared.Environment

 @ line 10, column 1.

   import shared.Environment

   ^

 

/shared/custom-jira-functions/insight-automation/ukicmdb/map-insight-user-to-jira-user.groovy: 7: unable to resolve class com.onresolve.scriptrunner.runner.customisers.WithPlugin

 @ line 7, column 1.

   import com.onresolve.scriptrunner.runner.customisers.WithPlugin

   ^

 

/shared/custom-jira-functions/insight-automation/ukicmdb/map-insight-user-to-jira-user.groovy: 6: unable to resolve class com.onresolve.scriptrunner.runner.customisers.PluginModule

 @ line 6, column 1.

   import com.onresolve.scriptrunner.runner.customisers.PluginModule

   ^

 

5 errors

1 answer

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

0 votes
PD Sheehan
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 Champions.
May 2, 2023

The insight groovy framework is a lot more barebones than the scriptrunner one.

You will not have access to any com.onresolve... classes in the Insight groovy framework.
So WithPlugin and PluginModule won't be possible.

As for your shared classes, the only way I've found to use them is to load them using the classloader.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.config.util.JiraHome

def jiraHome = ComponentAccessor.getComponentOfType(JiraHome.class).home
Class Insight = new GroovyClassLoader(getClass().classLoader).parseClass(new File("$jiraHome/shared/Insight.groovy"))

You will not get any autocomplete. And those shared classes will not be able to also import other shared classes or use anything from the scriptrunner framework.

To replace something like

@WithPlugin("com.atlassian.servicedesk") sdPlugin
@PluginModule ServiceDeskManager serviceDeskManager

You would do something like this:

def classLoader = ComponentAccessor.pluginAccessor.classLoader
def serviceDeskManager = ComponentAccessor.getOSGiComponentInstanceOfType(classLoader.findClass('com.atlassian.servicedesk.api.ServiceDeskManager'))

 

Something to keep in mind (especially if any of your shared classes are large) is that they are never pre-compiled and caches like they are in scriptrunner.

Each time the groovy script is loaded (once for every object that triggered the automation), each groovy file is read fresh from the disk and compiled on the fly. This could be a performance bottleneck.

 

My preference where I can is to use ScriptRunner for as much of the logic as possible. 

You can create a rest endpoint with all the logic, then use a simpler instance of an Insight Groovy script to call that rest endpoint.

Here is, for example, one of my scripts that runs on my Employee object type. It detects if any user's full name is changed, and then calls the rest endpoint called "processInsightNameChange" that does things (in my case, it updates some attributes in Active Directory).

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.config.util.JiraHome
import com.atlassian.sal.api.net.Request
import com.atlassian.sal.api.net.TrustedRequest
import com.atlassian.sal.api.net.TrustedRequestFactory
import groovy.json.JsonBuilder
import groovyx.net.http.ContentType
import groovyx.net.http.URIBuilder

def fullNameAttributeName = 'Full Name'

def processNameChange = false
def nameChangeItem
if (objectUpdateList) {
log.info "Attributes updated: \n ${new JsonBuilder(objectUpdateList.collect { [(it.attributeName): [added: it.addedValues, removed: it.removedValues]] }).toPrettyString()}"
nameChangeItem = objectUpdateList.find { it.attributeName == fullNameAttributeName }
log.info "nameChangeItem=$nameChangeItem"
}
if (!nameChangeItem) return

def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def baseUrl = ComponentAccessor.applicationProperties.jiraBaseUrl

def trustedRequestFactory = ComponentAccessor.getOSGiComponentInstanceOfType(TrustedRequestFactory)

def restUrl = baseUrl + '/rest/scriptrunner/latest/custom/processInsightNameChange'
def request = trustedRequestFactory.createTrustedRequest(Request.MethodType.POST, restUrl) as TrustedRequest
def oldName = nameChangeItem.removedValues[0]
def newName = nameChangeItem.addedValues[0]
def payload = [objectKey: object.objectKey, oldName: oldName, newName: newName]
def jsonPayload = new JsonBuilder(payload).toString()
request.addTrustedTokenAuthentication(new URIBuilder(baseUrl).host, currentUser.name)
request.setRequestBody(jsonPayload, ContentType.JSON.toString())
log.info "Making POST request to $restUrl"
log.info " as user: $currentUser.name"
log.info " with paylod: $jsonPayload"
log.info " and Headers: ${request.getHeaders().toString()}"
def resp = request.execute()

 

TAGS
AUG Leaders

Atlassian Community Events