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(a)bibbernet.org" <mailing(a)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(a)hibernate.org
>>>>>
http://hibernate.org
>>>>>
>>>> --
>>>> steve(a)hibernate.org
>>>>
http://hibernate.org
>>>>
>>> --
>>> steve(a)hibernate.org
>>>
http://hibernate.org
>>>
>> --
>> steve(a)hibernate.org
>>
http://hibernate.org
>>
> --
> steve(a)hibernate.org
>
http://hibernate.org
> ______________________________**_________________
> hibernate-dev mailing list
> hibernate-dev(a)lists.jboss.org
>
https://lists.jboss.org/**mailman/listinfo/hibernate-dev<https://lists...
>