Fork me on GitHub

Starting with version 0.12 PF4J comes with a better support for ServiceLoader. PF4J can read META-INF/services (Java Service Provider mechanism) as extensions, so, if you have a modular application based on java.util.ServiceLoader class you can replace entirely the ServiceLoader.load() calls from your application with PluginManager.getExtensions() and migrate smooth from ServiceLoader to PF4J.

Also you have the possibility to change the ExtensionStorage used in ExtensionAnnotationProcessor. By default we use the format with META-INF/extensions.idx:

org.pf4j.demo.HowdyGreeting
org.pf4j.demo.WhazzupGreeting

but you can use a more standard location and format, META-INF/services/<extension-point>, used by Java Service Provider (see java.util.ServiceLoader) via ServiceProviderExtensionStorage implementation. In this case the format of META-INF/services/org.pf4j.demo.api.Greeting is:

# Generated by PF4J
org.pf4j.demo.HowdyGreeting
org.pf4j.demo.WhazzupGreeting # pf4j extension

where the org.pf4j.demo.HowdyGreeting entry is legacy (it’s not generated by PF4J) but it’s seen as an extension of Greeting by PF4J (at runtime).

You can plug your custom ExtensionStorage implementation in ExtensionAnnotationProcessor in two possible modes:

  • set the annotation procesor option with key pf4j.storageClassName
  • set the system property with key pf4j.storageClassName

For example if I want to use ServiceProviderExtensionStorage then the value for the pf4j.storageClassName key must be org.pf4j.processor.ServiceProviderExtensionStorage

NOTE: ServiceLoaderExtensionFinder, the class that lookups for extensions stored in META-INF/services folder, is not added/enabled by default. To do this please override createExtensionFinder from DefaultPluginManager:

protected ExtensionFinder createExtensionFinder() {
    DefaultExtensionFinder extensionFinder = super.createExtensionFinder();
    extensionFinder.addServiceProviderExtensionFinder();

    return extensionFinder;
}