Permalink
Browse files

HHH-7620 - allow ValidatorFactory to be passed into EntityManagerFact…

…oryBuilder : reordered EMF builder processing to better allow late ValidatorFactory and DataSource (HHH-7621) passing
  • Loading branch information...
1 parent 35b9a9d commit d0f88347af9048e6756dc8a7b277495b7430563b @sebersole sebersole committed Sep 20, 2012
View
13 hibernate-core/src/main/java/org/hibernate/boot/registry/StandardServiceRegistryBuilder.java
@@ -90,6 +90,10 @@ public StandardServiceRegistryBuilder(BootstrapServiceRegistry bootstrapServiceR
return initiators;
}
+ public BootstrapServiceRegistry getBootstrapServiceRegistry() {
+ return bootstrapServiceRegistry;
+ }
+
/**
* Read settings from a {@link Properties} file. Differs from {@link #configure()} and {@link #configure(String)}
* in that here we read a {@link Properties} file while for {@link #configure} we read the XML variant.
@@ -214,6 +218,15 @@ public ServiceRegistry buildServiceRegistry() {
}
/**
+ * Temporarily exposed since Configuration is still around and much code still uses Configuration. This allows
+ * code to configure the builder and access that to configure Configuration object (used from HEM atm).
+ */
+ @Deprecated
+ public Map getSettings() {
+ return settings;
+ }
+
+ /**
* Destroy a service registry. Applications should only destroy registries they have explicitly created.
*
* @param serviceRegistry The registry to be closed.
View
392 ...anager/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java
@@ -68,6 +68,7 @@
import org.hibernate.SessionFactoryObserver;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.cfg.NamingStrategy;
@@ -130,6 +131,12 @@
public static final String JANDEX_INDEX = "hibernate.jandex_index";
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // Explicit "injectables"
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private Object validatorFactory;
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
private final PersistenceUnitDescriptor persistenceUnit;
private final SettingsImpl settings = new SettingsImpl();
private final StandardServiceRegistryBuilder serviceRegistryBuilder;
@@ -148,8 +155,6 @@
private static EntityNotFoundDelegate jpaEntityNotFoundDelegate = new JpaEntityNotFoundDelegate();
- private Object validatorFactory;
-
private static class JpaEntityNotFoundDelegate implements EntityNotFoundDelegate, Serializable {
public void handleEntityNotFound(String entityName, Serializable id) {
throw new EntityNotFoundException( "Unable to find " + entityName + " with id " + id );
@@ -176,8 +181,6 @@ public EntityManagerFactoryBuilderImpl(PersistenceUnitDescriptor persistenceUnit
this.configurationValues = mergePropertySources( persistenceUnit, integrationSettings, bootstrapServiceRegistry );
// add all merged configuration values into the service registry builder
this.serviceRegistryBuilder.applySettings( configurationValues );
- // And being processing those configuration values
- processProperties( bootstrapServiceRegistry );
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Next we do a preliminary pass at metadata processing, which involves:
@@ -189,6 +192,8 @@ public EntityManagerFactoryBuilderImpl(PersistenceUnitDescriptor persistenceUnit
// 3) building "metadata sources" to keep for later to use in building the SessionFactory
metadataSources = prepareMetadataSources( jandexIndex, collectedManagedClassNames, scanResult, bootstrapServiceRegistry );
+ withValidatorFactory( configurationValues.get( AvailableSettings.VALIDATION_FACTORY ) );
+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// push back class transformation to the environment; for the time being this only has any effect in EE
// container situations, calling back into PersistenceUnitInfo#addClassTransformer
@@ -487,133 +492,6 @@ private void processHibernateConfigurationElement(
}
}
- private void processProperties(BootstrapServiceRegistry bootstrapServiceRegistry) {
- applyJdbcConnectionProperties();
- applyTransactionProperties();
-
- // this check is needed for tests. Second form happens later (mainly against the explicitly passed validator)
- // when building EMF...
- final Object validationFactory = configurationValues.get( AvailableSettings.VALIDATION_FACTORY );
- if ( validationFactory != null ) {
- BeanValidationIntegrator.validateFactory( validationFactory );
- }
-
- // flush before completion validation
- if ( "true".equals( configurationValues.get( Environment.FLUSH_BEFORE_COMPLETION ) ) ) {
- serviceRegistryBuilder.applySetting( Environment.FLUSH_BEFORE_COMPLETION, "false" );
- LOG.definingFlushBeforeCompletionIgnoredInHem( Environment.FLUSH_BEFORE_COMPLETION );
- }
-
- for ( Object oEntry : configurationValues.entrySet() ) {
- Map.Entry entry = (Map.Entry) oEntry;
- if ( entry.getKey() instanceof String ) {
- final String keyString = (String) entry.getKey();
-
- if ( AvailableSettings.INTERCEPTOR.equals( keyString ) ) {
- sessionFactoryInterceptor = instantiateCustomClassFromConfiguration(
- entry.getValue(),
- Interceptor.class,
- bootstrapServiceRegistry
- );
- }
- else if ( AvailableSettings.SESSION_INTERCEPTOR.equals( keyString ) ) {
- settings.setSessionInterceptorClass(
- loadSessionInterceptorClass( entry.getValue(), bootstrapServiceRegistry )
- );
- }
- else if ( AvailableSettings.NAMING_STRATEGY.equals( keyString ) ) {
- namingStrategy = instantiateCustomClassFromConfiguration(
- entry.getValue(),
- NamingStrategy.class,
- bootstrapServiceRegistry
- );
- }
- else if ( AvailableSettings.SESSION_FACTORY_OBSERVER.equals( keyString ) ) {
- suppliedSessionFactoryObserver = instantiateCustomClassFromConfiguration(
- entry.getValue(),
- SessionFactoryObserver.class,
- bootstrapServiceRegistry
- );
- }
- else if ( AvailableSettings.DISCARD_PC_ON_CLOSE.equals( keyString ) ) {
- settings.setReleaseResourcesOnCloseEnabled( "true".equals( entry.getValue() ) );
- }
- else if ( keyString.startsWith( AvailableSettings.CLASS_CACHE_PREFIX ) ) {
- addCacheRegionDefinition(
- keyString.substring( AvailableSettings.CLASS_CACHE_PREFIX.length() + 1 ),
- (String) entry.getValue(),
- CacheRegionDefinition.CacheType.ENTITY
- );
- }
- else if ( keyString.startsWith( AvailableSettings.COLLECTION_CACHE_PREFIX ) ) {
- addCacheRegionDefinition(
- keyString.substring( AvailableSettings.COLLECTION_CACHE_PREFIX.length() + 1 ),
- (String) entry.getValue(),
- CacheRegionDefinition.CacheType.COLLECTION
- );
- }
- else if ( keyString.startsWith( AvailableSettings.JACC_PREFIX )
- && ! ( keyString.equals( AvailableSettings.JACC_CONTEXT_ID )
- || keyString.equals( AvailableSettings.JACC_ENABLED ) ) ) {
- addJaccDefinition( (String) entry.getKey(), entry.getValue() );
- }
- }
- }
- }
-
- private void applyJdbcConnectionProperties() {
- if ( persistenceUnit.getJtaDataSource() != null ) {
- serviceRegistryBuilder.applySetting( Environment.DATASOURCE, persistenceUnit.getJtaDataSource() );
- }
- else if ( persistenceUnit.getNonJtaDataSource() != null ) {
- serviceRegistryBuilder.applySetting( Environment.DATASOURCE, persistenceUnit.getNonJtaDataSource() );
- }
- else {
- final String driver = (String) configurationValues.get( AvailableSettings.JDBC_DRIVER );
- if ( StringHelper.isNotEmpty( driver ) ) {
- serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.DRIVER, driver );
- }
- final String url = (String) configurationValues.get( AvailableSettings.JDBC_URL );
- if ( StringHelper.isNotEmpty( url ) ) {
- serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.URL, url );
- }
- final String user = (String) configurationValues.get( AvailableSettings.JDBC_USER );
- if ( StringHelper.isNotEmpty( user ) ) {
- serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.USER, user );
- }
- final String pass = (String) configurationValues.get( AvailableSettings.JDBC_PASSWORD );
- if ( StringHelper.isNotEmpty( pass ) ) {
- serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.PASS, pass );
- }
- }
- }
-
- private void applyTransactionProperties() {
- PersistenceUnitTransactionType txnType = PersistenceUnitTransactionTypeHelper.interpretTransactionType(
- configurationValues.get( AvailableSettings.TRANSACTION_TYPE )
- );
- if ( txnType == null ) {
- txnType = persistenceUnit.getTransactionType();
- }
- if ( txnType == null ) {
- // is it more appropriate to have this be based on bootstrap entry point (EE vs SE)?
- txnType = PersistenceUnitTransactionType.RESOURCE_LOCAL;
- }
- settings.setTransactionType( txnType );
- boolean hasTxStrategy = configurationValues.containsKey( Environment.TRANSACTION_STRATEGY );
- if ( hasTxStrategy ) {
- LOG.overridingTransactionStrategyDangerous( Environment.TRANSACTION_STRATEGY );
- }
- else {
- if ( txnType == PersistenceUnitTransactionType.JTA ) {
- serviceRegistryBuilder.applySetting( Environment.TRANSACTION_STRATEGY, CMTTransactionFactory.class );
- }
- else if ( txnType == PersistenceUnitTransactionType.RESOURCE_LOCAL ) {
- serviceRegistryBuilder.applySetting( Environment.TRANSACTION_STRATEGY, JdbcTransactionFactory.class );
- }
- }
- }
-
private String jaccContextId;
private void addJaccDefinition(String key, Object value) {
@@ -643,35 +521,6 @@ private void addJaccDefinition(String key, Object value) {
}
}
- @SuppressWarnings("unchecked")
- private Class<? extends Interceptor> loadSessionInterceptorClass(
- Object value,
- BootstrapServiceRegistry bootstrapServiceRegistry) {
- if ( value == null ) {
- return null;
- }
-
- Class theClass;
- if ( Class.class.isInstance( value ) ) {
- theClass = (Class) value;
- }
- else {
- theClass = bootstrapServiceRegistry.getService( ClassLoaderService.class ).classForName( value.toString() );
- }
-
- try {
- return (Class<? extends Interceptor>) theClass;
- }
- catch (ClassCastException e) {
- throw persistenceException(
- String.format(
- "Specified Interceptor implementation class [%s] was not castable to Interceptor",
- theClass.getName()
- )
- );
- }
- }
-
private void addCacheRegionDefinition(String role, String value, CacheRegionDefinition.CacheType cacheType) {
final StringTokenizer params = new StringTokenizer( value, ";, " );
if ( !params.hasMoreTokens() ) {
@@ -714,66 +563,6 @@ private void addCacheRegionDefinition(String role, String value, CacheRegionDefi
}
@SuppressWarnings("unchecked")
- private <T> T instantiateCustomClassFromConfiguration(
- Object value,
- Class<T> type,
- ServiceRegistry bootstrapServiceRegistry) {
- if ( value == null ) {
- return null;
- }
-
- if ( type.isInstance( value ) ) {
- return (T) value;
- }
-
- final Class<? extends T> implementationClass;
-
- if ( Class.class.isInstance( value ) ) {
- try {
- implementationClass = (Class<? extends T>) value;
- }
- catch (ClassCastException e) {
- throw persistenceException(
- String.format(
- "Specified implementation class [%s] was not of expected type [%s]",
- ((Class) value).getName(),
- type.getName()
- )
- );
- }
- }
- else {
- final String implementationClassName = value.toString();
- try {
- implementationClass = bootstrapServiceRegistry.getService( ClassLoaderService.class )
- .classForName( implementationClassName );
- }
- catch (ClassCastException e) {
- throw persistenceException(
- String.format(
- "Specified implementation class [%s] was not of expected type [%s]",
- implementationClassName,
- type.getName()
- )
- );
- }
- }
-
- try {
- return implementationClass.newInstance();
- }
- catch (Exception e) {
- throw persistenceException(
- String.format(
- "Unable to instantiate specified implementation class [%s]",
- implementationClass.getName()
- ),
- e
- );
- }
- }
-
- @SuppressWarnings("unchecked")
private ScanResult scan(BootstrapServiceRegistry bootstrapServiceRegistry) {
Scanner scanner = locateOrBuildScanner( bootstrapServiceRegistry );
ScanningContext scanningContext = new ScanningContext();
@@ -921,6 +710,10 @@ private void scanInContext(
@Override
public EntityManagerFactoryBuilder withValidatorFactory(Object validatorFactory) {
this.validatorFactory = validatorFactory;
+
+ if ( validatorFactory != null ) {
+ BeanValidationIntegrator.validateFactory( validatorFactory );
+ }
return this;
}
@@ -932,23 +725,15 @@ public void cancel() {
@SuppressWarnings("unchecked")
public EntityManagerFactory build() {
- // IMPL NOTE : TCCL handling here is temporary.
- // It is needed because this code still uses Hibernate Configuration and Hibernate commons-annotations
- // in turn which relies on TCCL being set.
-
- if ( validatorFactory != null ) {
- // NOTE : need to add it to both
- configurationValues.put( AvailableSettings.VALIDATION_FACTORY, validatorFactory );
- }
-
- final Object validationFactory = configurationValues.get( AvailableSettings.VALIDATION_FACTORY );
- if ( validationFactory != null ) {
- BeanValidationIntegrator.validateFactory( validationFactory );
- }
+ processProperties();
final ServiceRegistry serviceRegistry = buildServiceRegistry();
final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
+ // IMPL NOTE : TCCL handling here is temporary.
+ // It is needed because this code still uses Hibernate Configuration and Hibernate commons-annotations
+ // in turn which relies on TCCL being set.
+
return ( (ClassLoaderServiceImpl) classLoaderService ).withTccl(
new ClassLoaderServiceImpl.Work<EntityManagerFactoryImpl>() {
@Override
@@ -975,6 +760,136 @@ public EntityManagerFactoryImpl perform() {
);
}
+ private void processProperties() {
+ applyJdbcConnectionProperties();
+ applyTransactionProperties();
+
+ Object validationFactory = this.validatorFactory;
+ if ( validationFactory == null ) {
+ validationFactory = configurationValues.get( AvailableSettings.VALIDATION_FACTORY );
+ }
+ if ( validationFactory != null ) {
+ BeanValidationIntegrator.validateFactory( validationFactory );
+ serviceRegistryBuilder.applySetting( AvailableSettings.VALIDATION_FACTORY, validationFactory );
+ }
+
+ // flush before completion validation
+ if ( "true".equals( configurationValues.get( Environment.FLUSH_BEFORE_COMPLETION ) ) ) {
+ serviceRegistryBuilder.applySetting( Environment.FLUSH_BEFORE_COMPLETION, "false" );
+ LOG.definingFlushBeforeCompletionIgnoredInHem( Environment.FLUSH_BEFORE_COMPLETION );
+ }
+
+ final StrategySelector strategySelector = serviceRegistryBuilder.getBootstrapServiceRegistry().getService( StrategySelector.class );
+
+ for ( Object oEntry : configurationValues.entrySet() ) {
+ Map.Entry entry = (Map.Entry) oEntry;
+ if ( entry.getKey() instanceof String ) {
+ final String keyString = (String) entry.getKey();
+
+ if ( AvailableSettings.INTERCEPTOR.equals( keyString ) ) {
+ sessionFactoryInterceptor = strategySelector.resolveStrategy( Interceptor.class, entry.getValue() );
+ }
+ else if ( AvailableSettings.SESSION_INTERCEPTOR.equals( keyString ) ) {
+ settings.setSessionInterceptorClass(
+ loadSessionInterceptorClass( entry.getValue(), strategySelector )
+ );
+ }
+ else if ( AvailableSettings.NAMING_STRATEGY.equals( keyString ) ) {
+ namingStrategy = strategySelector.resolveStrategy( NamingStrategy.class, entry.getValue() );
+ }
+ else if ( AvailableSettings.SESSION_FACTORY_OBSERVER.equals( keyString ) ) {
+ suppliedSessionFactoryObserver = strategySelector.resolveStrategy( SessionFactoryObserver.class, entry.getValue() );
+ }
+ else if ( AvailableSettings.DISCARD_PC_ON_CLOSE.equals( keyString ) ) {
+ settings.setReleaseResourcesOnCloseEnabled( "true".equals( entry.getValue() ) );
+ }
+ else if ( keyString.startsWith( AvailableSettings.CLASS_CACHE_PREFIX ) ) {
+ addCacheRegionDefinition(
+ keyString.substring( AvailableSettings.CLASS_CACHE_PREFIX.length() + 1 ),
+ (String) entry.getValue(),
+ CacheRegionDefinition.CacheType.ENTITY
+ );
+ }
+ else if ( keyString.startsWith( AvailableSettings.COLLECTION_CACHE_PREFIX ) ) {
+ addCacheRegionDefinition(
+ keyString.substring( AvailableSettings.COLLECTION_CACHE_PREFIX.length() + 1 ),
+ (String) entry.getValue(),
+ CacheRegionDefinition.CacheType.COLLECTION
+ );
+ }
+ else if ( keyString.startsWith( AvailableSettings.JACC_PREFIX )
+ && ! ( keyString.equals( AvailableSettings.JACC_CONTEXT_ID )
+ || keyString.equals( AvailableSettings.JACC_ENABLED ) ) ) {
+ addJaccDefinition( (String) entry.getKey(), entry.getValue() );
+ }
+ }
+ }
+ }
+
+ private void applyJdbcConnectionProperties() {
+ if ( persistenceUnit.getJtaDataSource() != null ) {
+ serviceRegistryBuilder.applySetting( Environment.DATASOURCE, persistenceUnit.getJtaDataSource() );
+ }
+ else if ( persistenceUnit.getNonJtaDataSource() != null ) {
+ serviceRegistryBuilder.applySetting( Environment.DATASOURCE, persistenceUnit.getNonJtaDataSource() );
+ }
+ else {
+ final String driver = (String) configurationValues.get( AvailableSettings.JDBC_DRIVER );
+ if ( StringHelper.isNotEmpty( driver ) ) {
+ serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.DRIVER, driver );
+ }
+ final String url = (String) configurationValues.get( AvailableSettings.JDBC_URL );
+ if ( StringHelper.isNotEmpty( url ) ) {
+ serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.URL, url );
+ }
+ final String user = (String) configurationValues.get( AvailableSettings.JDBC_USER );
+ if ( StringHelper.isNotEmpty( user ) ) {
+ serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.USER, user );
+ }
+ final String pass = (String) configurationValues.get( AvailableSettings.JDBC_PASSWORD );
+ if ( StringHelper.isNotEmpty( pass ) ) {
+ serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.PASS, pass );
+ }
+ }
+ }
+
+ private void applyTransactionProperties() {
+ PersistenceUnitTransactionType txnType = PersistenceUnitTransactionTypeHelper.interpretTransactionType(
+ configurationValues.get( AvailableSettings.TRANSACTION_TYPE )
+ );
+ if ( txnType == null ) {
+ txnType = persistenceUnit.getTransactionType();
+ }
+ if ( txnType == null ) {
+ // is it more appropriate to have this be based on bootstrap entry point (EE vs SE)?
+ txnType = PersistenceUnitTransactionType.RESOURCE_LOCAL;
+ }
+ settings.setTransactionType( txnType );
+ boolean hasTxStrategy = configurationValues.containsKey( Environment.TRANSACTION_STRATEGY );
+ if ( hasTxStrategy ) {
+ LOG.overridingTransactionStrategyDangerous( Environment.TRANSACTION_STRATEGY );
+ }
+ else {
+ if ( txnType == PersistenceUnitTransactionType.JTA ) {
+ serviceRegistryBuilder.applySetting( Environment.TRANSACTION_STRATEGY, CMTTransactionFactory.class );
+ }
+ else if ( txnType == PersistenceUnitTransactionType.RESOURCE_LOCAL ) {
+ serviceRegistryBuilder.applySetting( Environment.TRANSACTION_STRATEGY, JdbcTransactionFactory.class );
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private Class<? extends Interceptor> loadSessionInterceptorClass(Object value, StrategySelector strategySelector) {
+ if ( value == null ) {
+ return null;
+ }
+
+ return Class.class.isInstance( value )
+ ? (Class<? extends Interceptor>) value
+ : strategySelector.selectStrategyImplementor( Interceptor.class, value.toString() );
+ }
+
public ServiceRegistry buildServiceRegistry() {
return serviceRegistryBuilder.buildServiceRegistry();
}
@@ -994,11 +909,12 @@ public Configuration buildHibernateConfiguration(ServiceRegistry serviceRegistry
cfg.setInterceptor( sessionFactoryInterceptor );
}
- final IdentifierGeneratorStrategyProvider strategyProvider = instantiateCustomClassFromConfiguration(
- props.get( AvailableSettings.IDENTIFIER_GENERATOR_STRATEGY_PROVIDER ),
- IdentifierGeneratorStrategyProvider.class,
- serviceRegistry
- );
+ final Object strategyProviderValue = props.get( AvailableSettings.IDENTIFIER_GENERATOR_STRATEGY_PROVIDER );
+ final IdentifierGeneratorStrategyProvider strategyProvider = strategyProviderValue == null
+ ? null
+ : serviceRegistry.getService( StrategySelector.class )
+ .resolveStrategy( IdentifierGeneratorStrategyProvider.class, strategyProviderValue );
+
if ( strategyProvider != null ) {
final MutableIdentifierGeneratorFactory identifierGeneratorFactory = cfg.getIdentifierGeneratorFactory();
for ( Map.Entry<String,Class<?>> entry : strategyProvider.getStrategies().entrySet() ) {

0 comments on commit d0f8834

Please sign in to comment.