4

first: I'm really new to spring-boot and maven. So I still don't get how everything plugs together.

What I'm trying to achieve is some kind of plugin-feature for my application. From my research it seems the best way to do this is using ServiceLoader or the spring-boot implmentation of the SpringFactoriesLoader.

According to several instructions from the web I put two projects together

  • James (the main application) GitHub
  • TemperatureSensor (the plugin) GitHub

The JamesApplication provides an interfaces which is supposed to be implemented (de.maxrakete.james.device.domain.DeviceInterface).

The TemperatureSensor implements said class and exposes this in several ways.

According to this page I tried two different implementations (see in the onApplicationEvent-function) in the MainApplication:

@SpringBootApplication
public class JamesApplication implements ApplicationListener<ApplicationReadyEvent> {

    public static void main(String[] args) {
        SpringApplication.run(JamesApplication.class, args);

        ClassLoader cl = ClassLoader.getSystemClassLoader();

            URL[] urls = ((URLClassLoader)cl).getURLs();

        for(URL url: urls){
            System.out.println("Classpath file: " + url.getFile());
        }
    }

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        ServiceLoader<DeviceInterface> loader = ServiceLoader.load(DeviceInterface.class);
        loader.iterator();

        List<DeviceInterface> foos = SpringFactoriesLoader.loadFactories(DeviceInterface.class, null);
    } 
}

I'm trying both ways to load the jar, but nothing is happening (I'm supposed to get some log-messages from the plugin) but this is not happening.

The way I'm running the application is like this:

java -cp "./plugins/TemperatureSensor-0.0.1-SNAPSHOT.jar" -jar james.war

As you see I'm trying to add the jar in the subfolder to the classpath, but in the ouput of the main-function (where I try to print all the files in the classpath) I only get Classpath file: /home/max/folder/james.war

Conclusion

So, there are three possible error-sources

  1. Wrong cli command to add classpath files
  2. Wrong declaration of interfaces in the META-INF folder
  3. Wrong implementation of the Loader
  4. Maybe I'm compiling the sources the wrong way?
  5. Wrong configuration of the pom.xml

I really have no idea what the problem might be. I tried to provide you with as much information as possible and all the steps of my research. I hope someone finds some helpful clues, which I might have overlooked.

Thanks veryone!

mietzekotze
  • 195
  • 13
  • "some kind of plugin-feature for my application" - can you expand on that before going down SPI path? What is this so-called plugin feature? How to do plan to build and deploy those plugins? – Abhijit Sarkar Jul 12 '17 at 01:49
  • What about `java -cp "plugins/TemperatureSensor-0.0.1-SNAPSHOT.jar" -jar james.war` ? – StanislavL Jul 12 '17 at 07:20
  • @AbhijitSarkar The projects is supposed to be a smart home application. The plugins rpresent different devices, that I connect to it and I don't want to recompile the whole application everytime I add functionality. – mietzekotze Jul 12 '17 at 08:22
  • @StanislavL that does not work either – mietzekotze Jul 12 '17 at 08:22
  • Instead of inventing a new framework, I suggest you look at [OSGI](https://www.osgi.org/). – Abhijit Sarkar Jul 12 '17 at 08:26
  • @AbhijitSarkar according to this [post](https://stackoverflow.com/questions/4673406/programmatically-start-osgi-equinox/4673904#4673904) OSGI is using the ServiceLoader-API as well, so the problem that my application is not finding any other jar's in my classpath remains. – mietzekotze Jul 12 '17 at 11:34
  • @mietzekotze no, it doesn't. Do you understand the difference between using the Java API and developing the Java API? – Abhijit Sarkar Jul 12 '17 at 15:49
  • 1
    I'm sorry, I'm afraid I do not understand the question. Every OSGI implementation I've seen is using the Java APIs ServiceLoader, which I am using too in my example. Since my ServiceLoader implementation is not finding any jars, I don't think the other implementation will. How can the OSGI-Framework register something, when the API it is using is not finding anything? – mietzekotze Jul 12 '17 at 15:57
  • That was a rhetorical question. What I meant is that OSGI code is battle tested and used extensively. Your code, on the other hand, is your own homegrown solution. You can't claim that the problems in your code would exist in OSGI code as well. My suggestion is not to reinvent the wheel when you're shopping for a car. – Abhijit Sarkar Jul 12 '17 at 19:29

0 Answers0