/* * Hibernate OGM, Domain model persistence for NoSQL datastores * * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.ogm.transaction.impl; import java.util.Map; import org.hibernate.boot.registry.StandardServiceInitiator; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.selector.spi.StrategySelector; import org.hibernate.ogm.cfg.OgmProperties; import org.hibernate.ogm.compensation.ErrorHandler; import org.hibernate.ogm.compensation.impl.ErrorHandlerEnabledTransactionCoordinatorBuilder; import org.hibernate.ogm.datastore.spi.DatastoreProvider; import org.hibernate.ogm.transaction.emulated.impl.EmulatedLocalTransactionCoordinatorBuilder; import org.hibernate.ogm.transaction.jta.impl.RollbackOnCommitFailureJtaTransactionCoordinatorBuilder; import org.hibernate.ogm.util.configurationreader.spi.ConfigurationPropertyReader; import org.hibernate.resource.transaction.TransactionCoordinatorBuilder; import org.hibernate.resource.transaction.internal.TransactionCoordinatorBuilderInitiator; import org.hibernate.service.spi.ServiceRegistryImplementor; /** * Contributes OGM's {@link TransactionCoordinatorBuilder}. * <p> * Makes use of ORM's default builder in the case of JTA, otherwise {@link EmulatedLocalTransactionCoordinatorBuilder} * is used. In case an {@link ErrorHandler} has been configured, the actual builder will be wrapped by * {@link ErrorHandlerEnabledTransactionCoordinatorBuilder}. * * @author Emmanuel Bernard <emmanuel@hibernate.org> * @author Gunnar Morling */ public class OgmTransactionCoordinatorBuilderInitiator implements StandardServiceInitiator<TransactionCoordinatorBuilder> { public static final OgmTransactionCoordinatorBuilderInitiator INSTANCE = new OgmTransactionCoordinatorBuilderInitiator(); private OgmTransactionCoordinatorBuilderInitiator() { } @Override public Class<TransactionCoordinatorBuilder> getServiceInitiated() { return TransactionCoordinatorBuilder.class; } @Override public TransactionCoordinatorBuilder initiateService(Map configurationValues, ServiceRegistryImplementor registry) { TransactionCoordinatorBuilder builder = null; DatastoreProvider datastoreProvider = registry.getService( DatastoreProvider.class ); TransactionCoordinatorBuilder defaultBuilder = TransactionCoordinatorBuilderInitiator.INSTANCE.initiateService( configurationValues, registry ); TransactionCoordinatorBuilder customBuilder = datastoreProvider.getTransactionCoordinatorBuilder( defaultBuilder ); // Take custom builder if present if ( customBuilder != null && customBuilder != defaultBuilder ) { builder = customBuilder; } // JTA default builder can be taken as is else if ( defaultBuilder.isJta() ) { builder = defaultBuilder; } // For RESOURCE_LOCAL either use emulated local TX or delegate to JTA else if ( datastoreProvider.allowsTransactionEmulation() ) { // if the datastore does not support transactions it is enough to emulate them. In this case transactions // are just used to scope a unit of work and to make sure that the appropriate flush event occurs builder = new EmulatedLocalTransactionCoordinatorBuilder( defaultBuilder ); } else { builder = new RollbackOnCommitFailureJtaTransactionCoordinatorBuilder( getDefaultBuilder( registry, "jta" ) ); } return decorateWithErrorHandlerIfNeeded( configurationValues, registry, builder ); } private TransactionCoordinatorBuilder getDefaultBuilder(ServiceRegistryImplementor registry, String strategy ) { return registry.getService( StrategySelector.class ).resolveStrategy( TransactionCoordinatorBuilder.class, strategy ); } private TransactionCoordinatorBuilder decorateWithErrorHandlerIfNeeded(Map configurationValues, ServiceRegistryImplementor registry, TransactionCoordinatorBuilder builder) { ErrorHandler errorHandler = getErrorHandler( configurationValues, registry ); return errorHandler != null ? new ErrorHandlerEnabledTransactionCoordinatorBuilder( builder, errorHandler ) : builder; } private ErrorHandler getErrorHandler(Map<?, ?> configurationValues, ServiceRegistryImplementor registry) { ConfigurationPropertyReader propertyReader = new ConfigurationPropertyReader( configurationValues, registry.getService( ClassLoaderService.class ) ); return propertyReader.property( OgmProperties.ERROR_HANDLER, ErrorHandler.class ).instantiate().getValue(); } }