[hibernate-dev] Concept of "service availability"
Steve Ebersole
steve at hibernate.org
Tue Aug 28 08:39:10 EDT 2012
The problem there is timing. Hibernate already has to be started in order
for "this" to work. But what "this" is doing is providing things Hibernate
needs to start. Its chicken-egg.
Interestingly this is very similar to the proposal Scott Marlow and I made
to the JPA group. And in fact that could be leveraged here. Essentially
that proposal was to make JPA bootstrapping a 2-phase process rather than
just a single "build it" phase. Here however that would mean (iiuc, and
please correct me if I do not) Hibernate needing 2 OSGi services. One that
builds the BootstrapServiceRegistry and MetadataSources/Configuration and
then another that builds the SessionFactory/EntityManagerFactory. The type
of things you discuss here would depends on the first service but somehow
need to be ordered before the second Hibernate service.
Of course assuming we even want to go that route in Hibernate source. The
other option is the OSGi container adding that bundle to the ClassLoader it
passes Hibernate so Hibernate can do the auto-discovery. Maybe I am
missing some options?
On Aug 27, 2012 2:32 PM, "mailing at bibbernet.org" <mailing at bibbernet.org>
wrote:
> OSGI has two classes/interfaces for dealing with Service Tracking -
> ServiceTracker and ServiceTrackerCustomizer, which could be used to create
> a OSGI-auto-discovery (and auto-cleanup)-Helper for hibernate:
>
> A simple skeleton could look like:
>
> package org.bibbernet.osgi;
>
> import org.osgi.framework.**ServiceReference;
> import org.osgi.util.tracker.**ServiceTrackerCustomizer;
>
> public class MyServiceTrackerCustomizer implements
> ServiceTrackerCustomizer {
> @Override
> public Object addingService(ServiceReference reference) {
> // a new service matching the criteria of the ServiceTracker can
> be added to the ServiceTracker
>
> // get the service object
> Object service = reference.getBundle().**
> getBundleContext().getService(**reference);
>
> // TODO: -> add service to hibernate service registry or if we we
> don't want if to get tracked,
> // return null
>
> // reference.getBundle() could be used to
>
> return service;
> }
>
> @Override
> public void modifiedService(**ServiceReference reference, Object
> service) {
> // nothing todo - only service properties are modified
> }
>
> @Override
> public void removedService(**ServiceReference reference, Object
> service) {
> // TODO: -> remove service from hibernate service registry
>
> // release this service reference
> reference.getBundle().**getBundleContext().**
> ungetService(reference);
> }
>
> }
>
> ------------------------------**-------
>
> package org.bibbernet.osgi;
>
> import org.osgi.framework.**BundleActivator;
> import org.osgi.framework.**BundleContext;
> import org.osgi.framework.Constants;
> import org.osgi.framework.Filter;
> import org.osgi.util.tracker.**ServiceTracker;
>
> public class MyActivator implements BundleActivator {
> private ServiceTracker myServiceTracker;
>
> @Override
> public void start(BundleContext context) throws Exception {
> // Create a LDAP-like-Filter which matches the interested services
> // or better the interested interfaces the service should implement
> Filter filter = context.createFilter("(" + Constants.OBJECTCLASS
> + "=xxx.yyy.zzz)");
> myServiceTracker = new ServiceTracker(context, filter,
> new MyServiceTrackerCustomizer());
>
> // start tracking
> myServiceTracker.open();
> }
>
> @Override
> public void stop(BundleContext context) throws Exception {
> // close ServiceTracker to ensure all service references get
> released
> if (myServiceTracker != null) {
> myServiceTracker.close();
> }
> }
>
> }
>
> The bundle implementing the service then simple needs to announce a
> service with one of the watched interfaces - once the service gets started,
> hibernate gets announced and could use either the service object itself or
> the bundle defining the service - with this approach you could also use the
> bundle's classloader to load classes with bundle.loadClass() or access
> resources within the bundle with bundle.findEntries(), etc.
>
> - Martin
>
> On 08/27/2012 07:34 PM, Steve Ebersole wrote:
>
>> Not sure this will actually help with OSGi in terms of auto-discovery
>> at all after thinking about it some more. The problem is that in order
>> for auto-discovery to happen, Hibernate would need to have visibility
>> into the jar defining the service anyway in order to auto-discovery it.
>>
>> On the bright side, I realized another benefit. It would finally be
>> possible to report the available types of a particular
>> service/strategy. For example, show me all the available
>> ConnectionProviders; all the available Dialects; etc...
>>
>>
>> On Fri 24 Aug 2012 08:51:09 PM CDT, Steve Ebersole wrote:
>>
>>> Would be nice to consolidate the notions of
>>> "ServiceAvailabililtyNotifier" and "ServiceContributor" (that I just
>>> added on metamodel). Such that a ServiceContributor would be able to
>>> regsiter the short names as well.
>>>
>>>
>>> On Thu 23 Aug 2012 03:58:10 PM CDT, Steve Ebersole wrote:
>>>
>>>> Ok, going to start working this up on master tomorrow. We will just
>>>> tackle the "going away" problem if/when it actually arises.
>>>>
>>>> On Tue 21 Aug 2012 05:55:31 PM CDT, Steve Ebersole wrote:
>>>>
>>>>> Everyone else ok with this idea?
>>>>>
>>>>> On Tue 21 Aug 2012 08:27:25 AM CDT, Steve Ebersole wrote:
>>>>>
>>>>>> Not so concerned about shutdown situations.
>>>>>>
>>>>>> More, imagine a custom ConnectionProvider implementation provided by
>>>>>> user. And the use case of upgrading that implementation "in flight".
>>>>>> I think thats the OSGi use case. And not so sure Hibernate should be
>>>>>> implementing this self healing. I guess it depends how deeply we want
>>>>>> to support the OSGi model above and beyond JSE/JEE
>>>>>>
>>>>>> Obviously a used ConnectionProvider just going away is going to render
>>>>>> the SessionFactory using it broken.
>>>>>>
>>>>>> On Tue 21 Aug 2012 08:22:11 AM CDT, Scott Marlow wrote:
>>>>>>
>>>>>>> On 08/20/2012 11:19 PM, Steve Ebersole wrote:
>>>>>>>
>>>>>>>> This ties together a few different discussions that have been
>>>>>>>> going on
>>>>>>>> simultaneously on the mailing list that I think are all related.
>>>>>>>>
>>>>>>>> Right now to configure certain services (select one impl over
>>>>>>>> another)
>>>>>>>> users generally give the FQN for that impl Class. For example to
>>>>>>>> use
>>>>>>>> C3P0 connection pooling users would say:
>>>>>>>>
>>>>>>>> hibernate.connection.provider_**class =
>>>>>>>> org.hibernate.service.jdbc.**connections.internal.**
>>>>>>>> C3P0ConnectionProvider
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> We have discussed why this is bad even before any of the OSGi
>>>>>>>> discussions and the solution we wanted to shoot for was that of
>>>>>>>> naming
>>>>>>>> "selectors" such that the user would instead say:
>>>>>>>>
>>>>>>>> hibernate.connection.provider_**class = c3p0
>>>>>>>>
>>>>>>>> And "c3p0" here would be interpreted to mean "instantiate and
>>>>>>>> configure
>>>>>>>> the
>>>>>>>> org.hibernate.service.jdbc.**connections.internal.**
>>>>>>>> C3P0ConnectionProvider
>>>>>>>>
>>>>>>>>
>>>>>>>> Class". But that still means a limited set of short name values
>>>>>>>> *and*
>>>>>>>> still gives us a problem (iiuc) under OSGi due to visibility.
>>>>>>>>
>>>>>>>> So what I propose instead is a way for service implementors to be
>>>>>>>> registered under a short name via discovery. The main piece to
>>>>>>>> this is
>>>>>>>> the "registry" (which is also a service under the
>>>>>>>> BootstrapServiceRegistry):
>>>>>>>>
>>>>>>>> interface AvailableServiceRegistry extends Service {
>>>>>>>> public<T> Class<? extends T>
>>>>>>>> findAvailableServiceImplemento**r(Class<T> serviceRole, String
>>>>>>>> selector);
>>>>>>>> }
>>>>>>>>
>>>>>>>> class AvailableServiceRegistryImpl
>>>>>>>> implements AvailableServiceRegistry,
>>>>>>>> ServiceRegistryAwareService {
>>>>>>>> private Map<Class,Map<String,Class>> availableImplementors =
>>>>>>>> ...;
>>>>>>>>
>>>>>>>> @Override
>>>>>>>> public<T> Class<? extends T>
>>>>>>>> findAvailableServiceImplemento**r(Class<T> serviceRole, String
>>>>>>>> selector) {
>>>>>>>> // purposely simplistic :)
>>>>>>>> return availableImplementors.get( serviceRole ).get(
>>>>>>>> selector );
>>>>>>>> }
>>>>>>>>
>>>>>>>> @Override
>>>>>>>> public void injectServices(**ServiceRegistryImplementor
>>>>>>>> serviceRegistry) {
>>>>>>>> final LinkedHashSet<**ServiceAvailabililtyNotifier>
>>>>>>>> notifiers =
>>>>>>>> serviceRegistry.getService( ClassLoaderService.class
>>>>>>>> ).loadJavaServices(
>>>>>>>> ServiceAvailabililtyNotifier.**class );
>>>>>>>> for ( ServiceAvailabililtyNotifier notifier : notifiers
>>>>>>>> ) {
>>>>>>>> for ( ServiceAvailabililty availability :
>>>>>>>> notifier.getAvailabilities() ) {
>>>>>>>> // again, purposely simplistic
>>>>>>>> Map<String,Class> serviceImplementors =
>>>>>>>> availableImplementors.get( availability.getRole() );
>>>>>>>> serviceImplementors.put(
>>>>>>>> availability.getSelector(),
>>>>>>>> availability.getImplementor()
>>>>>>>> );
>>>>>>>> }
>>>>>>>> }
>>>>>>>> }
>>>>>>>> }
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Outstanding question... Especially in OSGi, where service bundles
>>>>>>>> can be
>>>>>>>> added/removed, how do we best account for cleaning up no-longer
>>>>>>>> valid
>>>>>>>> references (even more importantly perhaps, what the hell does it
>>>>>>>> mean to
>>>>>>>> Hibernate when a ConnectionProvider implementation, for example,
>>>>>>>> that is
>>>>>>>> in use gets taken away?!?). Perhaps this is just where an
>>>>>>>> OSGi-specific
>>>>>>>> Hibernate ServiceRegistry implementation would come into play.
>>>>>>>>
>>>>>>>> Adding Jesper as we were talking about how to handle "quiescence
>>>>>>> shutdown" at the AS level, which sounds related. Once we take the
>>>>>>> ConnectionProvider away, I would expect the Hibernate
>>>>>>> session(s)/session factory to be broken. If/when the
>>>>>>> ConnectionProvider comes back, Hibernate would need to re-establish
>>>>>>> it. I'm thinking that we need a neutral (autonomic) API/SPI for
>>>>>>> attempting to re-establish the ConnectionProvider.
>>>>>>>
>>>>>>> For the most part, a "quiescence shutdown" of the AS, would mean
>>>>>>> keeping the ConnetionProvider alive until the end (of the planned
>>>>>>> shutdown). I'm thinking that being able to re-establish the
>>>>>>> ConnectionProvider would still be useful (for AS "quiescence
>>>>>>> shutdown"), especially if something goes wrong during the shutdown
>>>>>>> and
>>>>>>> manual intervention is needed.
>>>>>>>
>>>>>>> To me, the process of re-establishing the ConnectionProvider,
>>>>>>> could be
>>>>>>> labeled "self healing" (with the help of an autonomic API/SPI).
>>>>>>>
>>>>>>> --
>>>>>> steve at hibernate.org
>>>>>> http://hibernate.org
>>>>>>
>>>>> --
>>>>> steve at hibernate.org
>>>>> http://hibernate.org
>>>>>
>>>> --
>>>> steve at hibernate.org
>>>> http://hibernate.org
>>>>
>>> --
>>> steve at hibernate.org
>>> http://hibernate.org
>>>
>> --
>> steve at hibernate.org
>> http://hibernate.org
>> ______________________________**_________________
>> hibernate-dev mailing list
>> hibernate-dev at lists.jboss.org
>> https://lists.jboss.org/**mailman/listinfo/hibernate-dev<https://lists.jboss.org/mailman/listinfo/hibernate-dev>
>>
>
>
More information about the hibernate-dev
mailing list