Author: Michael Krauße
The Spring-framework is fantastic if you need dependency injection in your application. Since I love OSGI’s idea that a framework provide extension-points which can be extended by other plugins I wanted something similar for my current project. What I need is a very lightweight approach similar to OSGI, which allows me that each plugin can have all configuration already “on board” and can contribute to a framework. Researching and asking at Stackoverflow gave me a link to Spring Dynamic Modules Unfortunatly this approach was a little bit to heavyweight for me since my application does not live in an application-server which supports OSGI.
This article contains my solution for the given problem. Available source-code is distributed under a BSD-License and unclear acronyms have been explained at the end.
At the moment I am working at a client who develops multiple plugins which were build upon a self-written-framework and share an Oracle database during runtime. Two years ago all plugins and the framework have been stored in the same repository-structure. This allowed us to configure the product in Spring configuration-files which belonged to the framework. During time the number of plugins raised and developers were not able to keep plugins up-to-date to latest framework version. Now we run into the problem that all plugin-registration-configuration is done in the framework but we do not want all plugins to be part of the product we deploy. (Plugins which have not been tested against latest version of framework will be deployed on an other server with a framework version which has been tested)
For solving the problem I looked for an approach which adds some OSGI to a Spring application. All I needed was a solution which simple creates s static configuration which is not changeable during runtime and is flexible enough to allow new plugins to register without touching the framework. The Spring Dynamic Modules looked promising but were a little bit heavyweight and I don’t like aspect-oriented-programming anyway if I can avoid it.
Or to make a long story short the only thing I wanted to change was that each plugin registers on its own to the framework. The framework should not know anything about the plugins which run on top of it.
My solution was inspired by OSGI. Removing dynamic plugin (un)loading, and all other OSGI I never knew it exists stuff helped me finding a solution. In my approach I changed the configuration is done in Spring. Instead of a Spring configuration which contains all plugin-registration in the framework the framework creates a
pluginRegistry with scope
singleton. Each contributing plugin is now able to contribute to this registry. In only has to create
pluginFactory which creates instances of the plugin. The instances of the plugin are created with help of the spring-application-context.
Since all pluging-factories are configured as spring singletons they will created during application-startup-time.
You will find more information in the following class-diagram and the source-code if you download it (see above how to do it).
minimalOsgiWithSpring(aka framework) contains all needed classes, where plugin implementations can contribute too
Application– contains a main method, does the work by calling responsible plugin
PluginRegistry– plugins register here and returns the plugin which is responsible for handling a specific task
PluginFactory– is able to create new instance of plugins. Each plugin implementation needs to register its plugin in is own instance of that factory
IPlugin– every plugin has to implement this interface. In an OSGI world this would be the extension-point
core.xmlwhich makes the registry available under the name
languageApplicationwhich uses this registry
<?xml version="1.0" encoding="UTF-8"?> <!-- author: Michael Krausse --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <!-- Bean coreRegistry becomes available in spring context. Plugins needs to register against this registry. --> <bean id="coreRegistry" class="de.m_krausse.articles.minimalOsgiWithSpring.PluginRegistry"> </bean> <!-- Application uses coreRegistry. No plugins are configured here this is done in plugin implementation --> <bean id="languageApplication" class="de.m_krausse.articles.minimalOsgiWithSpring.Application"> <property name="pluginRegistry" ref="coreRegistry" /> </bean> </beans>
pluginOne– is an example for an implementation which contributes to framework
PluginOne– an example implementation of the
pluginOne.xmlwhich creates a
pluginGermanFactorythis class gets a reference to
coreRegistryand therefore does the trick
<?xml version="1.0" encoding="UTF-8"?> <!-- author: Michael Krausse --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <!-- Configures the plugin which does the work of saying hello in German. --> <bean id="pluginGerman" class="de.m_krausse.articles.minimalOsgiPluginOne.PluginOne"> </bean> <!-- The factory creates new instances of pluginGerman if coreRegistry needs a plugin which can say hello in GERMAN. --> <bean id="pluginGermanFactory" class="de.m_krausse.articles.minimalOsgiWithSpring.PluginFactory"> <constructor-arg ref="coreRegistry" /> <constructor-arg value="GERMAN" /> <constructor-arg value="pluginGerman" /> </bean> </beans>
application– describes application
applicationis the product
With the approach described above it is possible to give your spring application a more OSGI like feeling. Although the approach allows only static configuration (no dynamic (un)loading of plugins) it might work well for situations when static configuration is sufficient.
I made good experience with this approach in a non-clustered tomcat environment. It is integrated into a batch-processing framework used in the output-management.
I am interested in your point of view. If you want drop me a line ClickToWriteMail
Please feel free to download the sources from my example project. You need at least maven 2.X to compile and run the project. Disclaimer You use the source-code on your own risk.
You find the source code under the following URI.
Some descriptions have been borrowed from wikipedia. ;-)
|OSGI||Open Services Gateway initiative framework – is a module system and service platform for the Java programming language that implements a complete and dynamic component model|
|Product||As used in an OSGI world. Consits of different applications and is shipable on its own (if runtime requirements are met)|