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. thanks 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: >> >> http://java.sun.com/javase/6/docs/api/java/util/ServiceLoader.html >> >> 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 >> >
