August 31, 2009

Powered by Service Provider Interface

In my previous post I used an annotation processor to enrich the usage of annotations. I stated that to configure an annotation processor you should use a compiler time parameter. In Java 6 you can do more. You have Service Provider Interface API which lets you configure the same processor in a more elegant manner. But what is SPI (Service Provider Interface)?

Brief on SPI

The official java doc is here. A service is an interface or abstract class which defines a contract for a specific functionality. A service provider is an implementation of that service. Java 6 provides a loader for services based on a provider-configuration file. Just as simple.

Steps to put on jobs
  1. You define an interface or use an existing one which defines the contract of your service.
  2. You define and implement one or more implementing classes. This classes should have an empty constructor, that is the only requirement.
  3. You create META-INF/services folder in you jar archive. In that folder you create a file named with the canonical class name of the interface. (as a sample: your.packages.MyInterface). That is the provider-configuration file.
  4. In the new created file you insert the canonical names of the implementing classes. These classes are the service providers. If you have more implementations, you put them on separate lines. The syntax of this file is the syntax of properties file (put comments prefixed with # for clarity).
That's all. The runtime will parse the provider-configuration files and provides service loaders for these services, which you can use.

What are the usages?

Insert providers for existent services

JDK provides some usefull SPIs already, which you can use them. Going back to the beggining of my article, the java annotation processor is such a SPI service. So, in place of putting "-processor org.aap.processor.AAPProcessor" as a compiler option, we can skip that. Instead, we create META-INF/services folder. In that folder we create a file called "javax.annotation.processing.Processor". In that provider-configuration file we put "org.aap.processor.AAPProcessor". Now it works. For the article go here. Simply by providing this, the runtime at the moment of loading the jar library, will parse providers and use them. Nice and clean.

Obviously we can provide implementation services for other SPIs as well. I mention here just a few like: LoginModule for authentication, sound sample API or better here, java text spi API (by the way, nice feature), and others.

Usage of service providers in an Observer Pattern manner
Implement your own interface for observable (eventually by extending java.util.Observer). Don't need to handle yourself contributions, service loader is here for that. And can handle contributions from the whole class path.

Usage of service providers in a Factory pattern manner
Implement an interface with a getter to discriminate between implementations. On execution time, use service loader to iterate through implementations and find which provider to use.

Conclusion
That's only a starting point for service provider. I found a nice feature brought by Java 6. In fact not only nice, but almost fabulous. An option to extending platform.

No comments:

Post a Comment