geronimo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Jencks <>
Subject Re: Adding OSGi support to Geronimo spec jars.
Date Mon, 24 May 2010 22:49:01 GMT

On May 24, 2010, at 2:18 PM, David Blevins wrote:

> Having a look at this code and trying to figure out what the impact is on non-Geronimo
consumers who might be using OSGi.
> The geronimo-osgi-registry seems fairly small (just 10 classes including the inner classes)
and only using the OSGi core and compendium jars.
> I grocked from the description that it is used to look for a provider of the related
API jar, but didn't get some specifics.
>  1. Using EJB as an example, how does one say "I am a provider".  There is no "i am the
EJB container" interface to implement so what exactly are we looking for?

EJB is not an example.  the provider stuff works for 2 situations:

1. Service providers, where you have a META-INF/services/<interface-name> file containing
one line, the name of an implementing class in the current jar (bundle)  In this case, put
a SPI-Provider manifest header in and your class will be accessible to service consumers via
ProviderLocator.getServices(...) and related methods.

2. you need to make a class from your bundle available to others without them knowing about
or getting inside your bundle.  Put a Export-SPI-provider header in your manifest whose value
is a comma separated list of the classes you want to make available.  Consumers can load the
classes by calling ProviderLocator.loadClass(className);
>  2. What is the effect if the Activator is activated and no provider is found?

There are 2 activators.  I guess you mean the one in provider-locator?  If it isn't found,
then you fall back on normal classloader tricks for trying to find services classes.  These
won't normally work in an osgi environment.

david jencks

> Any insight?
> -David
> On Feb 26, 2010, at 5:35 AM, Rick McGuire wrote:
>> I've been taking a hard look at what Servicemix had done to the various spec jars
to make them better behaved in an OSGi environment.  This is being done with the intent of
adding similar support to the base Geronimo spec jars.  I'm taking a fresh approach to this
rather than necessarily just copying what Servicemix is doing.  I've found a number of interesting
things during this process, so I thought it would be good to do a brain dump of what I've
found and how I'm planning on implementing this.
>> The basics of the Servicemix approach is to add an Activator to each of the spec
bundle that maintains a registry of factory class information.  Each spec bundle have a listener
that tracks bundle activity and will check for factory information in the META-INF/services
directory of each started bundle.  Each started bundle has its own listener and own copy of
the factory information.  The registry information is used in the various places spec code
needs to dynamically load provider classes for different subsystems.  For example, loading
a persistence provider.  All classloading is done lazily when a request is made for a matching
class file.  The spec code retrieves the loaded classes and handles all details of creating
the instances using the retrieved classes.
>> Jarek Gawor suggested I might want to take a look at what the Aries project had for
processing the META-INF/services information.  This test implementation, called "spifly",
uses the OSGi extender pattern to inspect the META-INF/services directories and uses that
information to automatically register services in the OSGi services registry.  In this situation,
the classes are eagerly loaded, instances are created (which requires a no-argument constructor)
and the services are registered in the OSGi registry.
>> So, we have one set of information, but two different interpretations of how this
information should be used.  The new implementation I was working on was using the extender
pattern to maintain a single registry of this information that could be accessed using a provider
registry service.  This would have a single listener, with a single version of the registry,
and each bundle that required the service would just have a thin accessor layer to call the
registry service if it was available.  This is essentially combining the approaches used by
Servicemix and spifly.
>> However, I was becoming increasingly concerned about this dual interpretation of
the META-INF/services information, and started researching what conventions were in play with
this.  What I found was there is a new feature in Java SE 6 called the ServiceLoader:
>> The service loader uses the META-INF/services information to create mappings between
interface classes and concrete implementations of these interfaces.  This is similar to the
spifly approach, but there are a few fundamental differences.  The biggest difference is that
each instance of the ServiceLoader class will instantiate a new instance of the implementation
class when needed.  For spifly, there is only ever a single instance of the service created.
 Both spifly and Servicemix are only processing the first line of the services files, while
the ServiceLoader defines that an individual definition file can define a one-to-many interface/implementation
mapping.  So, now we're up to 3 different interpretations of the META-INF/services information.
>> Looking a little deeper into how Servicemix was using this information, I found that
it was bending the intent of the META-INF/services information a bit.  The ServiceLoader definitions
are intended to create mappings between interface classes and implementers of a given interface.
 The service mix lookups were being used to directly resolve implementation classes.  To do
this, the service definition file would need to use the same class as both interface name
and implementer class.  This has a nice side effect of allowing particular implementations
to be selectively replaced, but this is a usage that could cause problems if the information
was picked up by either spifly or ServiceLoader.  This violated the fundamental assumption
that this information defined interface-to-implementation mappings.
>> In addition, the javamail changes were using this information to define protocol-to-provider
mappings.  For example, an "smtp" javamail provider implementation class.  In this case, the
mapping did not even start with the name of a Java class.  This definitely conflicted with
both spifly and ServiceLoader.
>> A lot of these difficulties go away if I decouple the Servicemix semantics by moving
the information to a different location so that we're not seeing multiple interpretations
of what the data in META-INF/services means.  The code I'm working on will be looking in OSGI-INF/providers,
and the mapping information is defined in terms of a provider identifier-to-provider class
mapping.  This is really is the interpretation used by the Servicemix code, but removes the
conflicting usage.
>> Rick

View raw message