HHH-8761 Hibernate OSGi 4.3.0.CR1 can't discover services

This commit is contained in:
Brett Meyer 2013-12-02 14:24:58 -05:00
parent 8d67d64fc2
commit 5acd232e10
8 changed files with 106 additions and 77 deletions

View File

@ -8,11 +8,12 @@
<config name="org.apache.aries.transaction">
aries.transaction.recoverable = true
aries.transaction.timeout = 600
aries.transaction.howl.logFileDir = ${karaf.data}/txlog
aries.transaction.howl.maxLogFiles = 2
aries.transaction.howl.maxBlocksPerFile = 512
aries.transaction.howl.bufferSizeKBytes = 4
</config>
<bundle start-level="30">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1</bundle>
<bundle dependency="true" start-level="30">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1</bundle>
<bundle start-level="30">mvn:org.apache.aries.transaction/org.apache.aries.transaction.blueprint/1.0.0</bundle>
<bundle start-level="30">mvn:org.apache.aries.transaction/org.apache.aries.transaction.manager/1.0.1</bundle>
@ -28,6 +29,7 @@
<bundle start-level="30">mvn:org.apache.aries.jpa/org.apache.aries.jpa.container.context/1.0.2-SNAPSHOT</bundle>
<!-- JNDI -->
<bundle start-level="30">mvn:org.apache.aries/org.apache.aries.util/1.0.0</bundle>
<bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.api/1.0.0</bundle>
<bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.core/1.0.0</bundle>
<bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.rmi/1.0.0</bundle>

View File

@ -25,13 +25,13 @@ package org.hibernate.osgi;
import java.util.Dictionary;
import java.util.Hashtable;
import javax.persistence.spi.PersistenceProvider;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.internal.util.ClassLoaderHelper;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
@ -61,6 +61,9 @@ import org.osgi.framework.ServiceRegistration;
@SuppressWarnings("UnusedDeclaration")
public class HibernateBundleActivator implements BundleActivator {
private OsgiClassLoader osgiClassLoader;
private OsgiServiceUtil osgiServiceUtil;
private ServiceRegistration<?> persistenceProviderService;
private ServiceRegistration<?> sessionFactoryService;
@ -69,31 +72,38 @@ public class HibernateBundleActivator implements BundleActivator {
public void start(BundleContext context) throws Exception {
// build a ClassLoader that uses all the necessary OSGi bundles, and place it into
// a well-known location so internals can access it
final OsgiClassLoader osgiClassLoader = new OsgiClassLoader();
osgiClassLoader = new OsgiClassLoader();
osgiClassLoader.addBundle( FrameworkUtil.getBundle( Session.class ) );
osgiClassLoader.addBundle( FrameworkUtil.getBundle( HibernatePersistenceProvider.class ) );
ClassLoaderHelper.overridenClassLoader = osgiClassLoader;
osgiServiceUtil = new OsgiServiceUtil( context );
// Build a JtaPlatform specific for this OSGi context
final OsgiJtaPlatform osgiJtaPlatform = new OsgiJtaPlatform( context );
final OsgiJtaPlatform osgiJtaPlatform = new OsgiJtaPlatform( osgiServiceUtil );
final Dictionary properties = new Hashtable();
// In order to support existing persistence.xml files, register using the legacy provider name.
properties.put( "javax.persistence.provider", HibernatePersistenceProvider.class.getName() );
persistenceProviderService = context.registerService(
PersistenceProvider.class.getName(),
new OsgiPersistenceProviderService( osgiClassLoader, osgiJtaPlatform, context ),
new OsgiPersistenceProviderService( osgiClassLoader, osgiJtaPlatform, osgiServiceUtil ),
properties
);
sessionFactoryService = context.registerService(
SessionFactory.class.getName(),
new OsgiSessionFactoryService( osgiClassLoader, osgiJtaPlatform, context ),
new OsgiSessionFactoryService( osgiClassLoader, osgiJtaPlatform, osgiServiceUtil ),
new Hashtable()
);
}
@Override
public void stop(BundleContext context) throws Exception {
osgiClassLoader.stop();
osgiClassLoader = null;
osgiServiceUtil.stop();
osgiServiceUtil = null;
persistenceProviderService.unregister();
persistenceProviderService = null;
sessionFactoryService.unregister();

View File

@ -33,6 +33,7 @@ import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import org.hibernate.service.spi.Stoppable;
import org.osgi.framework.Bundle;
/**
@ -42,7 +43,7 @@ import org.osgi.framework.Bundle;
* @author Brett Meyer
* @author Tim Ward
*/
public class OsgiClassLoader extends ClassLoader {
public class OsgiClassLoader extends ClassLoader implements Stoppable {
// Leave these as Sets -- addClassLoader or addBundle may be called more
// than once if a SF or EMF is closed and re-created.
private Set<ClassLoader> classLoaders = new HashSet<ClassLoader>();
@ -210,10 +211,10 @@ public class OsgiClassLoader extends ClassLoader {
bundles.add( bundle );
}
/**
* Clear all resources.
*/
public void clear() {
@Override
public void stop() {
classLoaders.clear();
bundles.clear();
classCache.clear();
resourceCache.clear();
}

View File

@ -30,8 +30,6 @@ import org.hibernate.TransactionException;
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.osgi.framework.BundleContext;
/**
* Offers the JTA Platform provided by the OSGi container. The Enterprise
* OSGi spec requires all containers to register UserTransaction
@ -42,22 +40,22 @@ import org.osgi.framework.BundleContext;
public class OsgiJtaPlatform implements JtaPlatform {
private static final long serialVersionUID = 1L;
private BundleContext bundleContext;
private OsgiServiceUtil osgiServiceUtil;
/**
* Constructs a OsgiJtaPlatform
*
* @param bundleContext The OSGi bundle context
*/
public OsgiJtaPlatform(BundleContext bundleContext) {
this.bundleContext = bundleContext;
public OsgiJtaPlatform(OsgiServiceUtil osgiServiceUtil) {
this.osgiServiceUtil = osgiServiceUtil;
}
@Override
public TransactionManager retrieveTransactionManager() {
try {
final TransactionManager transactionManager = OsgiServiceUtil.getServiceImpl(
TransactionManager.class, bundleContext );
final TransactionManager transactionManager = osgiServiceUtil.getServiceImpl(
TransactionManager.class );
if (transactionManager == null) {
throw new TransactionException("Cannot retrieve the TransactionManager OSGi service!");
}
@ -71,8 +69,8 @@ public class OsgiJtaPlatform implements JtaPlatform {
@Override
public UserTransaction retrieveUserTransaction() {
try {
final UserTransaction userTransaction = OsgiServiceUtil.getServiceImpl(
UserTransaction.class, bundleContext );
final UserTransaction userTransaction = osgiServiceUtil.getServiceImpl(
UserTransaction.class );
if (userTransaction == null) {
throw new TransactionException("Cannot retrieve the UserTransaction OSGi service!");
}

View File

@ -27,6 +27,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceUnitInfo;
@ -41,9 +42,7 @@ import org.hibernate.jpa.boot.spi.IntegratorProvider;
import org.hibernate.jpa.boot.spi.StrategyRegistrationProviderList;
import org.hibernate.jpa.boot.spi.TypeContributorList;
import org.hibernate.metamodel.spi.TypeContributor;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleReference;
/**
@ -55,8 +54,8 @@ import org.osgi.framework.BundleReference;
public class OsgiPersistenceProvider extends HibernatePersistenceProvider {
private OsgiClassLoader osgiClassLoader;
private OsgiJtaPlatform osgiJtaPlatform;
private OsgiServiceUtil osgiServiceUtil;
private Bundle requestingBundle;
private BundleContext context;
/**
* Constructs a OsgiPersistenceProvider
@ -69,12 +68,12 @@ public class OsgiPersistenceProvider extends HibernatePersistenceProvider {
public OsgiPersistenceProvider(
OsgiClassLoader osgiClassLoader,
OsgiJtaPlatform osgiJtaPlatform,
Bundle requestingBundle,
BundleContext context) {
OsgiServiceUtil osgiServiceUtil,
Bundle requestingBundle) {
this.osgiClassLoader = osgiClassLoader;
this.osgiJtaPlatform = osgiJtaPlatform;
this.osgiServiceUtil = osgiServiceUtil;
this.requestingBundle = requestingBundle;
this.context = context;
}
// TODO: Does "hibernate.classloaders" and osgiClassLoader need added to the
@ -122,7 +121,7 @@ public class OsgiPersistenceProvider extends HibernatePersistenceProvider {
settings.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform );
final Integrator[] integrators = OsgiServiceUtil.getServiceImpls( Integrator.class, context );
final Integrator[] integrators = osgiServiceUtil.getServiceImpls( Integrator.class );
final IntegratorProvider integratorProvider = new IntegratorProvider() {
@Override
public List<Integrator> getIntegrators() {
@ -131,8 +130,8 @@ public class OsgiPersistenceProvider extends HibernatePersistenceProvider {
};
settings.put( EntityManagerFactoryBuilderImpl.INTEGRATOR_PROVIDER, integratorProvider );
final StrategyRegistrationProvider[] strategyRegistrationProviders = OsgiServiceUtil.getServiceImpls(
StrategyRegistrationProvider.class, context );
final StrategyRegistrationProvider[] strategyRegistrationProviders = osgiServiceUtil.getServiceImpls(
StrategyRegistrationProvider.class );
final StrategyRegistrationProviderList strategyRegistrationProviderList = new StrategyRegistrationProviderList() {
@Override
public List<StrategyRegistrationProvider> getStrategyRegistrationProviders() {
@ -141,7 +140,7 @@ public class OsgiPersistenceProvider extends HibernatePersistenceProvider {
};
settings.put( EntityManagerFactoryBuilderImpl.STRATEGY_REGISTRATION_PROVIDERS, strategyRegistrationProviderList );
final TypeContributor[] typeContributors = OsgiServiceUtil.getServiceImpls( TypeContributor.class, context );
final TypeContributor[] typeContributors = osgiServiceUtil.getServiceImpls( TypeContributor.class );
final TypeContributorList typeContributorList = new TypeContributorList() {
@Override
public List<TypeContributor> getTypeContributors() {

View File

@ -21,7 +21,6 @@
package org.hibernate.osgi;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;
@ -35,7 +34,7 @@ import org.osgi.framework.ServiceRegistration;
public class OsgiPersistenceProviderService implements ServiceFactory {
private OsgiClassLoader osgiClassLoader;
private OsgiJtaPlatform osgiJtaPlatform;
private BundleContext context;
private OsgiServiceUtil osgiServiceUtil;
/**
* Constructs a OsgiPersistenceProviderService
@ -47,15 +46,15 @@ public class OsgiPersistenceProviderService implements ServiceFactory {
public OsgiPersistenceProviderService(
OsgiClassLoader osgiClassLoader,
OsgiJtaPlatform osgiJtaPlatform,
BundleContext context) {
OsgiServiceUtil osgiServiceUtil) {
this.osgiClassLoader = osgiClassLoader;
this.osgiJtaPlatform = osgiJtaPlatform;
this.context = context;
this.osgiServiceUtil = osgiServiceUtil;
}
@Override
public Object getService(Bundle requestingBundle, ServiceRegistration registration) {
return new OsgiPersistenceProvider(osgiClassLoader, osgiJtaPlatform, requestingBundle, context);
return new OsgiPersistenceProvider( osgiClassLoader, osgiJtaPlatform, osgiServiceUtil, requestingBundle );
}
@Override

View File

@ -21,66 +21,89 @@
package org.hibernate.osgi;
import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.service.spi.Stoppable;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
/**
* Utilities for dealing with OSGi environments
*
*
* @author Brett Meyer
*/
public final class OsgiServiceUtil {
public class OsgiServiceUtil implements Stoppable {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( OsgiServiceUtil.class );
/**
* Locate all implementors of the given service contract in the given OSGi buindle context. Utilizes
* {@link ServiceTracker} (best practice, automatically handles a lot of boilerplate and error conditions).
*
* @param contract The service contract for which to locate implementors
* @param context The OSGi bundle context
* @param T[] The Java type of the service to locate
*
* @return All know implementors
*/
public static <T> T[] getServiceImpls(Class<T> contract, BundleContext bundleContext) {
final ServiceTracker<T, T> serviceTracker = new ServiceTracker<T, T>( bundleContext, contract, null );
try {
T[] services = (T[]) serviceTracker.getServices();
if (services != null) {
return services;
}
}
catch ( Exception e ) {
LOG.unableToDiscoverOsgiService( contract.getName(), e );
}
return (T[]) Array.newInstance(contract, 0);
private BundleContext context;
private Map<String, ServiceTracker> serviceTrackers = new HashMap<String, ServiceTracker>();
public OsgiServiceUtil(BundleContext context) {
this.context = context;
}
/**
* Locate the single implementor of the given service contract in the given OSGi buindle context. Utilizes
* {@link ServiceTracker#waitForService(long)}
*
* Locate all implementors of the given service contract in the given OSGi buindle context. Utilizes
* {@link ServiceTracker} (best practice, automatically handles a lot of boilerplate and error conditions).
*
* @param contract The service contract for which to locate implementors
* @param context The OSGi bundle context
* @param T[] The Java type of the service to locate
*
* @return All know implementors
*/
public static <T> T getServiceImpl(Class<T> contract, BundleContext bundleContext) {
final ServiceTracker<T, T> serviceTracker = new ServiceTracker<T, T>( bundleContext, contract, null );
public <T> T[] getServiceImpls(Class<T> contract) {
final ServiceTracker serviceTracker = getServiceTracker( contract.getName() );
try {
T[] services = (T[]) serviceTracker.getServices();
if ( services != null ) {
return services;
}
}
catch (Exception e) {
LOG.unableToDiscoverOsgiService( contract.getName(), e );
}
return (T[]) Array.newInstance( contract, 0 );
}
/**
* Locate the single implementor of the given service contract in the given OSGi buindle context. Utilizes
* {@link ServiceTracker#waitForService(long)}
*
* @param contract The service contract for which to locate implementors
* @param context The OSGi bundle context
* @param T[] The Java type of the service to locate
* @return All know implementors
*/
public <T> T getServiceImpl(Class<T> contract) {
final ServiceTracker serviceTracker = getServiceTracker( contract.getName() );
try {
return (T) serviceTracker.waitForService( 1000 );
}
catch ( Exception e ) {
catch (Exception e) {
LOG.unableToDiscoverOsgiService( contract.getName(), e );
return null;
}
}
private OsgiServiceUtil() {
private <T> ServiceTracker getServiceTracker(String contractClassName) {
if ( !serviceTrackers.containsKey( contractClassName ) ) {
final ServiceTracker<T, T> serviceTracker = new ServiceTracker<T, T>( context, contractClassName, null );
serviceTracker.open();
serviceTrackers.put( contractClassName, serviceTracker );
}
return serviceTrackers.get( contractClassName );
}
@Override
public void stop() {
for (String key : serviceTrackers.keySet()) {
serviceTrackers.get( key ).close();
}
serviceTrackers.clear();
}
}

View File

@ -32,11 +32,8 @@ import org.hibernate.integrator.spi.Integrator;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.metamodel.spi.TypeContributor;
import org.hibernate.service.ServiceRegistry;
import org.jboss.logging.Logger;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.wiring.BundleWiring;
@ -65,7 +62,7 @@ public class OsgiSessionFactoryService implements ServiceFactory {
private OsgiClassLoader osgiClassLoader;
private OsgiJtaPlatform osgiJtaPlatform;
private BundleContext context;
private OsgiServiceUtil osgiServiceUtil;
/**
* Constructs a OsgiSessionFactoryService
@ -77,10 +74,10 @@ public class OsgiSessionFactoryService implements ServiceFactory {
public OsgiSessionFactoryService(
OsgiClassLoader osgiClassLoader,
OsgiJtaPlatform osgiJtaPlatform,
BundleContext context) {
OsgiServiceUtil osgiServiceUtil) {
this.osgiClassLoader = osgiClassLoader;
this.osgiJtaPlatform = osgiJtaPlatform;
this.context = context;
this.osgiServiceUtil = osgiServiceUtil;
}
@Override
@ -108,18 +105,18 @@ public class OsgiSessionFactoryService implements ServiceFactory {
final BootstrapServiceRegistryBuilder builder = new BootstrapServiceRegistryBuilder();
builder.with( osgiClassLoader );
final Integrator[] integrators = OsgiServiceUtil.getServiceImpls( Integrator.class, context );
final Integrator[] integrators = osgiServiceUtil.getServiceImpls( Integrator.class );
for ( Integrator integrator : integrators ) {
builder.with( integrator );
}
final StrategyRegistrationProvider[] strategyRegistrationProviders
= OsgiServiceUtil.getServiceImpls( StrategyRegistrationProvider.class, context );
= osgiServiceUtil.getServiceImpls( StrategyRegistrationProvider.class );
for ( StrategyRegistrationProvider strategyRegistrationProvider : strategyRegistrationProviders ) {
builder.withStrategySelectors( strategyRegistrationProvider );
}
final TypeContributor[] typeContributors = OsgiServiceUtil.getServiceImpls( TypeContributor.class, context );
final TypeContributor[] typeContributors = osgiServiceUtil.getServiceImpls( TypeContributor.class );
for ( TypeContributor typeContributor : typeContributors ) {
configuration.registerTypeContributor( typeContributor );
}