Should a script run by jjs.exe be able to locate services with ServiceLoader
just as any Java program could?
I have reduced my case to the following script:
function dump (stream)
{
(new BufferedReader(new InputStreamReader(stream))).lines().forEach(function (x) { print(x); });
}
var BufferedReader = Java.type("java.io.BufferedReader");
var InputStreamReader = Java.type("java.io.InputStreamReader");
var ServiceLoader = Java.type("java.util.ServiceLoader");
var Sts = Java.type("prodist.sts.Sts");
print(Sts);
// A
var stsConfigStream = Sts.class.getResourceAsStream("/META-INF/services/prodist.sts.Sts");
dump(stsConfigStream);
// B
var StsImpl = Java.type("prodist.sts.internal.StsImpl");
print(new StsImpl());
// C
var stsLoader = ServiceLoader.load(Sts.class);
var stsIterator = stsLoader.iterator();
stsIterator.next();
// D
I call jjs.exe
setting up the Class-Path on the command line. My script correctly finds and prints the interface name in point A. It locates the service description resource; when I dump the content of the resource, I see the expected content in point B. I make sure the expected implementation class is available in point C.
In point D, the program throws a NoSuchElementException
, which I interpret as ServiceLoader not finding any service description resource for the interface.
Is this supposed to work? Am I missing something?
You need to set the thread context class loader. Refer to any class from your jjs classpath, get it's Class object and then get it's class loader. You then set that loader as thread context class loader. This should be done before you use service loader API:
var StsClass = Java.type("prodist.sts.Sts").class;
java.lang.Thread.currentThread().contextClassLoader = StsClass.classLoader;