Details
-
Bug
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
None
-
None
Description
When a Processor calls a Controller Service, the framework changes the Thread's Context ClassLoader from the Processor's ClassLoader to the Controller Service's ClassLoader. This works well. However, when the object that is returned from a Controller Service has a method invoked, the Context ClassLoader is that of the Processor.
This means that if the object returned attempts to load a class when its method is invoked, it's attempting to load it from the wrong ClassLoader. This can result in NoClassDefFoundError/ClassNotFoundException, etc.
An example from the mailing list:
---------
Hello,
I try to implement a groovy script where I'm using jsonOutput.
With nifi 1.5 the script works, but If I'm try to use the same groovy script with nifi 1.11.4, I get
"unable to load FastStringService"
example code :
class GroovyRecordSetWriter implements RecordSetWriter {
....
@Override
WriteResult write(Record r) throws IOException {
...
def j = JsonOutput.toJson([name: 'John Doe', age: 42])
out.write(j.getBytes())
...
---------
The problem here is that Controller Service returns a GroovyRecordSetWriter. When the processor calls #write, the Context Class Loader is the Processor's Context Class Loader, which knows nothing about Groovy. The call then delegates to `JsonOutput.toJson`. When this happens, Groovy, under the hood, attempts to load the `FastStringService` class using the Context Class Loader, which of course fails since the Context Class Loader is the Processor's ClassLoader and not the ScriptedRecordSetWriter's ClassLoader.
Attachments
Issue Links
- links to