HowTo have multiple SPI implementations in one JAR
java
Solution
Just add multiple lines with the fully-qualified provider's class name
So if your SPI is `com.example.Marker`
META-INF/services/com.example.Marker
add each implementation in a new line
com.example.MarkerImplA
com.example.MarkerImplB
com.example.MarkerImplC
For details take a look at the JAR File Specification
Provider-Configuration File
A service provider identifies itself by placing a provider-configuration file in the resource directory META-INF/services. The file's name should consist of the fully-qualified name of the abstract service class. The file should contain a newline-separated list of unique concrete provider-class names. Space and tab characters, as well as blank lines, are ignored. The comment character is '#' (0x23); on each line all characters following the first comment character are ignored. The file must be encoded in UTF-8.
Provider lookup
Use the `ServiceLoader<T>` that was introduced in Java 1.6
ServiceLoader<Marker> markerLoader = ServiceLoader.load(com.example.Marker.class);
for (Marker marker : markerLoader ) {
// select the marker you want or use all
// only for demo
System.out.println(marker);
}
Prior to 1.6 you have to implement the service loader by yourself or use a library. E.g. the apache discovery library's `Service`.
A note about plug-ins
It is possible to have multiple `META-INF/service` provider-configuration files in different deployment units, usually jar archives.
archive1.jar
+- META-INF/services/com.example.Marker
archive2.jar
+- META-INF/services/com.example.Marker
A lookup via the `ServiceLoader<T>` will pick up all implementations in all archives. This is done using `ClassLoader.getResources()`.
Thus you only have to add a jar to the classpath and the provided services can be picked up. That gives you the opportunity to build a plug-in architecture.
This is how spring works. You just add a jar to the classpath and spring features are available, because spring scans for it's service definitions. These definitions are named e.g. `spring.handlers`. Spring handlers are namespace handlers that extend the xml parsing to create `BeanDefinition`s that a `BeanFactory` uses to create spring beans for the `ApplicationContext`. See e.g. spring-tx.
Problem
Assume I have one interface `com.example.Marker` and I do have one implementation of this, eg `com.example.MarkerImplA`. To get one of them registered, I need to place a text file in `META-INF/services/com.example.Marker` looking like this ``` com.example.MarkerImplA ``` This works like a charme. Now, I have another implementation in the same jar file, eg `com.example.MarkerImpl2`. How do I achieve the registration of the second one?