Jira Service Management ApprovalRequestedEvent is broken in ScriptRunner 8.34.0 - 8.40.0 listeners

Dear community,

I use Jira Data Center 9.12.15 with Jira Service Management 5.12.15 and ScriptRunner 8.33.0 and I have a ScriptRunner listener for com.atlassian.servicedesk.internal.api.events.ApprovalRequestedEvent.
It works perfect until I update the ScriptRunner plugin to 8.34.0 or even 8.40.0.

After ScriptRunner is updated, I can’t add any SR listener for ApprovalRequestedEvent. It shows the following error when I click “Save”:

startup failed: Script_52693419a3d27a6d59aea0a8640f3cfa.groovy: 13: unable to resolve class com.atlassian.servicedesk.internal.api.events.ApprovalRequestedEvent @ line 13, column 26. void onEvent(com.atlassian.servicedesk.internal.api.events.ApprovalRequestedEvent event) { ^ 1 error

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Script_52693419a3d27a6d59aea0a8640f3cfa.groovy: 13: unable to resolve class com.atlassian.servicedesk.internal.api.events.ApprovalRequestedEvent
 @ line 13, column 26.
               void onEvent(com.atlassian.servicedesk.internal.api.events.ApprovalRequestedEvent event) {
                            ^

1 error

	at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:292)
	at org.codehaus.groovy.control.CompilationUnit$ISourceUnitOperation.doPhaseOperation(CompilationUnit.java:909)
	at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:692)
	at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:666)
	at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:373)
	at groovy.lang.GroovyClassLoader.lambda$parseClass$2(GroovyClassLoader.java:316)
	at org.codehaus.groovy.runtime.memoize.StampedCommonCache.compute(StampedCommonCache.java:163)
	at org.codehaus.groovy.runtime.memoize.StampedCommonCache.getAndPut(StampedCommonCache.java:154)
	at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:314)
	at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:298)
	at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:258)
	at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:274)
	at groovy.lang.GroovyClassLoader$parseClass$2.call(Unknown Source)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139)
	at com.onresolve.scriptrunner.runner.events.ClassGeneratingInvokerRegistrar.memoizedMethodPriv$getClassForEventTypesSetboolean(ClassGeneratingInvokerRegistrar.groovy:90)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:343)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:328)
	at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:342)
	at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:63)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:171)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:194)
	at com.onresolve.scriptrunner.runner.events.ClassGeneratingInvokerRegistrar$_closure1.doCall(ClassGeneratingInvokerRegistrar.groovy)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:343)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:328)
	at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:279)
	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1009)
	at groovy.lang.Closure.call(Closure.java:418)
	at org.codehaus.groovy.runtime.memoize.Memoize$MemoizeFunction.lambda$call$0(Memoize.java:137)
	at org.codehaus.groovy.runtime.memoize.ConcurrentCommonCache.getAndPut(ConcurrentCommonCache.java:137)
	at org.codehaus.groovy.runtime.memoize.ConcurrentCommonCache.getAndPut(ConcurrentCommonCache.java:113)
	at org.codehaus.groovy.runtime.memoize.Memoize$MemoizeFunction.call(Memoize.java:136)
	at jdk.internal.reflect.GeneratedMethodAccessor1332.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:43)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:173)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:75)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:80)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148)
	at com.onresolve.scriptrunner.runner.events.ClassGeneratingInvokerRegistrar.getClassForEventTypes(ClassGeneratingInvokerRegistrar.groovy)

After restarting the Jira server, existing SR listeners for ApprovalRequestedEvent stop working. They just don’t trigger on this JSM event. Downgrading ScriptRunner from 8.40.0 to 8.33.0 version helps.

Has anyone faced this problem with listeners for JSM events? Is there any viable solution for it (except for upgrading to Jira 10 + SR 9)?

Thanks in advance!

@rlander what would you recommend in this situation? I appreciate your attention to this matter.

1 Like

There was some heavy “refactoring” in this area recently, it’s quite possible something is not being handled quite right with events from third party apps (of which JSM is one).

I’ll probably have to prod at things with a debugger, that’ll take me a couple of days.

If you have some concrete reproduction steps I can execute in a clean installation of Jira/JSM/ScriptRunner, that would be a big help @ViacheslavDobromyslo

Appears there is an existing public bug for this: https://assist.adaptavist.com/browse/SRJIRA-7431

Probably something isn’t being kept in sync when JSM enables/disables and ScriptRunner is either missing or holding on to a stale classloader from JSM

1 Like

@rlander you were right. I debugged ScriptRunner and found that it does not refresh its class loaders if it starts before ServiceDesk and Insight. Due to SR`s code obfuscation, I couldn’t dig deeper to identify the root cause.

I solved this problem with a quick workaround by appending Require-Bundle to the end of groovyrunner-8.40.0.jar:/META-INF/MANIFEST.MF:

Require-Bundle: com.riadalabs.jira.plugins.insight,com.atlassian.jira.
 plugins.jira-assets-plugin,com.atlassian.servicedesk.approvals-plugin
 ,com.atlassian.servicedesk


Note1: Empty lines at the bottom of the manifest file are mandatory.
Note2: I will likely narrow down the list of required bundles after thorough testing.

After this change, OSGi starts ScriptRunner after Insight and ServiceDesk, granting it access to the required classes from these plugins.

Caveat:
You must have JSM application installed in Jira. Otherwise, ScriptRunner won’t be able to find the required bundles and will wait for 5 minutes. After that, Jira will start without ScriptRunner.

This behaviour is a regression, so that will get fixed up in ScriptRunner at some point.

It’s been a bit of a hectic week but I do intend to take a look/fix when I clear my current todo list. Nice to see you have a temporary workaround!

Due to SR`s code obfuscation

We don’t actually obfuscate ScriptRunner code, the majority of ScriptRunner is however authored in Groovy, and the Groovy compiler bytecode output looks pretty obfuscated when decompiled :sweat_smile: