How to include a config file in the "META-INF/services" folder of a JAR using Maven
Create a new source folder with the location src/main/resources
, then create your META-INF/services
folder in there and drop in your fully-qualified class name (FQCN) file. This should copy them into the jar file automatically. So for implementations of an interface with a FQCN of com.acme.MyInterface
, you'll have:
Project
| src
| | main
| | java
| | [your source code]
| | resources
| | META-INF
| | services
| | com.acme.MyInterface
Note that com.acme.MyInterface
is the name of the file, not a directory structure like a Java package. The name of the file is the FQCN of the interface that you're implementing, and in it, you'll have the FQCN of each implementation on its own line, e.g.:
com.example.MyInterfaceImpl
com.example.AnotherMyInterfaceImpl
It's worth noting that this applies to Gradle projects with the default source sets as well.
Once you do this, you can load all the implementations of the interface using ServiceLoader
:
ServiceLoader<MyInterface> loader = ServiceLoader.load(MyInterface.class);
for (MyInterface service : loader) {
// Prints com.example.MyInterfaceImpl and com.example.AnotherMyInterfaceImpl
System.out.println(service.class.getName());
}
Some things to note:
- All the implementations must have a no-args constructor
- Applications that use modules or custom classloaders may have to use the overloads of
ServiceLoader.load
If these conditions won't work for you, then you may want to switch to another system, e.g. a CDI-style framework like Spring, EJB, etc.
By default Maven looks for resources at:
src/main/resources
So put it at
src/main/resources/META-INF/services
Alternatively, if your project does not use a standard directory structure (or your simply wish to have alternate resource directories), you can specify resource directories manually the POM file.
For example, if your META-INF/services
is located in a folder called resources
which lies in the root of your project directory, could specify it as follows:
<project>
...
<build>
...
<resources>
<resource>
<directory>resources</directory>
</resource>
</resources>
...
</build>
...
</project>
You can use this to specify several directories by adding multiple <resource>
elements.