Plugin architecture tutorial - java

I am looking for a tutorial on how to create a plugin system, preferably in Java, but I can't find any generic examples on google (they are all about making plugins) - can anyone explain or link to how to achieve this?

A plugin system, at it's core is usually composed of two things.
1) An interface or set of interfaces that the plugin must implement so that the core system can use them.
2) A custom classloader that the main system implements to load the plugins that are usually packaged as jars.
The main system builds the classloader based on some predefined directory, or configuration file that specifies where the plugins exist. This loader iterates over the classes and finds ones that implement the specified interface, and calls methods based on that interface as appropriate for the system.

Why dont use something that's already there like Equinox, or go one step further and use Eclipse plugin system.

Related

What's the proper way to share the interface?

What if I have a project that relies on the abstraction(interface) but does not contain any implementation for this interface. Therefore I want to give that interface to someone who can implement it so I (or someone else who is going to use my software) will be able to use their implementation of my interface.
Thus, I have the following question. How can I, let's say, share that interface?
The idea which came to me is to make JAR which contains interface and give it to someone who is going to implement that interface in JAR. After it, the one who implemented the interface, creates his JAR and gives it to me. So I can use his JAR with the implementation of my interface. Is it a proper way to do so?
The purpose of it is to make modular architecture so that if I need a new game(according to the above example), I'll take a JAR with implemented interface and just plug it in my project.
Yes.
You should have a shared build artifact (JAR file) that contains only the interfaces, which your project and the implementing project can both depend on.
You may want to look into tools like Maven or Gradle for helping orchestrate your build process with dependencies like this. For example, you may want to publish your API JAR to a shared package repository that both developers can work with.
You may also want to look into java.util.ServiceLoader and the Service Locator pattern, for discovering which specific implementation(s) you have available.

select different jar at runtime - toggling

I was wondering if there was a way to select different versions of the same jar at runtime. I am hoping to avoid using maven profiles since this would be a build-time selection.
Lets say there are two versions of the same jar:
greatFeature_version_A.jar
greatFeature_version_B.jar
My initial idea was to use JMX to create a basic runtime toggle selecting between those two jars which are both included in the classpath. Also, the contents of the two jars are the same (no versioning or different naming of the internal classes).
So when a class is requested, lets say from version_A, the class loader will always select the first one it finds, regardless of which jar it belongs to.
My thinking is that no effective runtime toggling can be achieved this way. I was wondering if anyone might have a experienced something similar and have a recommended workaround. I am also hoping to avoid writing a custom class loader if possible.
Many thanks!
P.S. Other related questions on SO indicate custom class loaders, like this one.
You can use jarjar to "rename" the packages so greatFeature_version_A.jar's packages start ajar.* and the other start bjar.* This way you can use the code from both jars in the same application, potentially at the same time.

How to restrict the usage of a Java public class outside of its Jar?

I'd like to be able to annotate a public class/interface in Java as #NonPublic, which would mean This interface is only to be used within this project, it is not part of the public API that this project exports.
This is common for projects that are composed of several jar files. Not all public classes/interfaces are meant to really be public outside of your jar.
Do you know of any tool/framework/plugin that does this?
IMHO the package system in Java is one of the most broken things that exist.
I'm not familiar with any standard Java-level mechanism to do that, although it is probably easy to write a tool or compiler extension that will enforce it.
However, if you are using OSGi (Eclipse is written that way), one of its advantages is a system for specifying better package and module level restrictions.
Without OSGi another common practice is the separate API from implementation.
You could separate classes required during compile time from the ones which are required during runtime. To prevent users of your library to have dependencies to implementation details.
myLibAPI.jar
myLibImpl.jar
OSGi Bundle is the solution.
If you want to convert you Jar into an Eclipse Plug-in, you can use Eclipse RCP release. Right click on your project : Configure -> Convert to plug-in projects

Java - keeping multi-version application from splitting codebase

I am writing an application that will ship in several different versions (initially around 10 variations of the code base will exist, and will need to be maintained). Of course, 98% or so of the code will be the same amongst the different systems, and it makes sense to keep the code base intact.
My question is - what would be the preferred way to do this? If I for instance have a class (MyClass) that is different in some versions (MyClassDifferent), and that class is referenced at a couple of places. I would like for that reference to change depending on what version of the application I am compiling, rather than having to split all the classes referring to MyClassDifferent too. Preprocessor macros would be nice, but they bloat the code and afaik there are only proof of concept implementations available?
I am considering something like a factory-pattern, coupled with a configuration file for each application. Does anyone have any tips or pointers?
You are on the right track: Factory patterns, configuration etc.
You could also put the system specific features in separate jar files and then you would only need to include the appropriate jar alongside your core jar file.
I'd second your factory approach and you should have a closer look at maven or ant (depending on what you are using).
You can deploy the different configuration files that determine which classes are used based on parameters/profiles.
Preprocessor makros like C/C++ have are not available directly for java. Although maybe it's possible to emulate this via build scripts. But I'd not go down that road. My suggestion is stick with the factory approach.
fortunately you have several options
1) ServiceLoader (builtin in java6) put your API class like MyClass in a jar, the compile your application against this API. Then put a separate implementation of MyClass in a separate jar with /META-INF/services/com.foo.MyClass. . Then you can maintain several version of your application simply keeping a "distribution" of jars. Your "main" class is just a bunch of ServiceLoader calls
2) same architecture of 1) but replacing META-INF services with Spring or Guice config
3) OSGI
4) your solution
Look up the AbstractFactory design pattern, "Dependency Injection", and "Inversion of Control". Martin Fowler writes about these here.
Briefly, you ship JAR files with all the needed components. For each service point that can be customized, you define an Interface for the service. Then you write one or more implementations of that Interface. To create a service object, you ask an AbstractFactory for it, eg:
AbstractFactory factory = new AbstractFactory();
...
ServiceXYZ s = factory.newServiceXYZ();
s.doThis();
s.doThat();
Inside your AbstractFactory you construct the appropriate ServiceXYZ object using the Java reflection method Class.classForName(), and SomeClassObject.newInstance(). (Doing it this way means you don't have to have the ServiceXYZ class in the jar files unless it makes sense. You can also build the objects normally.)
The actual class names are read in from a properties file unique to each site.
You can roll your own solution easily enough, or use a framework like Spring, Guice, or Pico.

How to create a pluginable Java program?

I want to create a Java program that can be extended with plugins. How can I do that and where should I look for?
I have a set of interfaces that the plugin must implement, and it should be in a jar. The program should watch for new jars in a relative (to the program) folder and registered them somehow.
Although I do like Eclipse RCP, I think it's too much for my simple needs.
Same thing goes for Spring, but since I was going to look at it anyway, I might as well try it.
But still, I'd prefer to find a way to create my own plugin "framework" as simple as possible.
I've done this for software I've written in the past, it's very handy. I did it by first creating an Interface that all my 'plugin' classes needed to implement. I then used the Java ClassLoader to load those classes and create instances of them.
One way you can go about it is this:
File dir = new File("put path to classes you want to load here");
URL loadPath = dir.toURI().toURL();
URL[] classUrl = new URL[]{loadPath};
ClassLoader cl = new URLClassLoader(classUrl);
Class loadedClass = cl.loadClass("classname"); // must be in package.class name format
That has loaded the class, now you need to create an instance of it, assuming the interface name is MyModule:
MyModule modInstance = (MyModule)loadedClass.newInstance();
Look into OSGi.
On one hand, OSGi provides all sorts of infrastructure for managing, starting, and doing lots of other things with modular software components. On the other hand, it could be too heavy-weight for your needs.
Incidentally, Eclipse uses OSGi to manage its plugins.
I recommend that you take a close look at the Java Service Provider (SPI) API. It provides a simple system for finding all of the classes in all Jars on the classpath that expose themselves as implementing a particular service. I've used it in the past with plugin systems with great success.
Although I'll second the accepted solution, if a basic plugin support is needed (which is the case most of the time), there is also the Java Plugin Framework (JPF) which, though lacking proper documentation, is a very neat plugin framework implementation.
It's easily deployable and - when you get through the classloading idiosynchrasies - very easy to develop with. A comment to the above is to be aware that plugin loadpaths below the plugin directory must be named after the full classpath in addition to having its class files deployed in a normal package path named path. E.g.
plugins
`-com.my.package.plugins
`-com
`-my
`-package
`-plugins
|- Class1.class
`- Class2.class
At the home-grown classloader approach:
While its definitely a good way to learn about classloaders there is something called "classloader hell", mostly known by people who wrestled with it when it comes to use in bigger projects. Conflicting classes are easy to introduce and hard to solve.
And there is a good reason why eclipse made the move to OSGi years ago.
So, if its more then a pet project, take a serious look into OSGi. Its worth looking at.
You'll learn about classloaders PLUS an emerging technolgy standard.
Have you considered building on top of Eclipse's Rich Client Platform, and then exposing the Eclipse extension framework?
Also, depending on your needs, the Spring Framework might help with that and other things you might want to do: http://www.springframework.org/

Categories