Difference between SPI and API?

Java

Java Problem Overview


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?

Java Solutions


Solution 1 - Java

  • 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.

Solution 2 - Java

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();
    }
}

Solution 3 - Java

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

Solution 4 - Java

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

Solution 5 - Java

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.

Solution 6 - Java

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 and it is expected to evolve. If you write an API and "know" it won't require any future backward compatible improvements ever, there is no real reasons for splitting your code into the two parts. Also if you're not writing platform at all (you have all the API consumer code under control), the only benefit will be good & clean object design as you can refactor however you need 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.

Solution 7 - Java

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.

Solution 8 - Java

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.

Solution 9 - Java

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkctangView Question on Stackoverflow
Solution 1 - JavaJoachim SauerView Answer on Stackoverflow
Solution 2 - JavaRomanView Answer on Stackoverflow
Solution 3 - JavaSandeep JindalView Answer on Stackoverflow
Solution 4 - JavaVenkata Aditya PavanView Answer on Stackoverflow
Solution 5 - JavaOndra ŽižkaView Answer on Stackoverflow
Solution 6 - JavaMartin JaníčekView Answer on Stackoverflow
Solution 7 - JavaChris DennettView Answer on Stackoverflow
Solution 8 - JavatapasviView Answer on Stackoverflow
Solution 9 - JavaewernliView Answer on Stackoverflow