1. Certain framework classes had to be part of boot delegation like Terracotta.
Added com.tc.* to org.osgi.framework.bootdelegation = \ in
/home/pg/thirdparty/springsource-dm-kernel-2.0.0.RELEASE/lib/java6-server.profile
2.Certain jboss imports were not getting part of package imports when jars were run through bundlor
So had to explicitly add these to bundles which required JMS(JBoss MQ) functionalities.
org.jboss.logging,
org.jboss.mq.referenceable,
org.jnp.interfaces,
org.jboss.util,
3. If there is any Custom Class Loader created in the code ,special care has to be taken to ensure that you set the custom class loaders parent to Bundle Classloader.
4. Special care needs to be taken that classes loaded through custom class loader should see all its imports and exports through its parent Bundles manifest.
5. Where ever class was loaded using Class.forname() we had to change it to ensure these where done through Thread Context Classloader where classes were laoded from other bundle.
6. Since we use jbossallclient.jar for JMS(Jboss MQ) we had issues as this was conflicting with packages in bootdelegation.
We could either solve this using explicit imports from system bundle(bundle 0).
a.
BootClasspath was exporting javax.management
Removed javax.management from jboss all client jar - Using bundlor excluded exports manifest
b.
Because jboss-allclient.jar also exports javax.jms which is also exported by javax.jms_1.1.0 bundle
Ensured jbossallclient.jar imports this and doesnt export it by changing manifest.
7.Since there were multiple bundles exporting org.apache.log4j , i had to explicitly mention bundle
symbolic names for the imports.
There were certain cases of cyclic dependency since it was legacy code.
Code in one bundle was initialized(spring application context) by code in another bundle. This cyclic dependency was solved by
explicitly marking this imports as optional(resolution="optional").
8. Wherever Application Context was read using regular expression had to change classpath: to classpath*: to ensure that all classpath resources are read.
Monday, August 9, 2010
Issues during migration of platform to OSGi
BootStrap Initialization GuideLines (For same code base to work in both OSGi and Non-OSGi environment)
During the migration of the platform into OSGi we had use cases where we needed the platform to work in both OSGi and non OSGi cases until the OSGi platform had stabilized.But our mail goal was we needed the same code based and packaging to work in both OSGi and non OSGi use cases.
We had come up with list of guidelines and conventions to achieve the same.
One major assumption was that in a non OSGi case there has to be a single application Context as against OSGi where there is application context
per bundle.
1. Separate xml files for OSGi service definitions and bean definitions.
2. Naming convention for spring xml files are as follows
<MODULE_NAME>-osgi-context.xml
<MODULE_NAME>-bean-context.xml
3.Naming convention for beans to be exported as services
Service Exposing side
<bean id="<MODULE_NAME>service" class="XXX.YYY.ZZZ"/>
<osgi:service ref=""<MODULE_NAME>service"" interface="bla.bla.IService"/>
Service Reference side
<osgi:ref interface=" bla.bla.IService" id="<MODULE_NAME>service"/>
Now this <MODULE_NAME>service can be used as regular bean.
This convention will help us run the same code base both in OSGi and non OSGi cases without changing these xmls. Note that in non OSgi cases we will initialize META-INF/spring/*-bean-context.xml. This will help in unit testing so that only required xmls can be initialized.
4. All spring bean definition files have to be in the following location - META-INF/spring/*
5. Ensure that in NON-OSGI cases individual products/services/modules do not independently initialize the application Context.There should be a independent initialization moduel which initilialises the app context across all products(jars) in the Vm based on some naming convention followed by the products.This will help easy wiring of beans across products which in other cases are done through OSGi services.Also the common module will expose a method in for accessing the beans present in the context.
6. Conventions have to be followed so that there are no same named beans across products as there is a single application context and objects will get overridden.
7.Boot Strap initialized xmls with this regular expression - [*-bean-context.xml]
[** Ensure that if any module in not following all these conventions the spring xml file has to be in any other folder than META-INF/spring ***[so that DM server doesnt initialize it ]* . *Ensure that in any case the spring xmls** are not initialized twice *[all the above guidelines are just to ensure that ] ***]
8. Property File initialization
Property placeholder config definitions containing files should be seperated from bean and osgi definition files and should be present in META-INF/spring folder.
Naming convention pgconfig-<MODULE_NAME>.properties
This will be initialized in bootstrap based on this expression in teh bootstrap propertyPlaceHolconfigurator : "classpath*:pgconfig*.properties"
{"classpath*:META-INF/spring/bootstrapconfig.xml","classpath*:/META-INF/spring/*-bean-context.xml"};
bootstrapconfig.xml contains --> <context:property-placeholder location="classpath*:pgconfig*.properties"/>
9.Avoid using Bundle Activator and instead use spring config (init method) for initialization as this will give us a common approach in both OSGi and Non OSGi cases.
OSGi Guidelines
1.Interaction between non-core bundles which can be hot-deployed should be through services (Interfaces).
2.Bundle should Import packages only for utilities, datatypes packages / classes and interfaces.
3.Interface and implementation should be separately bundled. The datatypes associated with service contracts can be bundled along with the interfaces.
4.All third party jars should be converted into bundles. Avoid using "external" in Bundle-classpath.
5.Avoid split package. Proper package structure should be followed. Two bundles should not have same package structure. We can have package structure like -.
6.TC shared classes to be bundled into separate bundles.
7.Avoid static variables and blocks.
8.Avoid Class.forname instead use Classloader.loadclass(). Class.forname may cause issues when bundle is hot deployed as initiating classloader caches the loaded class.
9.Classes present in separate dependent bundles should be loaded using TCCL. For example in jdbcframework all TYPE classes would be bundled with the respective bundle. These classes have to be loaded by jdbcframework bundle. Since classes present in respective bundle will not be visible to jdbcframewok bundle, so jdbcframework bundle has to use TCCL to load these classes.
10.Cyclic dependency should not exist between bundles.
11.Resource clean up - Each bundle / bean should clean up its resources like threads, sockets, cache, file handles, connections etc using its life cycle method (using "destroy" of bean or "stop" of "bundle activator")
12.Use the bean initialization method to initialize the properties and avoid putting initialization logic into constructor.
13.Native library to be loaded once. The code that is loading the native library should be part of core bundle which should not be hot deployed.
14.Prefer composition over inheritance.
15.Use AOP for common concerns - prefer compile time weaving over load-time / runtime weaving.
16.Use DM kernel when web container is not required.
17.Prefer import package over import-bundle.
18.All In-House jars should not have resolution optional for package imports.[Just to ensure that in production enviroment dependencies are resolved at deployment time rather than run time.]
19.All third party converted jars have resolution=optional.Else this pulled a not of other jars which were never used.
20.All log4j imports should have bundle symbolic name for lo4j to resolve properly to log4j instead of slf4j - something like
org.apache.log4j.*;bundle-symbolic-name="com.springsource.org.apache.log4j"
This can be added as part of Bundlor template during building the jar.
21.Manifest is generated at build time based on template(Spring Utility like Bundlor can be used for the same).