Java Service Provider Interface (SPI)

You are viewing an old version (v. 3) of this page.
The latest version is v. 7, last edited on Jun 29, 2011 (view differences | )
<< View previous version | view page history | view next version >>

Introduction

When we use an approach service based we have to deal with interfaces (i.e. contracts), factories and implementations. We need a mechanism to discovery the right implementation for specific service. A commons solution is to use a system property that contain the full qualified name (FQN) of the implementation class and then the factory will use this to instantiate the implementation. Service Provider Interface allow us to use a standard technique to discovery a right implementation on a desired interface (i.e. contract )

SPI

This technique consist of put a file, whose name is contract's name , within jar under path META-INF/services. For example if the interface is org.bsc.spi.MyContract into the jar the file will be:

META-INF/services/org.bsc.spi.MyContract

and within this file must be put just one line containing the FQN of the implementation.

At this point the steps to create a SPI application will be:

  1. create a contract (i.e. project containing interface)
  2. create a provider that implements the contract and publish implementation through SPI service
  3. create a factory (consumer) that discovery implementation and return the instance

Java Example

Create a contract


package org.bsc.spi;

public interface MyContract
{

    String test();
}

Create a provider

public class MyProvider implements MyContract
{

    public String test() {
        return "hello world!";
    }
}
@MetaInfServices
public class MyProvider implements MyContract
{

    public String test() {
        return "hello world!";
    }
}
pom fragment
  <repositories>
      <repository>
          <id>java.net</id>
          <url>http://download.java.net/maven/2/</url>
      </repository>
  </repositories>
  <dependencies>

    <dependency>
      <groupId>org.kohsuke.metainf-services</groupId>
      <artifactId>metainf-services</artifactId>
      <version>1.1</version>
      <optional>true</optional>
      <type>jar</type>
    </dependency>

Create a Factory


public class MyContractFactory {


   public static MyContract createInstance() throws Exception {
        
        java.io.InputStream is = Consumer.class.getClassLoader().getResourceAsStream("META-INF/services/org.bsc.spi.MyContract");

        java.io.LineNumberReader r = new LineNumberReader( new java.io.InputStreamReader(is));

        String fqn = r.readLine();

        return Class.forName(fqn).newInsance();
   }

}

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.