I am very new to Java (coming from C# .NET background). Trying to create an "expansion/IoC" style architecture via a combination of Google Guice and ServiceLoader, but can't seem to get the ServiceLoader part working running Java 1.7.0_75 and IntelliJ IDEA 14.
I have a module within my project which is effectively a base class library called ViProJ.Bcl that contains an interface called com.vipro.bcl.SimplePluginLoader.
I have another module called ViProJ.TestModules which contains a single implementation of SimpleModuleLoader called com.vipro.test.TestModule1.
Within my src folder is a resources folder (marked as a resource within the module settings screen) that contains a folder called META-INF.services that contains a single file called com.vipro.bcl.SimpleModuleLoader. The value within this file is com.vipro.test.TestModule1.
I have two artefacts being created (into same directory) by IntelliJ, the first is a module with a Main function that runs from the command line. It loads service loader like so:
ServiceLoader<SimpleModuleLoader> loader = ServiceLoader.load(SimpleModuleLoader.class);
The other is the aforementioned test library. When I debug this, the service loader contains no classes, so the exporting of the class has not worked.
When I open the jar file in 7zip, I can see META-INF\services\com.vipro.bcl.SimpleModuleLoader so IntelliJ has correctly packaged these files up.
The MANIFEST.MF file looks like this:
Manifest-Version: 1.0
Export-Package: com.google.inject.name;version="1.3",com.google.inject
.binder;version="1.3",com.google.inject.spi;version="1.3",com.google.
inject.matcher;version="1.3",com.google.inject.util;version="1.3",com
.google.inject;version="1.3"
Bundle-Name: guice
Created-By: 1.6.0_23 (Sun Microsystems Inc.)
Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6
Bundle-Copyright: Copyright (C) 2006 Google Inc.
Ant-Version: Apache Ant 1.7.1
Bundle-Vendor: Google, Inc.
Bundle-Version: 3.0
Bundle-ManifestVersion: 2
Bundle-Description: Guice is a lightweight dependency injection framew
ork for Java 5 and above
Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
Bundle-SymbolicName: com.google.inject
Import-Package: javax.inject,org.aopalliance.intercept
Bundle-DocURL: http://code.google.com/p/google-guice/
Not really sure why the manifest is talking about Guice and not my module? Probably not causing this to fail though? Can anyone tell me why this isn't working? I'm sure I haven't given you everything you need, but not really sure what else I should include here?
The modules Module
is using an .impl file for building instead of a pom.xml (Maven), this is what that looks like:
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/resources" type="java-resource" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="ViProJ.Bcl" />
<orderEntry type="library" name="guice-3.0" level="project" />
<orderEntry type="library" name="guice-multibindings-3.0" level="project" />
</component>
</module>
My injection code uses a MultiBinder, like this:
// dynamic modules via service loader
Multibinder<IModule> modBinder = Multibinder.newSetBinder(binder(), IModule.class);
ServiceLoader<SimpleModuleLoader> loader = ServiceLoader.load(SimpleModuleLoader.class);
for (SimpleModuleLoader moduleLoader : loader) {
for (Class<? extends IModule> moduleClass : moduleLoader.getModules()) {
System.out.print("Found expansion module");
modBinder.addBinding().to(moduleClass);
}
}
pom.xml
file? Is your intention that you will use ServiceLoader to find modules and use those modules to build an Injector? Have you seen the example of Using Multibindings to host Plugins in the Guice documentation? – DifferentMANIFEST.MF
file and the difficulty making ServiceLoader work indicate that the problem likely lies with your build system, not with your code. Basically, can you create an MVCE that doesn't use Guice at all? – Different