This article shows how to use ZK in OSGi environment and the example that comes with it demonstrates how to develop plug-in based applications using OSGi bundles as base for plug-ins.
OSGi (Open Services Gateway initiative framework) allows Java applications to be written in a fully modular way. Something that is not present in standalone Java environments as of 2011. Basically OSGi allows to decouple each application concern into separate bundles. Bundles run concurrently in different kernels and by default are unaware of other bundles, their kernels and their classpaths. Bundle services can be shared with other bundles via service registry - that's how bundles interact with each other. Each bundle has it's own classpath. Manifest files are used to define bundle meta-data, which packages from other bundles; determining which particular bundle is able to be used and which packages from this bundle should be exported for other bundles to use. OSGi keywords are: loose-coupling, hot deployment and versioning.
This example comes with 3 bundles:
- zk-osgi.blueprint - Contains interface which is shared with other 2 bundles.
- zk-osgi.host - Host web application bundle.
- zk-osgi.test-plugin - Test plug-in bundle.
Example vs. OSGi Dynamics
When you start going through example projects you probably start noticing that not every OSGi rule is respected. This example's goal is to demonstrate the capability of seamless plug-in integration with the host application without the need to define plug-in dependencies. Host application is capable of discovering changes in real time as they happen.
Example is not as loose-coupled as it should be in OSGi standards. For the sake of simplicity I kept it to 3 bundles. There are no restrictions if you want to fragment your application to smaller bundles. The more bundles you have, the more modular your application is.
Host application is able to discover plug-in installs/uninstalls and modifications instantaneously.
Not in OSGi standards. When you deploy the same bundle under different versions, host app will discover it and you will end up with duplicated resources. Example architecture is little bit different as to how OSGi standards dictate. Normally, shared services are accessible via service registry. Plug-ins in this example don't use shared services for communication. Host application accesses plug-in resources directly when it needs via ApplicationContext.getBean() which is slightly discouraged because by doing so host application bypasses service registry which guarantees that it only sees services it is supposed to see. Excerpt from Spring DM documentation.
- ↑ Note: the application context is published as a service primarily to facilitate testing, administration, and management. Accessing this context object at runtime and invoking getBean() or similar operations is discouraged. The preferred way to access a bean defined in another application context is to export that bean as an OSGi service from the defining context, and then to import a reference to that service in the context that needs access to the service. Going via the service registry ensures that a bean only sees services with compatible versions of service types, and that OSGi platform dynamics are respected.
- ZK 5.0.9
- Spring 3.0.5
- Spring DM (Virgo provides)
- Hibernate 3.3.2.GA (with Ehcache as second level cache)
- Fair understanding of ZK, OSGi, Virgo and frameworks used if you choose to modify examples.
- EclipseRT Virgo (Example is designed for version 3.0.2)
- Download example and unpack it.
- Download and install Virgo and PostgreSQL.
- Configure PostgreSQL:
- Create database: osgi.
- Grant an user access for that database. Username: postgres, Password: osgi.
- Copy content of Required Bundles to Virgo/repository/usr directory.
- Copy content of Example Bundles to Virgo/pickup directory.
- Launch Virgo/bin/startup.bat.
If Virgo manages to deploy bundles in correct order you should be able to access it from http://localhost:8080/zk-osgi/ URL.
Virgo Constraint Errors
If Virgo fails to deploy example bundles in correct order you most likely will be prompted with a constraint error informing that some package is missing. As zk-osgi.blueprint bundle is needed for the other 2 bundles this bundle should be installed first. To enforce correct order, delete other 2 bundles, and leave zk-osgi.blueprint in pickup directory. When deleted, copy the other two bundles back to pickup directory. This forces Virgo to redeploy the other two bundles which should now be resolved correctly. To avoid such manual intervention in the future Virgo supports PARs and Plans for more concrete deployment.
Projects can be built with Maven. There are two dependencies missing from public repositories. You have to install them manually to your local repository.
- zk-osgi.blueprint - Comes with the example.
- org.eclipse.virgo.kernel.deployer - Resides in Virgo/repository/ext folder.
zk-osgi.host bundle has two classes which are modified in order to accommodate plug-in architecture:
- zk.osgi.host.hibernate.PluginAwareOpenSessionInViewFilter - Modified version of OpenSessionInViewFilter which compared to the original also opens sessions for Hibernate SessionFactories found from plug-ins.
- zk.osgi.spring.scope.PluginAwareSessionScope - Modified version of SessionScope for the use in plug-ins so that plug-in beans can be scoped as sessions.
Standard ZK is not OSGi compatible. In order to use ZK in OSGi environment one has to "OSGify" ZK libraries. Process of "OSGifying" is to add meta-data information to META-INF/MANIFEST.MF file, import packages that might be needed and export packages that other bundles might need (including versioning).
There are various tools to help you achieve this:
You can either convert each library separately or create one huge bundle for all ZK libraries you need. Creating one huge bundle you probably will save yourself from pain and misery caused by various bundles not finding resource from other bundles. I used Eclipse's Plug-In Project to create one huge bundle. Steps to follow:
- Create Plug-In Project.
- Import all the libraries you need (I also added reflections-0.9.5.jar and zkspring-core.jar and excluded ones I don’t use), let's say to lib folder but the location shouldn't really matter.
- If you are using zkspring-core.jar then unpack it and copy spring.handlers and spring.schemas files under META-INF to your plug-in project's META-INF folder.
- Open plug-in project's MANIFEST.MF under META-INF folder and navigate to Runtime tab.
- In Runtime tab add all imported jars to your classpath.
- Then add all export packages.
- Hit Calculate Uses (it may take some time).
- Import packages that are missing from the project, there are 2 approaches you could take:
- Use Dependencies tab to add imports. Eclipse requires all the plug-ins to be present where you want to import from. This can be somewhat cumbersome. Also, Eclipse manifest is generated with a slightly different import directive and may cause problems later on.
- Import packages manually (which I did). Build the bundle (next step). Unpack the bundle and modify META-INF/MANIFEST.MF manually for packages you need. I added following packages (which are probably required anyway):
Import-Package: javax.servlet;version="2.5.0", javax.servlet.http;version="2.5.0", org.reflections, javassist;version="3.12.1", javassist.bytecode;version="3.12.1", javassist.bytecode.annotation;version="3.12.1", com.google.common.collect;version="10.0.0", com.google.common.base;version="10.0.0", org.slf4j;version="1.6.1", org.springframework.beans.factory.annotation;version="3.0.5.RELEASE", org.springframework.beans.factory;version="3.0.5.RELEASE", org.springframework.context;version="3.0.5.RELEASE", org.springframework.web.context.support;version="3.0.5.RELEASE", org.springframework.beans.factory.xml;version="3.0.5.RELEASE", org.springframework.beans.factory.config;version="3.0.5.RELEASE", org.springframework.beans.factory.support;version="3.0.5.RELEASE", org.springframework.beans.propertyeditors;version="3.0.5.RELEASE", org.apache.commons.fileupload, javax.naming
- Building bundle: navigate to Overview tab and use Export Wizard in bottom right corner to build the bundle.
|Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.|