ZK OSGi - Developing plug-in based applications with OSGi"

From Documentation
(One intermediate revision by one other user not shown)
Line 9: Line 9:
  
 
== OSGi ==
 
== OSGi ==
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.
+
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 decoupling each application concern into a separate bundle. 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 its own ''classpath''. Manifest files are used to define bundle imports and exports. OSGi keywords are: loose-coupling, hot deployment and versioning.
  
 
== Example Bundles ==
 
== Example Bundles ==
 
This example comes with 3 bundles:
 
This example comes with 3 bundles:
*<b>zk-osgi.blueprint</b> - Contains interface which is shared with other 2 bundles.
+
*<b>zk-osgi.blueprint</b> - Contains interfaces for inter-bundle communication.
 
*<b>zk-osgi.host</b> - Host web application bundle.
 
*<b>zk-osgi.host</b> - Host web application bundle.
 
*<b>zk-osgi.test-plugin</b> - Test plug-in bundle.
 
*<b>zk-osgi.test-plugin</b> - Test plug-in bundle.
Line 27: Line 27:
  
 
=== Versioning ===
 
=== Versioning ===
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 <tt>ApplicationContext.getBean()</tt> 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<ref>Note: the application context is published as a service primarily to facilitate testing, administration, and management.
+
Not exactly as OSGi versining is meant to be used. 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 <tt>ApplicationContext.getBean()</tt> 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<ref>Note: the application context is published as a service primarily to facilitate testing, administration, and management.
  
 
Accessing this context object at runtime and invoking <tt>getBean()</tt> or similar operations is discouraged.
 
Accessing this context object at runtime and invoking <tt>getBean()</tt> or similar operations is discouraged.
Line 55: Line 55:
 
*Configure PostgreSQL:
 
*Configure PostgreSQL:
 
**Create database: osgi.
 
**Create database: osgi.
**Grant an user access for that database. Username: postgres, Password: osgi.
+
**Grant user access for that database. Username: postgres, Password: osgi.
*Copy content of Required Bundles to Virgo/repository/usr directory.
+
*Copy Required Bundles content to Virgo/repository/usr directory.
*Copy content of Example Bundles to Virgo/pickup directory.
+
*Copy Example Bundles content to Virgo/pickup directory.
 
*Launch Virgo/bin/startup.bat.
 
*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.
+
If Virgo manages to deploy bundles in correct order you should be able to access it from http://localhost:8080/zk-osgi/.
  
 
== Virgo Constraint Errors ==
 
== 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 <b>zk-osgi.blueprint</b> bundle is needed for the other 2 bundles this bundle should be installed first. To enforce correct order, delete other 2 bundles, and leave <b>zk-osgi.blueprint</b> 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 [http://www.eclipse.org/virgo/documentation/virgo-documentation-3.0.0.x/docs/virgo-programmer-guide/html/ch04s02.html#developing-applications-packaging-par PARs] and [http://www.eclipse.org/virgo/documentation/virgo-documentation-3.0.0.x/docs/virgo-programmer-guide/html/ch04s03.html Plans] for more concrete deployment.
+
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 <b>zk-osgi.blueprint</b> bundle is needed for the other 2 bundles this bundle should be first to be installed. To enforce correct order, delete other 2 bundles, and leave <b>zk-osgi.blueprint</b> 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 [http://www.eclipse.org/virgo/documentation/virgo-documentation-3.0.0.x/docs/virgo-programmer-guide/html/ch04s02.html#developing-applications-packaging-par PARs] and [http://www.eclipse.org/virgo/documentation/virgo-documentation-3.0.0.x/docs/virgo-programmer-guide/html/ch04s03.html Plans] for more concrete deployment.
  
 
== Building Projects ==
 
== Building Projects ==
Line 75: Line 75:
  
 
= OSGifying ZK  =
 
= OSGifying ZK  =
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:
+
Standard ZK is not OSGi compatible. In order to use ZK in OSGi environment one has to "''OSGify''" ZK libraries. Process of "''OSGifying''" is adding meta-data information to <b>META-INF/MANIFEST.MF</b> 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:
 +
 
 
*[http://www.aqute.biz/Bnd/Bnd BND]
 
*[http://www.aqute.biz/Bnd/Bnd BND]
 
*[http://www.springsource.org/bundlor Bundlor]
 
*[http://www.springsource.org/bundlor Bundlor]
 
*Or use Eclipse to create Plug-In Project
 
*Or use Eclipse to create Plug-In Project
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:
+
 
 +
You can either convert each library separately or create a huge single bundle for all ZK libraries you need. Creating a single bundle you probably will save yourself from pain and misery caused by various bundles not being able to find resources they need. I used Eclipse's Plug-In Project for that purpose.  
 +
Steps to follow:
 +
 
 
*Create Plug-In Project.
 
*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), lets say to lib folder but the location shouldn't matter.
+
*Import all the libraries you need (I also added <b>reflections-0.9.5.jar</b> and <b>zkspring-core.jar</b> and excluded ones I don’t use), let's say to lib folder but location does not 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.
 
*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.
+
*Open plug-in project's <b>MANIFEST.MF</b> under META-INF folder and navigate to Runtime tab.
*In Runtime tab add all imported jars to your classpath.
+
*In Runtime tab add all imported jars to your ''classpath''.
 
*Then add all export packages.
 
*Then add all export packages.
*Hit Calculate Uses (it may take some time).
+
*Hit Calculate Uses (may take some time).
*Import packages are missing from the project, there are 2 approaches you could take:
+
*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 some what 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):
+
**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 <b>META-INF/MANIFEST.MF</b> manually for packages you need. I added following packages:
 +
 
 
<source lang="java" line="false">
 
<source lang="java" line="false">
 
Import-Package:  
 
Import-Package:  

Revision as of 15:27, 12 October 2013

DocumentationSmall Talks2011DecemberZK OSGi - Developing plug-in based applications with OSGi
ZK OSGi - Developing plug-in based applications with OSGi

Author
Erko Knoll, Java Developer
Date
December 30, 2011
Version
ZK 5.0.9

Introduction

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

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 decoupling each application concern into a separate bundle. 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 its own classpath. Manifest files are used to define bundle imports and exports. OSGi keywords are: loose-coupling, hot deployment and versioning.

Example Bundles

This example comes with 3 bundles:

  • zk-osgi.blueprint - Contains interfaces for inter-bundle communication.
  • 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.

Loose-Coupling

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.

Hot Deployment

Host application is able to discover plug-in installs/uninstalls and modifications instantaneously.

Versioning

Not exactly as OSGi versining is meant to be used. 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[1].


  1. 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.

Example

Used Frameworks

  • ZK 5.0.9
  • Spring 3.0.5
  • Spring DM (Virgo provides)
  • Hibernate 3.3.2.GA (with Ehcache as second level cache)

Prerequisites

  • 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)
  • PostgreSQL

Running Example

  • Download example and unpack it.
  • Download and install Virgo and PostgreSQL.
  • Configure PostgreSQL:
    • Create database: osgi.
    • Grant user access for that database. Username: postgres, Password: osgi.
  • Copy Required Bundles content to Virgo/repository/usr directory.
  • Copy Example Bundles content 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/.

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 first to be installed. 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.

Building Projects

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.

Modifications

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.

OSGifying ZK

Standard ZK is not OSGi compatible. In order to use ZK in OSGi environment one has to "OSGify" ZK libraries. Process of "OSGifying" is adding 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:

  • BND
  • Bundlor
  • Or use Eclipse to create Plug-In Project

You can either convert each library separately or create a huge single bundle for all ZK libraries you need. Creating a single bundle you probably will save yourself from pain and misery caused by various bundles not being able to find resources they need. I used Eclipse's Plug-In Project for that purpose. 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 location does not 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 (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:
 1 Import-Package: 
 2  javax.servlet;version="2.5.0",
 3  javax.servlet.http;version="2.5.0",
 4  org.reflections,
 5  javassist;version="3.12.1",
 6  javassist.bytecode;version="3.12.1",
 7  javassist.bytecode.annotation;version="3.12.1",
 8  com.google.common.collect;version="10.0.0",
 9  com.google.common.base;version="10.0.0",
10  org.slf4j;version="1.6.1",
11  org.springframework.beans.factory.annotation;version="3.0.5.RELEASE",
12  org.springframework.beans.factory;version="3.0.5.RELEASE",
13  org.springframework.context;version="3.0.5.RELEASE",
14  org.springframework.web.context.support;version="3.0.5.RELEASE",
15  org.springframework.beans.factory.xml;version="3.0.5.RELEASE",
16  org.springframework.beans.factory.config;version="3.0.5.RELEASE",
17  org.springframework.beans.factory.support;version="3.0.5.RELEASE",
18  org.springframework.beans.propertyeditors;version="3.0.5.RELEASE",
19  org.apache.commons.fileupload,
20  javax.naming
  • Building bundle: navigate to Overview tab and use Export Wizard in bottom right corner to build the bundle.

Download Example

Download


Comments



Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.