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 >> >> >> > >
