The java.util.ServiceLoader class in Java provides a simple mechanism for discovering and loading implementations of a service interface from the classpath. It is part of the Java Standard Library and is often used in modular or plugin-based applications where different implementations of a service interface may be available.
Here's how ServiceLoader works:
1. Service Provider Interface
First, you define a service interface that represents a contract or API. This interface defines the methods or behaviour that implementations must adhere to.
To demonstrate the example, I defined a log-service project, and it has LogService interface.
LogService.java
package com.sample.app.log.service;
public interface LogService {
void log(String msg);
}
2. Service Provider Implementations
Next, you create one or more implementations of the service interface. These implementations are typically packaged as JAR files and made available in the classpath.
To demonstrate the example, I defined two libraries sdk1, and sdk2 which implement LogService interface.
Example
public class Sdk1Logger implements LogService {
@Override
public void log(String msg) {
System.out.println("From Sdk1Logger " + new Date() + " : " + msg);
}
}
3. Service Configuration File
Include a special file named META-INF/services/{fully-qualified-service-interface-name} in the JAR files containing the implementations. This file lists the fully qualified class names of the service provider implementations, one per line.
com.sample.app.log.service.LogService
com.sample.app.sdk1.log.service.Sdk1Logger
4. Service Loading
At runtime, you use the ServiceLoader class to dynamically load implementations of the service interface. The ServiceLoader class reads the service configuration files from the classpath and instantiates the service provider implementations.
ServiceLoader<LogService> logServicesLoader = ServiceLoader.load(LogService.class);
5. Iterating Over Implementations
You can then iterate over the loaded service provider implementations using the iterator() method of ServiceLoader. This returns an iterator that provides access to the instantiated service provider objects.Iterator<LogService> logServiceIterator = logServicesLoader.iterator();
while (logServiceIterator.hasNext()) {
LogService logService = logServiceIterator.next();
logService.log("Hello World");
}
Find the below step-by-step procedure to build the working application.
log-service project setup
Create new maven project ‘log-service’ and update pom.xml like below.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample.app</groupId>
<artifactId>log-service</artifactId>
<version>1.0.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M6</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<localCheckout>true</localCheckout>
<autoVersionSubmodules>true</autoVersionSubmodules>
</configuration>
</plugin>
</plugins>
</build>
</project>
Define LogService interface.
LogService.java
package com.sample.app.log.service;
public interface LogService {
void log(String msg);
}
Setup sdk1
Create sdk1 maven project and update pom.xml like below.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample.app</groupId>
<artifactId>sdk1</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>com.sample.app</groupId>
<artifactId>log-service</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M6</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<localCheckout>true</localCheckout>
<autoVersionSubmodules>true</autoVersionSubmodules>
</configuration>
</plugin>
</plugins>
</build>
</project>
Define Sdk1Logger class.
Sdk1Logger.java
package com.sample.app.sdk1.log.service;
import java.util.Date;
import com.sample.app.log.service.LogService;
public class Sdk1Logger implements LogService {
@Override
public void log(String msg) {
System.out.println("From Sdk1Logger " + new Date() + " : " + msg);
}
}
Create a file 'com.sample.app.log.service.LogService' in src/main/resources/META-INF/services folder of sdk1 project.
com.sample.app.log.service.LogService
com.sample.app.sdk1.log.service.Sdk1Logger
sdk2 project setup
Create a new maven project sdk2 and update pom.xml with maven dependencies.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample.app</groupId>
<artifactId>sdk2</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>com.sample.app</groupId>
<artifactId>log-service</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M6</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<localCheckout>true</localCheckout>
<autoVersionSubmodules>true</autoVersionSubmodules>
</configuration>
</plugin>
</plugins>
</build>
</project>
Define Sdk2Logger class.
Sdk2Logger.java
package com.sample.app.sdk2.log.service;
import com.sample.app.log.service.LogService;
public class Sdk2Logger implements LogService {
@Override
public void log(String msg) {
System.out.println("From Sdk2Logger : " + msg);
}
}
Create a file 'com.sample.app.log.service.LogService' in src/main/resources/META-INF/services folder of sdk2 project.
com.sample.app.log.service.LogService
com.sample.app.sdk2.log.service.Sdk2Logger
Main project setup
Create new maven project ‘service-loader-demo’. Update pom.xml with maven dependencies.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample.app</groupId>
<artifactId>service-loader-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.sample.app</groupId>
<artifactId>sdk1</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.sample.app</groupId>
<artifactId>sdk2</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version> <!-- Use the latest version -->
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.sample.app.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
Define main application class.
App.java
package com.sample.app;
import java.util.Iterator;
import java.util.ServiceLoader;
import com.sample.app.log.service.LogService;
public class App {
public static void main(String[] args) {
ServiceLoader<LogService> logServicesLoader = ServiceLoader.load(LogService.class);
Iterator<LogService> logServiceIterator = logServicesLoader.iterator();
while (logServiceIterator.hasNext()) {
LogService logService = logServiceIterator.next();
logService.log("Hello World");
}
}
}
Build log-service artifact
Navigate to pom.xml file of log-service and execute below command.
mvn package
Build sdk1 artifact
Navigate to pom.xml file of sdk1 and execute below command.
mvn package
Build sdk2 artifact
Navigate to pom.xml file of sdk2 and execute below command.
mvn package
Build service-loader-demo project
Navigate to pom.xml file of service-loader-demo and execute below command.
mvn package
Copy all the jar files to a folder and run service-loader-demo-0.0.1-SNAPSHOT.jar file to test the application.
$ java -jar service-loader-demo-0.0.1-SNAPSHOT.jar
From Sdk1Logger Wed Apr 10 20:09:20 IST 2024 : Hello World
From Sdk2Logger : Hello World
You can download this application from this link.
You may like
How to Get Client Certificate from HttpServletRequest
Programmatically import certificate to cacerts file in Java
Command to check CPU temperature in Mac
No comments:
Post a Comment