tags:

views:

192

answers:

4

What is the difference between Service Provider Interface (SPI) and Application Programming Interface (API)?

More specifically, for Java libraries, what makes them an API and/or SPI?

+2  A: 

I suppose an SPI slots into a larger system by implementing certain features of an API, and then registering itself as being available via service lookup mechanisms. An API is used by the end-user application code directly, but may integrate SPI components. It's the difference between encapsulation and direct usage.

Chris Dennett
thanks for the response chris. any examples of existing Java (i.e. Servlet, JDBC, etc) libraries? ...like how it makes them API/SPI. can be hard to visualize the difference with description alone.
koss
An API is JDBC, an SPI for JDBC is the database connector interface which SPI developers can use to create new database connectors which the developer can select for usage.
Chris Dennett
A: 

In the Java world, different technologies are meant to be modular and "pluggable" into an application server. There is then a difference between

  • the application server
    • [SPI]
  • the pluggable technology
    • [API]
  • the end user application

Two examples of such technologies are JTA (the transaction manager) and JCA (adapter for JMS or database). But there are others.

Implementer of such a pluggable technology must then implement the SPI to be pluggable in the app. server and provide an API to be used by the end-user application. An example from JCA is the ManagedConnection interface which is part of the SPI, and the Connection that is part of the end-user API.

ewernli
+3  A: 
  • the API is the description of classes/interfaces/methods/... that you call and use to achieve a goal and
  • the SPI is the description of classes/interfaces/methods/... that you extend and implement to achieve a goal

Put differently, the API tells you what a specific class/method does for you and the SPI tells you what you must do to conform.

Sometimes SPI and API overlap. For example in JDBC the Driver class is part of the SPI: If you simply want to use JDBC, you don't need to use it directly, but everyone who implements a JDBC driver must implement that class.

The Connection interface on the other hand is both SPI and API: You use it routinely when you use a JDBC driver and it needs to be implemented by the developer of the JDBC driver.

Joachim Sauer
koss
@koss: most API? I know what you mean, but I don't see those things a lot.
Joachim Sauer
+1  A: 

From Effective Java 2nd Edition:

A service provider framework is a system in which multiple service providers implement a service, and the system makes the implementations available to its clients, decoupling them from the implementations.

There are three essential components of a service provider framework: a service interface, which providers implement; a provider registration API, which the system uses to register implementations, giving clients access to them; and a service access API, which clients use to obtain an instance of the service. The service access API typically allows but does not require the client to specify some criteria for choosing a provider. In the absence of such a specification, the API returns an instance of a default implementation. The service access API is the “flexible static factory” that forms the basis of the service provider framework.

An optional fourth component of a service provider framework is a service provider interface, which providers implement to create instances of their service implementation. In the absence of a service provider interface, implementations are registered by class name and instantiated reflectively (Item 53). In the case of JDBC, Connection plays the part of the service interface, DriverManager.registerDriver is the provider registration API, DriverManager.getConnection is the service access API, and Driver is the service provider interface.

There are numerous variants of the service provider framework pattern. For example, the service access API can return a richer service interface than the one required of the provider, using the Adapter pattern [Gamma95, p. 139]. Here is a simple implementation with a service provider interface and a default provider:

// Service provider framework sketch

// Service interface
public interface Service {
    ... // Service-specific methods go here
}

// Service provider interface
public interface Provider {
    Service newService();
}

// Noninstantiable class for service registration and access
public class Services {
    private Services() { }  // Prevents instantiation (Item 4)

    // Maps service names to services
    private static final Map<String, Provider> providers =
        new ConcurrentHashMap<String, Provider>();
    public static final String DEFAULT_PROVIDER_NAME = "<def>";

    // Provider registration API
    public static void registerDefaultProvider(Provider p) {
        registerProvider(DEFAULT_PROVIDER_NAME, p);
    }
    public static void registerProvider(String name, Provider p){
        providers.put(name, p);
    }

    // Service access API
    public static Service newInstance() {
        return newInstance(DEFAULT_PROVIDER_NAME);
    }
    public static Service newInstance(String name) {
        Provider p = providers.get(name);
        if (p == null)
            throw new IllegalArgumentException(
                "No provider registered with name: " + name);
        return p.newService();
    }
}
Roman
thanks for the very nice description on service provider framework. this will be useful to know. however, it does not clearly describe "difference" between api -)
koss