geronimo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Rick McGuire <rick...@gmail.com>
Subject Re: Adding OSGi support to Geronimo spec jars.
Date Tue, 25 May 2010 10:17:50 GMT
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