/* * Copyright 2004-2009 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.compass.core.transaction; import javax.transaction.Status; import javax.transaction.Synchronization; import javax.transaction.Transaction; import javax.transaction.UserTransaction; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.compass.core.spi.InternalCompassSession; /** * Implements a basic transaction strategy for JTA transactions. Instances check * to see if there is an existing JTA transaction. If none exists, a new * transaction is started. If one exists, all work is done in the existing * context. * * @author kimchy */ public class JTASyncTransaction extends AbstractJTATransaction { private boolean commitBeforeCompletion; public JTASyncTransaction(UserTransaction ut, boolean commitBeforeCompletion, TransactionFactory transactionFactory) { super(ut, transactionFactory); this.commitBeforeCompletion = commitBeforeCompletion; } protected void doBindToTransaction(Transaction tx, InternalCompassSession session, boolean newTransaction) throws Exception { tx.registerSynchronization(new JTATransactionSynchronization(session, tx, newTransaction, commitBeforeCompletion, transactionFactory)); } private static class JTATransactionSynchronization implements Synchronization { private static final Log log = LogFactory.getLog(JTATransactionSynchronization.class); private InternalCompassSession session; private Transaction tx; private boolean compassControlledJtaTransaction; private boolean commitBeforeCompletion; private TransactionFactory transactionFactory; public JTATransactionSynchronization(InternalCompassSession session, Transaction tx, boolean compassControlledJtaTransaction, boolean commitBeforeCompletion, TransactionFactory transactionFactory) { this.session = session; this.tx = tx; this.compassControlledJtaTransaction = compassControlledJtaTransaction; this.commitBeforeCompletion = commitBeforeCompletion; this.transactionFactory = transactionFactory; } public void beforeCompletion() { if (!commitBeforeCompletion) { return; } if (log.isDebugEnabled()) { log.debug("Committing compass transaction using JTA synchronization beforeCompletion on thread [" + Thread.currentThread().getName() + "]"); } session.getSearchEngine().commit(true); } public void afterCompletion(int status) { try { if (!commitBeforeCompletion) { if (status == Status.STATUS_COMMITTED) { if (log.isDebugEnabled()) { log.debug("Committing compass transaction using JTA synchronization afterCompletion on thread [" + Thread.currentThread().getName() + "]"); } session.getSearchEngine().commit(true); } else { if (log.isDebugEnabled()) { log.debug("Rolling back compass transaction using JTA synchronization afterCompletion on thread [" + Thread.currentThread().getName() + "] with status [" + status + "]"); } session.getSearchEngine().rollback(); } } } catch (Exception e) { // TODO swallow?????? log.error("Exception occured when sync with transaction", e); } finally { session.evictAll(); ((JTASyncTransactionFactory) transactionFactory).unbindSessionFromTransaction(tx, session); // close the session AFTER we cleared it from the transaction, // so it will be actually closed (and only if we are not // controlling the trnasction) if (!compassControlledJtaTransaction) { session.close(); } } } } }