Scriptrunner: loadClass() not exposing the Methods?

david-guild November 8, 2019

Hello All,

When I loadClass() from a script executed by a scriptrunner post function, none of the methods are available.

ie: 

testMe = this.class.classLoader.loadClass( load_class, true )?.newInstance()
log.debug("testMe: " + testMe.dump())
if (!testMe.metaClass.respondsTo(testMe,"populateTransitionName")) {
log.debug("populateTransitionName is a NOT a valid method!")

}

 

The dump looks fine, the properties of the class are exposed and accessible ... but the test fails.

When trying to access the methods, I get a methodNotFound exception .. which I would expect since the metaClass test fails

What I really want to do is to not have to "import" a metric ton of packages so I want to accept the post function , interrogate the payload, and dynamically load the appropriate class to execute.

Maybe this is just not possible in the confines of Groovy executed by ScriptRunner?

I tried a bunch of different way to load the class including GroovyClassLoader among others.

Hopefully this is something simple? I have already wasted a couple of hour trying different ways of invoking loadClass() to try to make it work ...

 

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.
November 8, 2019

Interesting idea.

I have played with class loader to be able to load custom class in the console. But I'd never tried to load existing classes.

Playing around with your code and what I had before I got this to respond apparently correctly in the console:

def load_class = "com.atlassian.jira.component.ComponentAccessor"
testMe = this.class.classLoader.loadClass( load_class, true )?.newInstance()
log.debug("testMe: " + testMe.dump())
testMethod = "getProjectManager"
if (!testMe.metaClass.respondsTo(testMe,testMethod)) {
log.debug("$testMethod is a NOT a valid method!")
}
testMe.projectManager.projectCount
david-guild November 11, 2019

Where as, that did not work for me when invoking a post function.

But, this is what did work in the end:

def getClass($path_to_file) {

// Take groovy off, just in case it was passed in
def cleaned_path = $path_to_file.replaceAll(".groovy","")

// Combine base path + cleaned path + .groovy
File sourceFile = new File("${base_url}/${cleaned_path}.groovy")

// Delcare the Object
Class groovyClass = new GroovyClassLoader(getClass().getClassLoader()).parseClass(sourceFile)

// Return the object
(GroovyObject) groovyClass.newInstance()
}

This is a method of a classLoader that I created to handle the code.  I should have used regex to strip the .groovy, but I was in a hurry.

The main difference here is the "parseClass" method ... and the use of "GroovyClassLoader".

This now works as expected ... I have not tested from the console as this is part of an automation system so console working / not working is a non-issue.

The end goal? to not have a bunch of "post functions" spread out all over the workflow transitions. (multiple transitions with multiple post functions).   In the end, there will be one post function call per transition and that call will act as a "router" to call the proper controllers / handlers / repo's.

This will allow us to manage all processes through "code deploy" instead of manually changing workflows.

Suggest an answer

Log in or Sign up to answer