geronimo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Blevins <david.blev...@visi.com>
Subject Re: Adding OSGi support to Geronimo spec jars.
Date Tue, 25 May 2010 22:29:54 GMT
Hey I got an idea.  Since we're already modding spec jars, some of which will have to be installed
into the endorsed dir directory anyway,....

Why don't we just mod the java.util.ServiceLoader class to do this optional OSGi search?

You know, the whole one to rule them all approach.  Then we don't have to mod each spec jar
and it would work even for SAXParserFactory and other Java SE searches.

And people could opt-in. "If you want this functionality, install this jar to your endorsed
dir"


-David


On May 25, 2010, at 3:17 AM, Rick McGuire wrote:

> On 5/24/2010 8:06 PM, David Blevins wrote:
>> On May 24, 2010, at 3:49 PM, David Jencks wrote:
>> 
>>   
>>> On May 24, 2010, at 2:18 PM, David Blevins wrote:
>>> 
>>>     
>>>> 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:
>>>     
>> The activator and locator were added to the EJB spec jar.  Was that a mistake?
>>   
> I don't believe it was. There are two sides to this generally. The first side is the
role played by the specs, which generally need to locate a provider. Typically, the specification
defines a search path that generally searches for 1) a META-INF/services definition, 2) a
class defined in a properties file, and 3) a system property. Depending on the age of the
specification, the order in which these 3 are searched will vary, and the newest java ee components
only define step 1. Generally, this search order will resolve to the name of a provider class
that the API code will then instantiate to create the provider instance.
> 
> The second role is that of the provider class itself. Typically, a provider jar would
use the META-INF/services mechanism to advertise its availability. The java EE defined mechanism
for locating the provider is to search the classpath for an appropriate META-INF/services
file and load the first definition it locates.
> 
> In an OSGi environment, there are a number of problems associated with the "search the
classpath" step, so the ProviderLocator was created. There are two pieces to this:
> 
> 1) A provider registry. This is an extender that watches new bundles being activated,
and if the bundle contains the appropriate metadata, then then the services it exports are
made part of a framework-wide registry.
> 
> 2) The ProviderLocator. This is how APIs that need to resolve providers access the registry
information. The provider registry is an OSGi service, so the ProviderLocator needs a bundle
context instance to resolve the service instance. The Activator manages obtaining the bundle
context at activation and setting up a service tracker to give access to the registry service.
The ProviderLocator code manages the details of locating a loading a service instance and
will revert to classic classpath behavior if used outside of an OSGi environment.
> 
> There are two different models in play here for locating a provider instance. In the
first model, the API has been handed the name of the desired provider directly as a class
name. The API could would then attempt to instantiate that class directly (typically by using
the thread context classloader). In the second model, an appropriate META-INF/services definition
is located using the interface that the provider is expected to implement as the search key.
The services definition file provides a mapping to the provider class name, which is then
loaded and instantiated. In terms of my search paths defined in the first paragraph above,
1) is the META-INF/services mode, and 2) and 3) are the first mode of direct loading.
> 
> The provider registry can handle either of these locator modes. If your provider is already
using a META-INF/services model, then the registry then generally all you need to do is add
an SPI-Provider header to your jar file. Openejb should have this already, but the EJB3 spec
code is not strictly following the EJB specification for locating the provider, so it is possible
it is not.
> 
> If your provider needs to be located via a direct load mechanism where the class name
is provided, then you can use an Export-Service-Provider header to advertise your provider
class so the ProviderLocator code can locate it by name.
> 
> So, what should the openejb code be doing? The best solution would be to create the META-INF/services
file that maps EJBContainerProvider to your implementation class and add the SPI-Provider
header. Unfortunately, there is a gotcha here, in the form of this Jira:
> 
> https://issues.apache.org/jira/browse/GERONIMO-5186
> 
> The EJB specification says the EJBContainerProvider lookup mechanism should use only
the META-INF/services mechanism, and for each definition if finds, it should instantiate the
service instance and call createEJBContainer() passing the property bundle that was passed
to EJBContainer.createEJBContainer(). The provider instance is then responsible for determining
if it is the appropriate provider by examining the provider name in the properties bundle.
Here's the wording from the spec:
> 
> The EJBContainer bootstrap class will locate all of the container providers by their
provider configuration files and call EJBContainerProvider.createEJBContainer(Map<?, ?>)
on them in turn until an appropriate backing provider returns an EJBContainer. A provider
may deem itself as appropriate for the embeddable application if any of the following are
true :
> •The javax.ejb.embeddable.provider property was included in the Map passed to createEJBContainer
and the value of the property is the provider's implementation class.
> •No javax.ejb.embeddable.provider property was specified.
> If a provider does not qualify as the provider for the embeddable application, it must
return null when createEJBContainer is invoked on it.
> 
> Unfortunately, the search mechanism in the Geronimo EJBContainer class short-cuts this
mechanism and checks the provider property directly and uses that information to directly
load the provider class rather than using the META-INF/services mechanism. I'm guessing this
is the normal mode of operation for openejb. In that case, you need to be using the Export-Service-Provider
header.
> 
> I would really like to fix this Jira, but this requires a bit of rework in the EJBContainer.createEJBContainer()
method. Rework that would break OpenEJB as it exists in its current state. I think the issues
in OpenEJB need to be fixed first, then the spec behavior can be fixed. Here's what I think
needs to be done in OpenEJB:
> 
> 1) Add the META-INF/services definition mapping the EJBContainerProvider to the implementation
class.
> 2) Add the SPI-Provider header to opt in to the services registry for this definition.
> 3) Add the Export-Service-Provider header to the bundle to also export the provider class
explicitly.
> 4) Ensure that the implementation of createEJBContainer() properly implements the behavior
of returning null if it is not the correct provider for the provided configuration.
> 
> Assuming this is done, then the spec class can be changed to be compliant without breaking
openejb. During the transitional period, the Export-ServiceProvider header will allow the
provider class to be loaded using the current spec implementation, and after the Jira is fixed,
META-INF/services mapping will allow it to revert to the specified mechanism.
> 
> Rick
> 
>> 
>> -David
>> 
>> 
>>   
> 
> 


Mime
View raw message