Difference between SPI and API?
Asked Answered
C

9

371

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?

Clair answered 2/6, 2010 at 1:2 Comment(0)
R
464
  • 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.

Usually API and SPI are separate. 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.

Sometimes they overlap, however. The Connection interface 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.

Responsive answered 2/6, 2010 at 10:30 Comment(7)
sounds about right. its just that the lines between SPI & API can be a little grey as most API has abstract classes/interfaces for its user to implement to get things done as well...Clair
@koss: most API? I know what you mean, but I don't see those things a lot.Responsive
API is more relevent to developers while SPI is to vendors.Dealings
@AzfarNiaz: well, since vendors employ developers to build their products both are relevant to developers ;-)Responsive
In Java, are annotations part of an SPI? For example, if I have to add @SomeAnnotation to my class to get it picked up by some framework, would this annotation class SomeAnnotation.class be considered part of the SPI, even though I am not technically extending or implementing it?Aronarondel
@Kidburla I'd say that in most cases this is part of the API, since it's something you use to achieve a programming goal. Unless it's intended to facilitate implementers of an SPI, but then it would expect the annotation somewhere in the package structure of the SPI (typically SPI types are contained in a package .spi. One other case I can think of is when an SPI type is annotated because this annotation is used in the internals of the component/app that the SPI is for. You can see an SPI as an extension/plugin point that allows swappable implementations for (part of) the component.Quinate
Why the difference? To a nōn-Java™ experienced programmer, both is just API.Lalapalooza
H
72

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();
    }
}
Harber answered 2/6, 2010 at 10:54 Comment(1)
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 & spi so i won't put a tick here... ;-)Clair
C
29

The difference between API and SPI comes when an API additionally provides some concrete implementations. In that case, the service provider has to implement a few APIs (called SPI)

An example is JNDI:

JNDI provides interfaces & some classes for context lookup. The default way to lookup a context is provided in IntialContext. This class internally will use SPI interfaces (using NamingManager) for provider specific implementations.

See the JNDI Architecture below for better understanding.

Enter image description here

Coarse answered 6/7, 2013 at 11:10 Comment(0)
K
27

API stands for Application Programming Interface, where API is a means for accessing a service / function provided by some kind of software or a platform.

SPI stands for Service Provider Interface, where SPI is way to inject, extend or alter the behavior for software or a platform.

API is normally target for clients to access a service and it has the following properties:

-->API is a programmatic way of accessing a service to achieve a certain behavior or output

-->From API evolution point of view, addition is no problem at all for clients

-->But API's once utilized by clients it can not (and should not) be altered / deleted unless there are an appropriate communications, since its a complete degradation of the client expectation

SPI on the other part are targeted for providers and has the following properties:

-->SPI is a way to extend / alter the behavior of a software or a platform (programmable vs. programmatic)

-->SPI evolution is different from API evolution, in SPI removal is not an issue

-->Addition of SPI interfaces will cause problems and may break existing implementations

For more explanation click here : Service Provider Interface

Knowledge answered 12/11, 2013 at 13:25 Comment(0)
L
15

NetBeans' FAQ: What is an SPI? How is it different from an API?

API is a general term - an acronym for Application Programming Interface - it means something (in Java, usually some Java classes) a piece of software exposes, which allows other software to communicate with it.

SPI stands for Service Provider Interface. It is a subset of all things that can be API specific to situations where a library is providing classes which are called by the application (or API library), and which typically change the things the application is able to do.

The classic example is JavaMail. Its API has two sides:

  • The API side — which you call if you are writing a mail client or want to read a mailbox
  • The SPI side if you are providing a wire-protocol handler to allow JavaMail to talk to a new kind of server, such as a news or IMAP server

Users of the API rarely need to see or talk to the SPI classes, and vice-versa.

In NetBeans, when you see the term SPI, it is usually talking about classes that a module can inject at runtime which allow NetBeans to do new things. For example, there is a general SPI for implementing version control systems. Different modules provide implementations of that SPI for CVS, Subversion, Mercurial and other revision control systems. However, the code that deals with files (the API side) does not need to care if there is a version control system, or what it is.

Louisalouisburg answered 23/7, 2011 at 15:22 Comment(0)
L
13

There is one aspect which doesn't seem to be highlighted much but is very important to understand why and when to use API/SPI.

API/SPI split is only required when you actually write a platform that has at least one third-party client. If you're not writing platform and have all the API consumer code under control, the only benefit will be good & clean object design as you can refactor it any time.

But once you have at least one third-party client of your platform and you want to do changes in backward compatible way, you should most probably use API/SPI split.

Lets show it on one of the well known Java objects Collection and Collections.


API: Collections is a set of utility static methods. Often classes representing API object are defined as final as it ensures (at compilation time) that no client can ever "implement" that object and they can depend on "calling" its static methods, e.g.

Collections.emptySet();

Since all clients are "calling" but not "implementing", authors of JDK are free to add new methods into the Collections object in the future version of JDK. They can be sure it can't break any client, even if there are probably milions of usages.


SPI: Collection is an interface which implies that anyone can implement her own version of it. Thus, authors of JDK can't add new methods into it as it would break all clients who wrote their own Collection implementation (*).

Typically when additional method is required to be added, new interface, e.g. Collection2 which extends the former one needs to be created. SPI client then can decide whether to migrate to the new version of SPI and implement it's additional method or whether to stick with the older one.


You might already seen the point. If you combine both pieces together into a single class, your API is blocked from any additions. That's also the reason why good Java APIs and Frameworks don't expose abstract class as they would block their future evolution with respect to the backward compatibility.

If something is still unclear, I recommend to check this page which explains the above in more detail.


(*) Note this is true only until Java 1.8 which introduces concept of default methods defined in an interface.

Laplante answered 2/11, 2017 at 23:14 Comment(0)
C
4

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.

Cytology answered 2/6, 2010 at 1:8 Comment(2)
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.Clair
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.Cytology
C
4

Service provider interface is the service interface which all providers must implement. If none of the existing provider implementations work for you, you need to write your own service provider (implementing the service interface) and register somewhere (see the useful post by Roman).

If you're reusing the existing provider implementation of the service interface, you're basically using the API of that particular provider, which include all the methods of service interface plus a few public methods of its own. If you're using methods of provider API outside the SPI, you're using provider specific features.

Cutpurse answered 26/7, 2011 at 14:47 Comment(0)
P
3

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.

Pibgorn answered 2/6, 2010 at 7:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.