How to make a Java application modular

I am trying to make my Java application modular so that there will be a main base module the client will use for aqcuire, but he / she will be able to add additional features / plugins as they become available or as her needs expand. Similar to how IDEs like NetBeans do it.

I am planning to have a subdirectory called modules / plugins on PC clients where any plugin applications will be included as .jar files. The main module, when the user launches the application, includes these other plugins in the last element, so, for example, the Stage will have buttons from both the main module and the plugin modules in the same scene .

I speak fluently with elgg , which uses views for this. Borrowing from this, I could have HBox, for example, on the main module, which is populated with buttons from different plugins when the application starts.

How can I use core_base_module.jar below to call all plugins in below plugins directory. In other words, how can I use one file .jar

calling another file .jar

?

Example directory structure:

main dir/---core_base_module.jar
        /---plugins ---/chat.jar
                       /videoplayer.jar
                       /like.jar
                       /unlike.jar
                       /etc.jar
                       /etc_etc.jar

      

+3


source to share


2 answers


You can do it manually:

  • Search plugins folder
  • Scan a folder to get a list of all jars
  • Create a classloader, include a jar file, then look into each jar for your plugin API implementation.
  • Create an instance and register it in your plugin registry

While you can do this yourself, it would be easier to use the service loader API . This API is part of Java and was created for this purpose. This is what spring uses to load plugins that can handle different XML tags in spring XML config files. For example take a lookspring-web.jar!/META-INF/services

Then you will want your startup script to add all JARs to your main classpath like this:



java -cp plugins/* -jar app.jar

      

Or if you don't have a lauch script, you can do the same in java, but by creating a URLClassLoader , passing it all the jar files you want, then call your main class inside that new classloader.

Additional Information:

+4


source


If you really want to build a professional grade app, the ServiceLoader API suggested by @DavidRoussel is the way to go.

If you prefer something lighter that you can do manually, you can simply use an API package containing only the interfaces of the abstract classes that you include in your application and an implementation package containing the actual classes that you provide as a separate jar. Since you cannot create objects that only know the interface through new

, you will have to use a factory pattern and reflection. You should also use Class.forName("package.to.class")

to check for the existence of an implementation at the beginning of your program.

An example assuming an interface Foo

, optionally implemented FooImpl

, whose constructor takes a string factory argument could be:

public class FooFactory {
    public static final String CLASSNAME = "...FooImpl";
    public static Foo createFoo(String key) {
        try {
            Class<?> fooclazz = Class.forName(CLASSNAME);
            Foo foo = (Foo) fooclazz.getConstructor(String.class).newInstance(key);
            return foo;
        }
        catch (Exception e) {
            // eventually process some exceptions
        }
        return null;
    }
}

      

First you set up a global boolean hasFoo

(a static member of the main class, for example):



    try {
        Class.forName(FooFactory.CLASSNAME);
        hasOpt = true;
    }
    catch (Exception e) {
        hasOpt = false;
    }

      

And you optionnaly use it:

    if (MainClass.hasOpt) {
        Foo foo = FooFactory.createFoo("bar");
        // do something with foo
    }
    else {
        // warning message : Option not present
    }

      

With this method, you just add the implementation jar to the classpath and restart your application to use it.

+1


source







All Articles