Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in
Celebration

Earn badges and make progress

You're on your way to the next level! Join the Kudos program to earn points and save your progress.

Deleted user Avatar
Deleted user

Level 1: Seed

25 / 150 points

Next: Root

Avatar

1 badge earned

Collect

Participate in fun challenges

Challenges come and go, but your rewards stay with you. Do more to earn more!

Challenges
Coins

Gift kudos to your peers

What goes around comes around! Share the love by gifting kudos to your peers.

Recognition
Ribbon

Rise up in the ranks

Keep earning points to reach the top of the leaderboard. It resets every quarter so you always have a chance!

Leaderboard

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,556,176
Community Members
 
Community Events
184
Community Groups

Insight Automation - Unable to resolve classes

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

0 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.
May 02, 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()

 

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events