SBT Plugin development - help needed (possible BUG found w/ java.util.ServiceLoader ?)

107 views
Skip to first unread message

Dominik

unread,
Sep 16, 2015, 2:07:54 PM9/16/15
to sbt-dev
Hi!

I created a custom SBT Plugin for PMD (a sourcecode analysis tool) as there is no existing plugin available.

I based it on the SBT-RSS Plugin by Will Sargent. 

I put the source on github: https://github.com/domdorn/sbt-pmd 

Right now, I have one problem, and I think it might be a bug in sbt or the way sbt uses classloaders:


PMD uses java.util.ServiceLoader to load its Plugins. It does this in two places.
One is 
net.sourceforge.pmd.lang.LanguageRegistry
and one is 
net.sourceforge.pmd.cpd.LanguageFactory

The code looks more or less like how you would expect it:
public final class LanguageRegistry {
private static LanguageRegistry instance = new LanguageRegistry();
private Map<String, Language> languages = new HashMap();

private LanguageRegistry() {
ServiceLoader languageLoader = ServiceLoader.load(Language.class);
Iterator i$ = languageLoader.iterator();

while(i$.hasNext()) {
Language language = (Language)i$.next();
this.languages.put(language.getName(), language);
}

}


In my plugin, I've added the dependencies to PMD-Core, PMD-Java, PMD-Scala as libraryDependencies in build.sbt (is this the error?)

I can use/instantiate the above mentioned classes, in particular JavaLanguage/JavaLanguageModule in the plugin itself.
However, when the plugin calls into PMD, which itself then uses the ServiceLoader to look for the Services (JavaLanguage) nothing is
found. 

So either it does not see these classes in the classloader at runtime or somehow the META-INF/services/... stuff disappeared.. ? 

Is there a special thing needed so that the dependencies of the plugin are available during the plugins runtime? 
Or is something broken in regard to classloaders? 

You can test/reproduce this by checking out the project and change to the sbt-pmd-tester, then do a  
sbt pmd 

Thanks for your help.

Dominik 

eugene yokota

unread,
Sep 16, 2015, 2:22:54 PM9/16/15
to sbt-dev
http://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html
There are two variants of the load method. One that takes a Classloader argument,
and the other that guesses from the tread. Maybe try passing one specifically from getClass.getClassloader?

-eugene

Dominik

unread,
Jun 2, 2018, 7:42:11 AM6/2/18
to sbt-dev
for everyone stumbling on this post:

In the end, I didn't use a "real" SBT plugin, but just created some files in my project itself.
See this gist for details on how to set it up in your project (or use the plugin of someone else)

https://gist.github.com/domdorn/040186480d516f2a51c59a84052cff12

Cheers,
Dominik
Reply all
Reply to author
Forward
0 new messages