Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Architecture for plugins to be loaded in runtime

Considering that I am developing an end-user software program (as an uberjar) I am wondering what my options are to make it possible for the user to download a plugin and load that during runtime.

The plugin(s) should come compiled and without source code, so sth. like load is not an option. What existing libraries (or ways of Java...?) exist to build this on?

EDIT: If you are not sure I would also be satisfied with a way that costs a reboot/-start of the main-program. However, what is important is that the source-code won't be included in any JAR file (neither main application nor plugin-jars, see :omit-source of Leiningen documentation).

like image 781
Leon Grapenthin Avatar asked Jul 31 '13 12:07

Leon Grapenthin


People also ask

What is a plugin architecture?

A plug-in is a bundle that adds functionality to an application, called the host application, through some well-defined architecture for extensibility. This allows third-party developers to add functionality to an application without having access to the source code.

What is the plugin system?

In computing, a plug-in (or plugin, add-in, addin, add-on, or addon) is a software component that adds a specific feature to an existing computer program. When a program supports plug-ins, it enables customization.


3 Answers

To add a jar during runtime, use pomegranate which lets you add a .jar file to the classpath. Plugins of your software should be regular Clojure libs that follow certain conventions that you need to establish:

  1. Make them provide (e. g. in an edn) a symbol to an object implementing a constructor/destructor mechanism such as the Lifecycle protocol in Stuart Sierras component library. In runtime, require and resolve that symbol, start the resulting object and hand it over to rest your programs plugin coordination facilities.

  2. Provide a public API in your program that allows the plugins to interact with it in ways that you coordinate asynchronously e. g. with clojure.core.async (don't let one plugin block the entire program).

  3. Make sure that the plugins have a coordinated way to expose their functionality to each other only if they desire so to enable a high degree of modularity among your plugins. Make sure that your plugin loader is capable of detecting dependencies among plugins and is capable of loading and unloading them in the right order.

like image 101
Leon Grapenthin Avatar answered Oct 01 '22 11:10

Leon Grapenthin


I've not tried it myself, but you should in theory be able to get OSGi to work with Clojure.

There's a Clojure / OSGi integration library here:

  • https://github.com/aav/clojure.osgi
like image 20
mikera Avatar answered Oct 01 '22 12:10

mikera


If I were to attempt to role my own solution, I would try using tools.namespace to load and unload plugins. I'm not entirely sure it will work, but it's certainly in the right direction. I think one key piece is that the plugin jars will have to be "installed" in a location that's already on the classpath.

Again, this is only the start of one possible solution. I haven't tried doing this.

like image 39
Jeremy Avatar answered Oct 01 '22 11:10

Jeremy