Spring boot application not able to load SPI implementation

Viewed 653

I have an SPI interface defined in a maven module A. In Module B, which is a spring-boot application, I have defined META-INF/services/<interface-named-file>.

In Module A, I am having this code.

public class NotificationResultPluginProvider {
    private static NotificationResultPluginProvider notificationResultPluginProvider;
    private NotificationResultPlugin notificationResultPlugin;

    private NotificationResultPluginProvider() {
        final ServiceLoader<NotificationResultPlugin> loader = ServiceLoader.load(NotificationResultPlugin.class);
        final Iterator<NotificationResultPlugin> it = loader.iterator();
        if (it.hasNext()) {
            notificationResultPlugin = it.next();
        }
    }

    public static synchronized NotificationResultPluginProvider getInstance() {
        if (null == notificationResultPluginProvider) {
            notificationResultPluginProvider = new NotificationResultPluginProvider();
        }
        return notificationResultPluginProvider;
    }

    public NotificationResultPlugin getNotificationResultPlugin() {
        return notificationResultPlugin;
    }
}

In Module B - spring boot app - I have an implementation of NotificationResultPlugin interface.

Now here is the pickle.

When I run the boot app from intellij, I see that (in below code) it.hasNext() is true and notificationResultPlugin is found. In this case my application is working as expected.

if (it.hasNext()) {
            notificationResultPlugin = it.next();
        }

But when I run the boot app with CLI, using a command like below (note I am deflating the jar first and then launching)

jar -xf <jar file>;
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=12341 -cp 'BOOT-INF/lib/*:BOOT-INF/classes' <main/class/fqn>;

Then it.hasNext() is false and my implementation in Module B for given SPI is not found. As a result, my application is not working as expected. I am at wits end now.

Other relevant information:

My spring boot app, is not a web app. That is I am not exposing any rest end point. I am simply using spring-kafka with minimal dependencies.

What am I missing ? Any help is appreciated.

Found solution

As they say, mind works best when you are not trying.

ServiceLoader was not able to load the SPI implementation because META-INF/services directory was not in classpath while I am starting the application. Setting the class path correctly did the trick. Ergo, this is the change i needed to do.

-cp 'BOOT-INF/lib/*:BOOT-INF/classes:.'

Notice that extra dot at the end.

0 Answers
Related