package multithreaded;

import java.util.concurrent.Callable;

import javax.transaction.SystemException;

import com.atomikos.icatch.CompositeTransaction;
import com.atomikos.icatch.CompositeTransactionManager;
import com.atomikos.icatch.config.Configuration;
import com.atomikos.icatch.jta.UserTransactionManager;

class SubTransactionLogicInSeparateThread implements Callable<Void> {

	private CompositeTransaction subTransaction;
	private CompositeTransactionManager ctm;
	private UserTransactionManager utm;
	
	/**
	 * Each thread needs do work in a separate subTransaction to avoid interference.
	 * The only drawback is that threads may not see each other's data in the DBMS.
	 * 
	 * @param subTransaction
	 */
	SubTransactionLogicInSeparateThread(CompositeTransaction subTransaction) {
		this.subTransaction = subTransaction;
		ctm = Configuration.getCompositeTransactionManager();
		utm = new UserTransactionManager();
	}
	
	/**
	 * This is the main method, illustrating how to do subTransaction work in this thread.
	 */
	
	@Override
	public Void call() throws Exception {
		assertNoTransactionContext(); 
		ctm.resume(subTransaction); //needed to make JTA/XA work as expected
		assertJtaTransactionContext();
		//here, do any JTA/XA work you like in this thread
		subTransaction.commit();
		ctm.suspend(); //important, or this thread will continue with parent transaction - which interferes with main thread!
		assertNoTransactionContext();
		return null;
	}

	/**
	 * Utility assert for testing purposes only. Ignore for production code.
	 * @throws SystemException
	 */
	private void assertJtaTransactionContext() throws SystemException {
		if (utm.getTransaction() == null) throw new IllegalStateException("Thread should have transaction context");
	}
	
	/**
	 * Utility assert for testing purposes only. Ignore for production code.
	 * @throws SystemException
	 */

	private void assertNoTransactionContext() {
		if (ctm.getCompositeTransaction() != null) throw new IllegalStateException("Thread has unexpected existing transaction context");
	}

}
