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

org.springframework.ldap.transaction.compensating.manager.ContextSourceTransactionManager Maven / Gradle / Ivy

There is a newer version: 3.2.4
Show newest version
/*
 * Copyright 2005-2013 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 org.springframework.ldap.transaction.compensating.manager;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.transaction.compensating.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.UnbindOperationExecutor;
import org.springframework.ldap.transaction.compensating.support.DefaultTempEntryRenamingStrategy;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
import org.springframework.transaction.compensating.CompensatingTransactionOperationRecorder;
import org.springframework.transaction.compensating.support.CompensatingTransactionObject;
import org.springframework.transaction.compensating.support.DefaultCompensatingTransactionOperationManager;
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
import org.springframework.transaction.support.DefaultTransactionStatus;

/**
 * TransactionManager for managing LDAP transactions. Since transactions are not
 * supported in the LDAP protocol, this class and its collaborators aim to
 * provide compensating transactions instead. Should a transaction
 * need to be rolled back, this TransactionManager will try to restore the
 * original state using information recorded prior to each operation. The
 * operation where the original state is restored is called a compensating
 * operation.
 * 

* NOTE: The transactions provided by this TransactionManager are all * client side and are by no means 'real' transactions, in the sense * that we know them in the ordinary database world, e.g.: *

    *
  • Should the transaction failure be caused by a network failure, there is * no way whatsoever that this TransactionManager can restore the database * state. In this case, all possibilities for rollback will be utterly lost.
  • *
  • Transaction isolation is not provided, i.e. entries participating in a * transaction for one client may very well participate in another transaction * for another client at the same time. Should one of these transactions be * rolled back, the outcome of this is undetermined, and may in the worst case * result in total failure.
  • *
*

* While the points above should be noted and considered, the compensating * transaction approach will be perfectly sufficient for all but the most * unfortunate of circumstances. Considering that there currently is a total * absence of server-side transaction support in the LDAP world, being able to * mark operations as transactional in the same way as for relational database * operations is surely a step forward. *

* An LDAP transaction is tied to a {@link ContextSource}, to be supplied to * the {@link #setContextSource(ContextSource)} method. While the actual * ContextSource used by the target LdapTemplate instance needs to be of the * type {@link TransactionAwareContextSourceProxy}, the ContextSource supplied * to this class should be the actual target ContextSource. *

* Using this TransactionManager along with * {@link TransactionAwareContextSourceProxy}, all modifying operations (bind, * unbind, rebind, rename, modifyAttributes) in a transaction will be * intercepted. Each modification has its corresponding * {@link CompensatingTransactionOperationRecorder}, which collects the * information necessary to perform a rollback and produces a * {@link CompensatingTransactionOperationExecutor} which is then used to * execute the actual operation and is later called for performing the commit or * rollback. *

* For several of the operations, performing a rollback is pretty * straightforward. For example, in order to roll back a rename operation, it * will only be required to rename the entry back to its original position. For * other operations, however, it's a bit more complicated. An unbind operation * is not possible to roll back by simply binding the entry back with the * attributes retrieved from the original entry. It might not be possible to get * all the information from the original entry. Consequently, the * {@link UnbindOperationExecutor} will move the original entry to a temporary * location in its performOperation() method. The commit() method will know that * everything went well, so it will be OK to unbind the entry. The rollback * operation will be to rename the entry back to its original location. The same * behaviour is used for rebind() operations. The operation of calculating a * temporary location for an entry is delegated to a * {@link TempEntryRenamingStrategy} (default * {@link DefaultTempEntryRenamingStrategy}), specified in * {@link #setRenamingStrategy(TempEntryRenamingStrategy)}. *

* The actual work of this Transaction Manager is delegated to a * {@link ContextSourceTransactionManagerDelegate}. This is because the exact * same logic needs to be used if we want to wrap a JDBC and LDAP transaction in * the same logical transaction. *

* * @author Mattias Hellborg Arthursson * * @see ContextSourceAndDataSourceTransactionManager * @see ContextSourceTransactionManagerDelegate * @see DefaultCompensatingTransactionOperationManager * @see TempEntryRenamingStrategy * @see TransactionAwareContextSourceProxy * @since 1.2 */ public class ContextSourceTransactionManager extends AbstractPlatformTransactionManager implements InitializingBean { private static final long serialVersionUID = 7138208218687237856L; private ContextSourceTransactionManagerDelegate delegate = new ContextSourceTransactionManagerDelegate(); /* * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doBegin(java.lang.Object, * org.springframework.transaction.TransactionDefinition) */ protected void doBegin(Object transaction, TransactionDefinition definition) { delegate.doBegin(transaction, definition); } /* * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doCleanupAfterCompletion(java.lang.Object) */ protected void doCleanupAfterCompletion(Object transaction) { delegate.doCleanupAfterCompletion(transaction); } /* * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doCommit(org.springframework.transaction.support.DefaultTransactionStatus) */ protected void doCommit(DefaultTransactionStatus status) { delegate.doCommit(status); } /* * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doGetTransaction() */ protected Object doGetTransaction() { return delegate.doGetTransaction(); } /* * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doRollback(org.springframework.transaction.support.DefaultTransactionStatus) */ protected void doRollback(DefaultTransactionStatus status) { delegate.doRollback(status); } /** * Get the ContextSource. * * @return the contextSource. * @see ContextSourceTransactionManagerDelegate#getContextSource() */ public ContextSource getContextSource() { return delegate.getContextSource(); } /** * Set the ContextSource. * * @param contextSource * the ContextSource. * @see ContextSourceTransactionManagerDelegate#setContextSource(ContextSource) */ public void setContextSource(ContextSource contextSource) { delegate.setContextSource(contextSource); } /** * Set the {@link TempEntryRenamingStrategy}. * * @param renamingStrategy * the Renaming Strategy. * @see ContextSourceTransactionManagerDelegate#setRenamingStrategy(TempEntryRenamingStrategy) */ public void setRenamingStrategy(TempEntryRenamingStrategy renamingStrategy) { delegate.setRenamingStrategy(renamingStrategy); } public void afterPropertiesSet() throws Exception { delegate.checkRenamingStrategy(); } @Override protected boolean isExistingTransaction(Object transaction) throws TransactionException { CompensatingTransactionObject txObject = (CompensatingTransactionObject) transaction; return (txObject.getHolder() != null); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy