Open In App

Java Mdoules – Service Implementation Module

Last Updated : 17 Jul, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

SPI(Service Provider Interface) is an API. It can be customizable by a third-party provider. We can change the existing implementation or extendable. In this, a Service is an extension of the set of interfaces containing different methods, and Service Provider is an implementation of the service. General features are given in the service via Classes. A Service Provider when it is created will provide a feature to customize the provider according to the requirements. The main advantage of the service provider is it will  not change the original code base but it will provide the additional functionalities to extend the code base

Installation of Service Providers is done in two ways:

  1. As plug-ins in the form of a JAR file and can copy to the classpath on the application. This is called local installation.
  2. As a plug-in in the form of a JAR file and copy the JAR file JRE/lib/ext folder in the JAVA_HOME path. This way of installation is a global installation.

Loading Service Providers

This is a very important step. JDK needs to be known about the availability of service providers. A new file under  META-INF/services folder in the application classpath has to be created for this. META-INF/services folder filename should be the fully qualified binary name of the service, in that we need to specify all the valid list of fully qualified binary names of service provider classes.

Service Loader

This is the main part of the Service Provider Interface.  It has the responsibility of discovering the loading of the SPI implementations lazily. It is used to scan the application classpath to discover the provider implementations and maintained in a cache.

Examples of SPI

java.util.spi.ConcurrencyNameProvider Provides the localized currency symbols for Currency
java.util.spi.LocaleNameProvider Provides the localized names for Locale.
java.util.spi.TimeZoneNameProvider Provides the localized timeZone for Timezone.
java.text.spi.DateFormatProvider Provides date and time formats for a specified locale
java.text.spi.NumberFormatProvider Provides monetary, integer, and percentage values for the NumberFormat class

Let us see a small example of building a customized Service Provider

Example Project

Project Structure:

Project Structure

 

It is a maven-based project. Let’s start with pom.xml

pom.xml

XML




         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  
  <groupId>org.gfg</groupId>
  <artifactId>Sample-Account-api</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
  
  <name>Sample-Account-api</name>
  <url>http://maven.apache.org</url>
  
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  
  <build>
      <plugins>
          <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.0</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      </plugins>
  </build>
</project>


Let us start by seeing the service interface first.

AccountInterface.java

Java




public interface AccountInterface {
    public String getAccountType(String accountType);
    public int getAccountId(int accountId);
}


We can add methods matching business requirements. As of now, 2 methods are given for simplicity. Implement the methods now via

AccountServiceProvider.java

Java




import org.gfg.spi.AccountInterface;
  
public class AccountServiceProvider implements AccountInterface{
    @Override
    public String getAccountType(String accountType) {
        // can do any business logic here
        return " Your account type is " + accountType;  
    }
    @Override
    public int getAccountId(int accountId) {
        return accountId;
    }
}


Let’s create the main method via the App.java file

App.java

Java




import java.util.Iterator;
import java.util.ServiceLoader;
import org.gfg.spi.AccountInterface;
  
public class App 
{
    public static void main( String[] args )
    {
        ServiceLoader<AccountInterface> loader =ServiceLoader.load(AccountInterface.class);
        Iterator<AccountInterface> iter = loader.iterator();
        while(iter.hasNext()){
            AccountInterface account = iter.next();
            System.out.println(account.getAccountType("Savings"));
            System.out.println(account.getAccountId(1000));
        }
    }
}


Very important and essential step:

Under the resources folder, we need to create META-INF/services folder. A file named “org.gfg.spi.AccountInterface” has to be created and it should have content as

org.gfg.spi.providers.AccountServiceProvider

We have to give it correctly. Otherwise, the program will not execute correctly. Now run App.java. We can see the below output

 

Conclusion

  1. Service provider framework is an easy way to decouple.
  2. It can load multiple service implementations of the given Service Interface. 
  3. The very essential and important step is that all Service Provider classes must be in the META-INF/services folder with the fully qualified name of the Service Interface.


Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads