Friday, October 23, 2009

Distibuted OSGi


DOSGi helps in interaction between services which exists in different services in the same way as when they are co-hosted.

Specifications for DOSGi: http://www.osgi.org/Specifications/HomePage

Well Known implementations are

Apache CXF implementation : http://cxf.apache.org/distributed-osgi.html

Eclipse ECF implementation : http://wiki.eclipse.org/Distributed_OSGi_Services_with_ECF

Apache Tuscany implementation


Apache CXF implementation
-------------------------

http://cxf.apache.org/roadmap.html : Nothing more other than web services even in roadmap.

DOSGi Webinar : http://download.progress.com/open/adobe/prc/psc/042809_fuse_osgi_webinar/index.htm

Some answers to the questions on the webinar

http://coderthoughts.blogspot.com/2009/05/questions-from-rfc-119-webinar.html

Exposing service -has to mention the interace which can be remotely invoked.

Based on this Apache CXF creates a wsdl - which can be called by any web service client

(RFC 119) complaint discovery service - http://cxf.apache.org/dosgi-discovery.html
---------------------------------------
If discovery service is present - it will aurmtically detect , else we need to statically configure end points.

To enable automatic hooking of these remote services we need to have Service Registry Hooks -OSGi 4.2 spec(RFC 126)

Service Registry Hook Functionality(RFC 126 -OSGi spec 4.2) -Should be part of OSgi Core

Service Hook Functionalities
----------------------------

1. On Demand Registration of remote Services

2. Limiting Service Visibility

3. Service Proxification




How does it work [Refer Attached Diagram]
-----------------
Interface bundles are present in both the interacting containers.

Both teh containers have RFC 119 complaint discovery service and RFC 126 complaint registry hook

Service implementer registers with teh service with local OSGi container.

If this service has to be remotely accessed it needs to mention the property of remote interface.

Once this interface is mentioned the Discovery Service comes into picture which creates a remote end point for the service

It also register some meta data info with teh discovery service.

On the client side(in another Vm) when it expresses its interest in consuming this service , this information is passed
from the local osgi registry into the Registry hook which consults the discover service.

Now the discovery service will see if any one has remotely registered and if so creates a proxy for this service which will be reffered by the local osgi registry.

Current Apache CXF doesnt have either discovery service nor registry hook , hence end points need to be statically mentioned.

Apache is working on a discovery service under withthe ZooKepper Project

http://hadoop.apache.org/zookeeper/

http://wiki.apache.org/hadoop/ZooKeeper/ProjectDescription


[I think ZooKeeper is an alternative to Jgroups for sharing registry information between two nodes]

Working Demo is present in the link I have mentioned above, but without discovery service or service registry hook and it has a web service based implementaion for communication.

So to use Apache CXF we need minimum of these version - Equinox 3.5 / Felix 1.4.1 or later

Dmversion of equinox currntly- Dm 1.0.2 uses equinox 3 and 2.0 version uses equinox 3.5

Eclipse ECF implementation
----------------------------

http://wiki.eclipse.org/Distributed_OSGi_Services_with_ECF

http://eclipsesource.com/blogs/2008/12/19/rfc-119-and-ecf-part-1/

http://wiki.eclipse.org/Getting_Started_with_ECF%27s_RFC119_Implementation

Here changing the protocol for communication between services in diffrent VM's looks very simple

They claim to support the following protocols

Distribution

* r-OSGi (http) -r-OSGi is based upon a TCP-based protocols
* XMPP
* ECF Generic
* Skype
* Java Messaging Service (JMS)
* JavaGroups

Dynamic registring of the Spring Bean to the Application Context

I have come across use cases where we need to dynamicaly create a bean and register it to the Application Context rather than creating it through xmls during initialization.

This api doc helps to do that

http://static.springsource.org/spring/docs/2.5.6/api/org/springframework/context/support/StaticApplicationContext.html#registerSingleton%28java.lang.String,%20java.lang.Class%29

Usecase Ref:

http://forum.springsource.org/showthread.php?t=76490

Useful Blog

http://www.carlobonamico.com/blog/2008/01/22/how-to-dynamicallyprogrammatically-define-spring-beans/

Spring Integration Router Configuration

Just came across a router config in which based on the header it will route the messages to respective channels-provided both header and channel

l have same names .(No static definition required in application xmls)


1. Configuration where mapping of header values to channels is required

<header-value-router input-channel="routingChannel" header-name="testHeader">

<mapping value="someHeaderValue" channel="channelA" />

<mapping value="someOtherHeaderValue" channel="channelB" />

</header-value-router>


2. Configuration where mapping of header values is not required if header values themselves represent the channel names

<header-value-router input-channel="routingChannel" header-name="testHeader"/>

Ways to get Spring ApplicationContext -In Spring DM

Couple of other ways to get hold of ApplicationContext (rather than doing new ClasspathXmlApplicationContext()).

1. Create a bean which is ApplicationContextAware


MessageChannel msgCh = (MessageChannel)ApplicationContextHolder.getApplicationContext().getBean("eventChannel");

msgCh.send(msg);


public class ApplicationContextHolder implements ApplicationContextAware {

private static ApplicationContext appContext;

public void setApplicationContext(ApplicationContext ctx)

throws BeansException {

System.out.println("*** ApplicationContextHolder::setApplicationContext()...");

ApplicationContextHolder.appContext = ctx;

}

public static ApplicationContext getApplicationContext() {

return appContext;

}

}


This one is in the case of Spring DM

2. Accessing the ApplicationContext from BundleContext (By default every bundle publishes the Application Context as a Service).



public static ApplicationContext getApplicationContext() {

if (appCtx == null) {

try {

ServiceReference[] svcRef = bundleContext.getAllServiceReferences("org.springframework.context.ApplicationContext", "(org.springframework.context.service.name=ContextInClass)"); // Service name is the Bundle Symbolic Name

ServiceReference ref = svcRef[0];

appCtx = (ApplicationContext) bundleContext.getService(ref);

} catch (Exception e) {

e.printStackTrace();

}

}

return appCtx;

}

This is the preferred approach if you wish to use the Application Context from another bundle.

Java Monitoring Guidelines

Use the following command which gives the process size.

ps auxwww | grep java

Process size - Max size is 3 Gb on unix and 4 gb on solaris

[process size includes stacks,native code,therads created etc]

user 6451 180 30.2 [1416444-->process_size] 626888 ?

A check on the process size is critical because when there are leaks this gradually increases and finally the server crashes.

Command to get the Memory Details

jmap -dump:live,format=b,file=histo.bin . this creates a file with name histo.bin

Command to generate Report Using JHat

jhat -J-mx256m histo.bin [histo.bin can be pscp'ed to windows machine and this command can be executed]

This starts a server gives a port number at the command line. using this url the details can be viewed through a explorer

Consequently the following command can be used to get the current memory picture in the JVM.

jmap -histo:live [process-id] > [filename].txt

The following command is also useful to understand the java heap and the GC behavior

jstat -gcutil 2361 1s

UseFull Vm parametres

-XX:+HeapDumpOnOutOfMemoryError
-XX:+PrintGCTimeStamps
-XX:+PrintGCDetails
-XX:+PrintGCApplicationStoppedTime
-verbose:gc
-XX:ErrorFile=/location/error.log
-XX:HeapDumpPath=/location/heap_dump.hprof

jstack [process_id] or kill -3 [process_id] can be used to get the thread dump of the process.

Saturday, August 8, 2009

Thread Context ClassLoader / Buddy ClassLoading in OSGi.

Bundles like Struts,hibernate,Spring need to instantiate classes in custom application bundle.In normal cases this can be directly done because there is a single class space(single class loader).

Consider a case where there are more than one class loaders .Lets take a simple case in which the struts/spring jar is kept under tomcat common lib and your application classes are under the web-inf lib. These two are jars now are loaded by two different classloaders.
Tomcat common lib class loader being the parent of tomcat web-inf/lib class loader.Also classloader of struts jar cannot see application classes in web-inf lib.

Now how can struts/spring see application classes ?

To solve such problems java Java came up with a solution called Thread Context Class Loader(TCCL). Thread context class loader was introduced in Java 2 to enable frameworks running in application servers to access the "right" application class loader for loading application classes.

This is accessed using Thread.getCurentThread.getContextClassloader().Its as simple as, It is the classloader associated with each thread.There are setter methods which can be called to set this TCCL.

By the definition in tomcat the TCCL is set to the context class loader from where the thread begins.So TCCL has the classloader visibity of web-inf lib,solving our problem.

Now since the thread started from that application ,these third party jars can use TCCL to instantiate application classes. The control starts from our application bundle and then flow moves to some third party bundle like struts or hibernate,which internally in their
source code use TCCL to instantiate our classes.

TCCL becomes slightly more complicated in the case of OSGI.

I have a small POC for the Reflection based Class loading using TCCL.

Source Code : http://www.4shared.com/file/123739699/3b6dd30e/TCCLosgi.html

Bundle 3(Core bundle) – has reflection code to instantiate application classes. Uses TCCL to instantiate classes.

Bundle 2 (Service) –Using the core bundle to instantiate its classes (imports bundle 3 classes directly)

Bundle 1 (Application) – uses the OSGi service provided by bundle 2.


Control Flow:

Bundle 1 makes a OSGi service call to bundle 2.

Bundle 2 now uses core to instantiate its(bundle 2) classes.

Result: ClassNotFoundException

Reason:

Bundle 2 is able to instantiate classes only in Bundle 3 and not in Bundle.

This is because TCCL has visibility only to class loader from where the thread started.

Solution:

1. PAR(Spring DM solution)

Spring Dm comes with a concept of PAR,which is grouping of bundles.All bundles inside the PAR will contribute together to form a synthetic context.And hence bundles inside it have visibility to all others exisiting inside it.

http://blog.springsource.com/2008/05/02/running-spring-applications-on-osgi-with-the-springsource-application-platform/

2.Buddy Class Loading (this is equinox specific solution and not part of OSGi spec)

http://wiki.eclipse.org/index.php/Context_Class_Loader_Enhancements#Buddy_Class_Loading


Now bundle 3, that is the core bundle can be a buddy to bundle 2 (service bundle).

Syntax

In bundle 3 manifest we need to mention Buddy-Policy :registered

In bundle 2 manifest we mention Eclipse-RegisterBuddy : bundle symbolic name


Now at run time we can add new slots(Bundle 4) which registers itself as a buddy to bundle 2(core) ,without affecting any other bundles.

3. We can set the TCCL in bundle 2 to bundle class loader when the deligation goes through it.I guess TCCL may not be the right approach(not good to tamper the class loader prior to making calls across bundles).

We can choose a solution based on the requirement.






Cyclic Dependency in OSGi & Dynamic Imports

Since in OSGi we have multiple class loaders as compared to single Class Loader case ,there may be occur the problem of cyclic dependency.

This cyclic dependency may not be compile type instead most of the cases its runtime. Some piece of code may try to instantiate classes in another bundle using reflection.

Consider such a example

Bundle A requires Bundle B at runtime and vice versa.

Bundle A has to mention import in its manifest for bundle B classes and Bundle B has to do the same for Bundle A classes.

Now in such case when Bundle A is deployed it says class not found for Bundle B classes,hence to solve this we need to write

Import Package : package-from-BundleB;resolution=optional

Now Bundle A doesn't give error . Follow with deployment of Bundle B. Later when bundle A tries to access classes in Bundle B it says ClassNotFoundException.

This is because when we mentioned resolution=optional , it doesn't try to link again when class is requested. And the linking happens only initial time.

To solve this we need to use Dynamic imports in such cases.

This cyclic dependency in most of the cases can be solved using Thread Context Class Loader or Eclipse Buddy Class Loading(refer next blog for details),and there will rarely occur a case to use dynamic imports.

 
Free Domain Names @ .co.nr!