All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.bitsensor.plugins.shaded.org.springframework.amqp.rabbit.transaction.RabbitTransactionManager Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2002-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.bitsensor.plugins.shaded.io.bitsensor.plugins.shaded.org.springframework.amqp.rabbit.transaction;

import io.bitsensor.plugins.shaded.io.bitsensor.plugins.shaded.org.springframework.amqp.AmqpException;
import io.bitsensor.plugins.shaded.io.bitsensor.plugins.shaded.org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import io.bitsensor.plugins.shaded.io.bitsensor.plugins.shaded.org.springframework.amqp.rabbit.connection.ConnectionFactory;
import io.bitsensor.plugins.shaded.io.bitsensor.plugins.shaded.org.springframework.amqp.rabbit.connection.ConnectionFactoryUtils;
import io.bitsensor.plugins.shaded.io.bitsensor.plugins.shaded.org.springframework.amqp.rabbit.connection.RabbitResourceHolder;
import io.bitsensor.plugins.shaded.io.bitsensor.plugins.shaded.org.springframework.amqp.rabbit.core.RabbitTemplate;
import io.bitsensor.plugins.shaded.org.springframework.beans.factory.InitializingBean;
import io.bitsensor.plugins.shaded.org.springframework.transaction.CannotCreateTransactionException;
import io.bitsensor.plugins.shaded.org.springframework.transaction.InvalidIsolationLevelException;
import io.bitsensor.plugins.shaded.org.springframework.transaction.TransactionDefinition;
import io.bitsensor.plugins.shaded.org.springframework.transaction.support.AbstractPlatformTransactionManager;
import io.bitsensor.plugins.shaded.org.springframework.transaction.support.DefaultTransactionStatus;
import io.bitsensor.plugins.shaded.org.springframework.transaction.support.ResourceTransactionManager;
import io.bitsensor.plugins.shaded.org.springframework.transaction.support.SmartTransactionObject;
import io.bitsensor.plugins.shaded.org.springframework.transaction.support.TransactionSynchronizationManager;

import io.bitsensor.plugins.shaded.com.rabbitmq.client.Connection;

/**
 * {@link io.bitsensor.plugins.shaded.org.springframework.transaction.PlatformTransactionManager} implementation for a single Rabbit
 * {@link ConnectionFactory}. Binds a Rabbit Channel from the specified ConnectionFactory to the thread, potentially
 * allowing for one thread-bound channel per ConnectionFactory.
 *
 * 

* This local strategy is an alternative to executing Rabbit operations within, and synchronized with, external * transactions. This strategy is not able to provide XA transactions, for example in order to share transactions * between messaging and database access. * *

* Application code is required to retrieve the transactional Rabbit resources via * {@link ConnectionFactoryUtils#getTransactionalResourceHolder(ConnectionFactory, boolean)} instead of a standard * {@link Connection#createChannel()} call with subsequent Channel creation. Spring's {@link RabbitTemplate} will * autodetect a thread-bound Channel and automatically participate in it. * *

* The use of {@link CachingConnectionFactory} as a target for this transaction manager is strongly recommended. * CachingConnectionFactory uses a single Rabbit Connection for all Rabbit access in order to avoid the overhead of * repeated Connection creation, as well as maintaining a cache of Channels. Each transaction will then share the same * Rabbit Connection, while still using its own individual Rabbit Channel. * *

* Transaction synchronization is turned off by default, as this manager might be used alongside a datastore-based * Spring transaction manager such as the JDBC io.bitsensor.plugins.shaded.org.springframework.jdbc.datasource.DataSourceTransactionManager, * which has stronger needs for synchronization. * * @author Dave Syer */ @SuppressWarnings("serial") public class RabbitTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, InitializingBean { private ConnectionFactory connectionFactory; /** * Create a new RabbitTransactionManager for bean-style usage. *

* Note: The ConnectionFactory has to be set before using the instance. This constructor can be used to prepare a * RabbitTemplate via a BeanFactory, typically setting the ConnectionFactory via setConnectionFactory. *

* Turns off transaction synchronization by default, as this manager might be used alongside a datastore-based * Spring transaction manager like DataSourceTransactionManager, which has stronger needs for synchronization. Only * one manager is allowed to drive synchronization at any point of time. * @see #setConnectionFactory * @see #setTransactionSynchronization */ public RabbitTransactionManager() { setTransactionSynchronization(SYNCHRONIZATION_NEVER); } /** * Create a new RabbitTransactionManager, given a ConnectionFactory. * @param connectionFactory the ConnectionFactory to use */ public RabbitTransactionManager(ConnectionFactory connectionFactory) { this(); this.connectionFactory = connectionFactory; afterPropertiesSet(); } /** * @param connectionFactory the connectionFactory to set */ public void setConnectionFactory(ConnectionFactory connectionFactory) { this.connectionFactory = connectionFactory; } /** * @return the connectionFactory */ public ConnectionFactory getConnectionFactory() { return this.connectionFactory; } /** * Make sure the ConnectionFactory has been set. */ public void afterPropertiesSet() { if (getConnectionFactory() == null) { throw new IllegalArgumentException("Property 'connectionFactory' is required"); } } public Object getResourceFactory() { return getConnectionFactory(); } @Override protected Object doGetTransaction() { RabbitTransactionObject txObject = new RabbitTransactionObject(); txObject.setResourceHolder((RabbitResourceHolder) TransactionSynchronizationManager .getResource(getConnectionFactory())); return txObject; } @Override protected boolean isExistingTransaction(Object transaction) { RabbitTransactionObject txObject = (RabbitTransactionObject) transaction; return (txObject.getResourceHolder() != null); } @Override protected void doBegin(Object transaction, TransactionDefinition definition) { if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { throw new InvalidIsolationLevelException("AMQP does not support an isolation level concept"); } RabbitTransactionObject txObject = (RabbitTransactionObject) transaction; RabbitResourceHolder resourceHolder = null; try { resourceHolder = ConnectionFactoryUtils.getTransactionalResourceHolder(getConnectionFactory(), true); if (logger.isDebugEnabled()) { logger.debug("Created AMQP transaction on channel [" + resourceHolder.getChannel() + "]"); } // resourceHolder.declareTransactional(); txObject.setResourceHolder(resourceHolder); txObject.getResourceHolder().setSynchronizedWithTransaction(true); int timeout = determineTimeout(definition); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { txObject.getResourceHolder().setTimeoutInSeconds(timeout); } TransactionSynchronizationManager.bindResource(getConnectionFactory(), txObject.getResourceHolder()); } catch (AmqpException ex) { if (resourceHolder != null) { ConnectionFactoryUtils.releaseResources(resourceHolder); } throw new CannotCreateTransactionException("Could not create AMQP transaction", ex); } } @Override protected Object doSuspend(Object transaction) { RabbitTransactionObject txObject = (RabbitTransactionObject) transaction; txObject.setResourceHolder(null); return TransactionSynchronizationManager.unbindResource(getConnectionFactory()); } @Override protected void doResume(Object transaction, Object suspendedResources) { RabbitResourceHolder conHolder = (RabbitResourceHolder) suspendedResources; TransactionSynchronizationManager.bindResource(getConnectionFactory(), conHolder); } @Override protected void doCommit(DefaultTransactionStatus status) { RabbitTransactionObject txObject = (RabbitTransactionObject) status.getTransaction(); RabbitResourceHolder resourceHolder = txObject.getResourceHolder(); resourceHolder.commitAll(); } @Override protected void doRollback(DefaultTransactionStatus status) { RabbitTransactionObject txObject = (RabbitTransactionObject) status.getTransaction(); RabbitResourceHolder resourceHolder = txObject.getResourceHolder(); resourceHolder.rollbackAll(); } @Override protected void doSetRollbackOnly(DefaultTransactionStatus status) { RabbitTransactionObject txObject = (RabbitTransactionObject) status.getTransaction(); txObject.getResourceHolder().setRollbackOnly(); } @Override protected void doCleanupAfterCompletion(Object transaction) { RabbitTransactionObject txObject = (RabbitTransactionObject) transaction; TransactionSynchronizationManager.unbindResource(getConnectionFactory()); txObject.getResourceHolder().closeAll(); txObject.getResourceHolder().clear(); } /** * Rabbit transaction object, representing a RabbitResourceHolder. Used as transaction object by * RabbitTransactionManager. * @see RabbitResourceHolder */ private static class RabbitTransactionObject implements SmartTransactionObject { private RabbitResourceHolder resourceHolder; public void setResourceHolder(RabbitResourceHolder resourceHolder) { this.resourceHolder = resourceHolder; } public RabbitResourceHolder getResourceHolder() { return this.resourceHolder; } public boolean isRollbackOnly() { return this.resourceHolder.isRollbackOnly(); } public void flush() { // no-op } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy