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

com.premiumminds.persistence.MultiplePersistenceTransaction Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2014 Premium Minds.
 *
 * This file is part of pm-persistence-utils.
 *
 * pm-persistence-utils is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any
 * later version.
 *
 * pm-persistence-utils is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with pm-persistence-utils. If not, see .
 */
package com.premiumminds.persistence;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.premiumminds.persistence.PersistenceTransactionSynchronization.Status;

public class MultiplePersistenceTransaction implements PersistenceTransaction {
	private static final Logger log = LoggerFactory.getLogger(MultiplePersistenceTransaction.class);
	
	private List persistenceTransactions = new ArrayList();
	private ThreadLocal> sync = new ThreadLocal>();

	public void add(PersistenceTransaction persistenceTransaction){
		persistenceTransactions.add(persistenceTransaction);
	}
	
	@Override
	public void start() {
		log.debug("Starting application transaction");
		try{
			for(PersistenceTransaction pt : persistenceTransactions){
				pt.start();
			}
		} catch(Exception e){
			
			for(PersistenceTransaction pt : persistenceTransactions){
				try{
					pt.setRollbackOnly();
					pt.end();
				} catch(Throwable t){ }
			}
			throw new RuntimeException("Aborting transaction start", e);
		}		
	}

	@Override
	public void end() {
		try {
			boolean rollback = isRollbackOnly();
			Exception caughtException = null;
			for(PersistenceTransaction pt : persistenceTransactions){
				try {
					if (caughtException!=null) {
						pt.setRollbackOnly();
						rollback = true;
					}
				} catch (Exception e) {
					log.warn("Failed to setRollbackOnly when ending transaction", e);
				}
				try {
					pt.end();
				} catch (Exception e) {
					log.warn("Failed to end transaction", e);
					caughtException = e;
				}
			}
			log.debug("Ending application transaction");
			if(sync.get()!=null){
				PersistenceTransactionSynchronization.Status status = Status.COMMITTED;
				if(rollback) status = Status.ROLLEDBACK;
				for(PersistenceTransactionSynchronization s : sync.get()){
					s.afterTransaction(status);
				}
			}
			if(caughtException!=null) throw new RuntimeException(caughtException);
		} finally {
			sync.remove();
		}
	}

	@Override
	public void setRollbackOnly() {
		log.debug("Marking application transaction for rollback");
		for(PersistenceTransaction pt : persistenceTransactions){
			try {
				pt.setRollbackOnly();
			} catch (Exception e) {
				log.warn("Failed to mark transaction for rollback", e);
			}
		}
	}

	@Override
	public boolean isRollbackOnly() {
		for(PersistenceTransaction pt : persistenceTransactions){
			try {
				if(pt.isRollbackOnly()) return true;
			} catch (Exception e) {
				log.warn("Failed to determine rollback status for transaction, trying to set rollback", e);
				try {
					setRollbackOnly();
				} catch (Exception ex) {
					log.warn("Failed setRollbackOnly: should not happen", e);
				}
				return true;
			}
		}
		return false;
	}

	@Override
	public void registerSynchronization(
			PersistenceTransactionSynchronization synchronization) {
		if(sync.get()==null) sync.set(new ArrayList());
		sync.get().add(synchronization);
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy