Java Service Provider Interface

Technology:

Service Provider Interface is an API proposed to be implemented or customized by a third-party provider. It can use as an extension or replaceable by existing implementations.

A Service is an extension of the set of interfaces, and Service Provider is an implementation of the service. Classes in the provider category will generally implement the service interface or expand the classes provided in the service. A Service Provider will provide a feature to customize the provider according to the requirements. Service Provider provides the feature to extend the service without modifying the original code base.

Installing Service Providers:

We can install service providers in two ways.

  • These providers can be installed as plug-ins in the form of a JAR file and can copy to the classpath on the application, which means that service provider installation to provide the application to the local.
  • These providers can be installed as plug-ins in the form of a JAR file and copy the JAR file JRE/lib/ext folder in the JAVA_HOME path so that it will install on all the applications that this JDK is using, it is called global installation.

Loading Service providers:

After placing the service provider JAR, we need to inform JDK about the availability of the service provider, by creating the new file under META-INF/services folder in the application classpath.

The file name should be the fully qualified binary name of the service, and it will contain a list of fully qualified binary names of service provider classes.

Service Loader:

The main part of the Service Provider Interface is ServiceLoader class, which has the responsibility of discovering the loading the SPI implementations lazily, it used to scan the application classpath to discover the provider implementations and maintains 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.

These providers can extend or replaced if we the JDK implementation is not suitable for requirements.

Building Custom Service Provider:

We start by creating maven project called hello-world-api.

Then create Service interface named HelloWorldService, that has to be implemented.

package org.sravan.spi; public interface HelloWorldService { public void sayHello(); }

Lets create a main class for finding the service provider and execute the sayHello() method

package org.sravan; import java.util.Iterator; import java.util.ServiceLoader; import org.sravan.spi.HelloWorldService; public class App { public static void main( String[] args ) { ServiceLoader<HelloWorldService> loader =ServiceLoader.load(HelloWorldService.class); Iterator<HelloWorldService> iter = loader.iterator(); while(iter.hasNext()){ iter.next().sayHello(); } } }

If we run the App.java then it will produce any output.

Let’s create the HelloWorldService providers.

package org.sravan.spi.providers; import org.sravan.spi.HelloWorldService; public class HelloServiceProvider implements HelloWorldService{ @Override public void sayHello() { System.out.println("Hello World"); } }

And if we run the App class then also produce the empty output as we are not specified the availability service provider.

Let’s create META-INF/services folder inside the src/main/resources folder.

Create a file named “org.sravan.spi.HelloWorldService” and add the below content into it.

org.sravan.spi.providers.HelloServiceProvider

Now if we run the App class files, then we can see the “Hello World” output same as the service provider returning.

Now let’s package this service Provider as JAR, by doing maven install.

Now let's create an extended version of HelloworldService Provider.

Create a new maven project named “hello-world-extended-api” and add the above project dependencies like below:

<dependency> <groupId>org.sravan</groupId> <artifactId>hello-world-api</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>

Create a new ExtendedHelloWorldServiceProvider that implements HelloWorldService interface.

package org.sravan.extended.providers; import org.sravan.spi.HelloWorldService; public class ExtendedHelloWorldServiceProvider implements HelloWorldService { @Override public void sayHello() { System.out.println("Hello World exteded"); } }

Let’s create META-INF/services folder inside the src/main/resources folder.

Create a file named “org.sravan.spi.HelloWorldService” and add the below content into it.

org.sravan.extended.providers.ExtendedHelloWorldServiceProvider

Now if we execute the App class again, we observe the output from both Service Providers.

ServiceLoader has overloaded method to load only the extended service provider using classloader.

ServiceLoader<S> load (Class<S> service,ClassLoader loader), we can write the custom classloader to load the classes from package.

Conclusion:

Java Web Development Company describe Service provider framework provides an easy way to decouple and load multiple service implementation of the given Service Interface. It is important to note that all Service Provider classes must be in the META-INF/services folder with the fully qualified name of the Service Interface.

Click here for Java-SPI-Example source code.

Read more: