I have four Eclipse plugin projects (create a new Java Project, right-click, configure, Convert to Plugin Project) in my workspace. The first (my.runtime
) contains an interface (MyFactoryInterface
) and a class (MyClient
) that defines a method (List<String> getAllFactoryNames()
) that loads all implementations of that interface via java.util.ServiceLoader
and calls a method (String getName()
) on them, collecting the results and returning them in a list.
To test that class, I have a JUnit test in the second project (my.runtime.test
, set up with my.runtime
as Fragment-Host), checking if the name returned by a dummy implementation(MyDummy
, returning "Dummy"
) I have in the my.runtime.test
project is in the list returned by MyClient.getAllFactoryNames()
. So far, it works fine.
In the third project (my.extension
, with my.runtime
as dependency) I have a class (MyHello
) that uses the names returned by MyClient.getAllFactoryNames()
to return a list of greetings ("Hello "+name
).
Again, to test t开发者_如何学Gohis, I have a project (my.extension.test
, with my.extension
as Fragment-Host) containing another Implementation (MyWorld
, returning "World"
as name) and a JUnit test case checking if "Hello World"
is in the greetings returned by MyHello.getGreetings()
. This test fails, as MyClient still only finds the MyDummy
implementation, and not the MyWorld
implementation. Both implementations are accompanied by matching entries in META-INF/services/my.runtime.MyFactoryInterface
files.
I currently use the following code to load the implementations:
ServiceLoader<MyFactoryInterface> myFactoryLoader = ServiceLoader.load(MyFactoryInterface.class);
for (MyFactoryInterface myFactory : myFactoryLoader) {
I know that I can supply a ClassLoader as a second argument to ServiceLoader.load
, but I have no idea how to get one that knows all plugin projects... any suggestions? Or is ServiceLoader not the right tool for this problem?
If anyone stumbles over the same problem: the combination of ServiceLoader.load(MyFactoryInterface.class, Thread.currentThread().getContextClassLoader())
in MyClient
and Thread.currentThread().setContextClassLoader(MyWorld.class.getClassLoader());
in the second test did the job.
精彩评论