ZK OSGi - Developing plug-in based applications with OSGi"
m (correct highlight (via JWB)) |
|||
(23 intermediate revisions by 3 users not shown) | |||
Line 6: | Line 6: | ||
= Introduction = | = Introduction = | ||
− | This article shows how to use ZK in OSGi environment and example that comes with it demonstrates how to develop plug-in based applications using OSGi bundles as base for plug-ins. | + | 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 == | ||
− | OSGi (Open Services Gateway initiative framework) allows Java | + | 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: | ||
− | *zk-osgi.blueprint - Contains | + | *<b>zk-osgi.blueprint</b> - Contains interfaces for inter-bundle communication. |
− | *zk-osgi.host - Host web application bundle. | + | *<b>zk-osgi.host</b> - Host web application bundle. |
− | *zk-osgi.test-plugin - Test plug-in bundle. | + | *<b>zk-osgi.test-plugin</b> - Test plug-in bundle. |
== Example vs. OSGi Dynamics == | == 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 capability of seamless plug-in integration with the host application | + | 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 === | === 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. | + | 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 === | === Hot Deployment === | ||
Line 27: | Line 27: | ||
=== Versioning === | === Versioning === | ||
− | Not as | + | 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 <code>ApplicationContext.getBean()</code> 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 getBean() or similar operations is discouraged. | + | Accessing this context object at runtime and invoking <code>getBean()</code> 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, | 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. | and then to import a reference to that service in the context that needs access to the service. | ||
− | Going via the service registry | + | |
− | and that OSGi platform dynamics are respected.</ | + | 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.</ref>. |
+ | |||
+ | ---- | ||
+ | <references/> | ||
= Example = | = Example = | ||
Line 44: | Line 47: | ||
== Prerequisites == | == Prerequisites == | ||
*Fair understanding of ZK, OSGi, Virgo and frameworks used if you choose to modify examples. | *Fair understanding of ZK, OSGi, Virgo and frameworks used if you choose to modify examples. | ||
− | *[http://www.eclipse.org/virgo/ EclipseRT Virgo] | + | *[http://www.eclipse.org/virgo/ EclipseRT Virgo] (Example is designed for version 3.0.2) |
*[http://www.postgresql.org/ PostgreSQL] | *[http://www.postgresql.org/ PostgreSQL] | ||
Line 52: | Line 55: | ||
*Configure PostgreSQL: | *Configure PostgreSQL: | ||
**Create database: osgi. | **Create database: osgi. | ||
− | **Grant | + | **Grant user access for that database. Username: postgres, Password: osgi. |
− | *Copy | + | *Copy Required Bundles content to Virgo/repository/usr directory. |
− | *Copy | + | *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/ | + | 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 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 other | + | 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 == | ||
− | Projects can be built with Maven. There are | + | 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. | + | *<b>zk-osgi.blueprint</b> - Comes with the example. |
− | *org.eclipse.virgo.kernel.deployer - Resides in Virgo/repository/ext folder. | + | *<b>org.eclipse.virgo.kernel.deployer</b> - Resides in Virgo/repository/ext folder. |
== Modifications == | == Modifications == | ||
− | zk-osgi.host bundle has | + | <b>zk-osgi.host</b> 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. | + | *<b>zk.osgi.host.hibernate.PluginAwareOpenSessionInViewFilter</b> - 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. | + | *<b>zk.osgi.spring.scope.PluginAwareSessionScope</b> - Modified version of ''SessionScope'' for the use in plug-ins so that plug-in beans can be scoped as sessions. |
= 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 | + | 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 | + | |
+ | 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), | + | *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 ( | + | *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 | + | |
− | **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 | + | **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"> | ||
Import-Package: | Import-Package: | ||
javax.servlet;version="2.5.0", | javax.servlet;version="2.5.0", | ||
Line 108: | Line 119: | ||
org.apache.commons.fileupload, | org.apache.commons.fileupload, | ||
javax.naming | javax.naming | ||
− | </ | + | </source> |
*Building bundle: navigate to Overview tab and use Export Wizard in bottom right corner to build the bundle. | *Building bundle: navigate to Overview tab and use Export Wizard in bottom right corner to build the bundle. | ||
Line 118: | Line 129: | ||
}} | }} | ||
[[Category:Small Talk]] | [[Category:Small Talk]] | ||
+ | [[Category:OSGI]] |
Latest revision as of 04:18, 20 January 2022
Erko Knoll, Java Developer
December 30, 2011
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].
- ↑ 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:
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
Comments
Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License. |