Locating services that matter

Lee Chuk-Munn discusses one seemingly trivial question: How do you find all implementations of a given interface at runtime?

How do you find all implementations of a given interface at runtime? This seemingly trivial question has some real implications in day-to-day Java development.

Imagine, for example, you have developed a word processor and you wish to allow other developers to extend the functionalities of your word processor by implementing an interface called WordProcessorFunction. Once the developer has implemented the interface, the question remains: How does the word processor know which class implements the WordProcessorFunction interface?

One solution is to specify the implementation either in a property or a property file. JDBC took the former approach while Java Cryptographic Architecture (JCA) used the latter. However, the problem with this solution is that the burden of configuring the runtime environment is placed on the user.

If you are using Apache's Derby database, for example, you have to configure the jdbc.drivers property with the appropriate Driver implementation so that the DriverManager can load the correct driver when we are creating a Derby database connection. The user should not need to know this level of detail in order to use a JDBC driver. An ideal solution would be to allow the JDK runtime to automagically discover all implementations of Driver.

Service provider
The service provider interface allows developers to specify implementations of a particular interface packaged in a JAR file. The service provider interface has been around since JDK 1.3 days. Here is how you use this feature. Using our WordProcessorFunction interface as an example, this is what you do:

1. Create a directory called META-INF/services

2. In services, create a text file from the fully qualified name (FQN) of the interface. For example if the FQN of WordProcessorFunction is org.wordprocessor.WordProcessorFunction, the name of this text file will be org.wordprocessor.WordProcessorFunction

3. List all implementations of the interface, in FQN, in this text file. So if your JAR has two implementations of WordProcessorFunction, list them like so:




The only requirement is that the implementations must have a zero argument constructor.

4. Jar the implementations, including any supporting or utility classes, and META-INF directory into a JAR file.

Once you have created the JAR file, place the JAR file in the CLASSPATH of your application.

Service lookup
Prior to JDK 6, there was no lookup mechanism; some application platforms like NetBeans roll their own lookups. The ServiceLoader is a utility class that looks up all implementation to a given interface; it is part of JavaSE 6. ServiceLoader will scan all JARs in its CLASSPATH and return an Iterator to all the implementations that it has found. By using the service provider interface, the responsibility of ensuring that the appropriate implementations found during runtime have shifted from the user to the developer. All the user has to do is to set the JAR file to its runtime CLASSPATH

Assuming that we are going to look up our WordProcessorFunction implementation, here is an example of the code snippet:

// Lookup all implementation of WordProcessorFunction

ServiceLoader loader = ServiceLoader.load(WordProcessorFunction.class);

// Iterate all implementations Iterator functions = loader.iterator();

for (WordProcessorFunction func: functions) {

  //Do something with them

Some of the features in JavaSE 6 like scripting and JDBC have begun to use this mechanism to look up JDBC drivers and scripting engines.

Lee Chuk-Munn has been programming in the Java language since 1996, when he first joined Sun Microsystems in Hong Kong. He currently works as a senior developer consultant and technology evangelist for Technology Outreach at Sun in Singapore. Chuk's focus is in Java APIs, Java EE, Java SE, and Java ME. Chuk graduated in 1987 from the Royal Melbourne Institute of Technology in Melbourne, Australia, where his favorite subject was compiler theory.