Wednesday, September 30, 2015

Service Provider Interface: Creating Extensible Java Applications



https://en.wikipedia.org/wiki/Service_provider_interface
Service Provider Interface (SPI) is an API intended to be implemented or extended by a third party. It can be used to enable framework extension and replaceable components.
Creating Extensible Applications
An extensible application is one that you can extend without modifying its original code base. You can enhance its functionality with new plug-ins or modules. Developers, software vendors, and customers can add new functionality or application programming interfaces (APIs) by adding a new Java Archive (JAR) file onto the application class path or into an application-specific extension directory.
Service
A set of programming interfaces and classes that provide access to some specific application functionality or feature. The service can define the interfaces for the functionality and a way to retrieve an implementation. In the word-processor example, a dictionary service can define a way to retrieve a dictionary and the definition of a word, but it does not implement the underlying feature set. Instead, it relies on a service provider to implement that functionality.
Service provider interface (SPI)
The set of public interfaces and abstract classes that a service defines. The SPI defines the classes and methods available to your application.
Service Provider
Implements the SPI. An application with extensible services enable you, vendors, and customers to add service providers without modifying the original application.
2. Define the Service That Retrieves the Service Provider Implementations
public class DictionaryService {

    private static DictionaryService service;
    private ServiceLoader<Dictionary> loader;

    private DictionaryService() {
        loader = ServiceLoader.load(Dictionary.class);
    }

    public static synchronized DictionaryService getInstance() {
        if (service == null) {
            service = new DictionaryService();
        }
        return service;
    }


    public String getDefinition(String word) {
        String definition = null;

        try {
            Iterator<Dictionary> dictionaries = loader.iterator();
            while (definition == null && dictionaries.hasNext()) {
                Dictionary d = dictionaries.next();
                definition = d.getDefinition(word);
            }
        } catch (ServiceConfigurationError serviceError) {
            definition = null;
            serviceError.printStackTrace();

        }
        return definition;
    }
}

To register your service provider, you create a provider configuration file, which is stored in the META-INF/services directory of the service provider's JAR file. The name of the configuration file is the fully qualified class name of the service provider, in which each component of the name is separated by a period (.), and nested classes are separated by a dollar sign ($).
The provider configuration file contains the fully qualified class names of your service providers, one name per line. The file must be UTF-8 encoded. Additionally, you can include comments in the file by beginning the comment line with the number sign (#).
For example, to register the service provider GeneralDictionary create a text file named dictionary.spi.Dictionary . This file contains one line:
dictionary.GeneralDictionary

Installed Extensions
Installed extensions are JAR files in the lib/ext directory of the Java Runtime Environment (JRE™) software.
any JAR file in the lib/ext of the JRE directory is automatically treated by the runtime environment as an extension.
Since installed extensions extend the platform's core API, use them judiciously. They are rarely appropriate for interfaces used by a single, or small set of applications.

  • 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
The java.util.spi package in JDK 1.6 defines some examples of a SPI:
A service provider implements the SPI and contains one or more concrete classes that implement or extend (subclass) the service type. A single SPI specification can have more than one provider. To promote loose coupling and information hiding, the provider class is typically not the entire provider itself but rather a proxy that contains enough functionality to decide whether the provider is able to satisfy a particular request.
You can install service providers by simply adding a new Java Archive (JAR) file that holds the provider classes to the application's classpath or by placing the JAR into any of the usual extension directories (jre/lib/ext).
You identify a service provider by placing a provider-configuration file in the resource directory META-INF/services. The file's name is the fully qualified binary name of the service's type. The file contains a list of fully qualified binary names of concrete provider classes, one per line.
ServiceLoader  maintains a cache of the providers that have been loaded. The only requirement this facility enforces is that every provider class must have a zero-argument constructor, so that it can be instantiated during loading. Providers are located and instantiated on demand.

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.
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
http://blog.jooq.org/2015/05/21/do-not-make-this-mistake-when-developing-an-spi/
https://weblogs.java.net/blog/2008/08/11/capability-pattern-future-proof-your-apis
http://harisankar-krishnaswamy.blogspot.com/2012/05/java-design-pattern-service-provider.html

https://dzone.com/articles/lightweight-application-development

http://cristian.sulea.net/blog.php?p=2015-08-07-api-vs-spi
http://mussabsharif.blogspot.ro/2011/08/api-vs-spi.html
API stands for Application Programming Interface, and is a mean for accessing a service/function provided by some kind of software or a platform. API is normally target for clients to access a service and its 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 stands for Service Provider Interface, and is way to inject, extend or alter the behavior for software or a platform. SPI is 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 that SPI evolution, in SPI removal is not an issue.
  • Addition of SPI interfaces will cause problems and may break existing implementations.
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. So:
  • the API is the description of classes/interfaces/methods/... that you call and use to achieve a goal
  • the SPI is the description of classes/interfaces/methods/... that you extend and implement to achieve a goal
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.



Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts