org.springframework.orm.ojb.OjbFactoryUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.orm.ojb.OjbFactoryUtils.java

Source

/*
 * Copyright 2002-2005 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.orm.ojb;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ojb.broker.OJBRuntimeException;
import org.apache.ojb.broker.PBKey;
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.PersistenceBrokerFactory;

import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
 * Helper class featuring methods for OJB PersistenceBroker handling,
 * allowing for reuse of PersistenceBroker instances within transactions.
 *
 * <p>Used by PersistenceBrokerTemplate and PersistenceBrokerTransactionManager.
 * Can also be used directly in application code.
 *
 * @author Juergen Hoeller
 * @since 1.1
 * @see PersistenceBrokerTemplate
 * @see PersistenceBrokerTransactionManager
 * @see org.springframework.transaction.jta.JtaTransactionManager
 */
public abstract class OjbFactoryUtils {

    /**
     * Order value for TransactionSynchronization objects that clean up OJB
     * PersistenceBrokers. Return DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 100
     * to execute PersistenceBroker cleanup before JDBC Connection cleanup, if any.
     * @see org.springframework.jdbc.datasource.DataSourceUtils#CONNECTION_SYNCHRONIZATION_ORDER
     */
    public static final int PERSISTENCE_BROKER_SYNCHRONIZATION_ORDER = DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER
            - 100;

    private static final Log logger = LogFactory.getLog(OjbFactoryUtils.class);

    /**
     * Get an OJB PersistenceBroker for the given PBKey. Is aware of a
     * corresponding PersistenceBroker bound to the current thread, for
     * example when using PersistenceBrokerTransactionManager. Will
     * create a new PersistenceBroker else, if allowCreate is true.
     * @param pbKey PBKey to create the PersistenceBroker for
     * @param allowCreate if a non-transactional PersistenceBroker should be created
     * when no transactional PersistenceBroker can be found for the current thread
     * @return the PersistenceBroker
     * @throws DataAccessResourceFailureException if the PersistenceBroker couldn't be created
     * @throws IllegalStateException if no thread-bound PersistenceBroker found and allowCreate false
     */
    public static PersistenceBroker getPersistenceBroker(PBKey pbKey, boolean allowCreate)
            throws DataAccessResourceFailureException, IllegalStateException {

        PersistenceBrokerHolder pbHolder = (PersistenceBrokerHolder) TransactionSynchronizationManager
                .getResource(pbKey);
        if (pbHolder != null) {
            return pbHolder.getPersistenceBroker();
        }

        if (!allowCreate && !TransactionSynchronizationManager.isSynchronizationActive()) {
            throw new IllegalStateException("No OJB PersistenceBroker bound to thread, "
                    + "and configuration does not allow creation of non-transactional one here");
        }

        try {
            logger.debug("Opening OJB PersistenceBroker");
            PersistenceBroker pb = PersistenceBrokerFactory.createPersistenceBroker(pbKey);

            if (TransactionSynchronizationManager.isSynchronizationActive()) {
                logger.debug("Registering transaction synchronization for OJB PersistenceBroker");
                // Use same PersistenceBroker for further OJB actions within the transaction.
                // Thread object will get removed by synchronization at transaction completion.
                pbHolder = new PersistenceBrokerHolder(pb);
                pbHolder.setSynchronizedWithTransaction(true);
                TransactionSynchronizationManager
                        .registerSynchronization(new PersistenceBrokerSynchronization(pbHolder, pbKey));
                TransactionSynchronizationManager.bindResource(pbKey, pbHolder);
            }

            return pb;
        } catch (OJBRuntimeException ex) {
            throw new DataAccessResourceFailureException("Could not open OJB PersistenceBroker", ex);
        }
    }

    /**
     * Close the given PersistenceBroker, created for the given PBKey,
     * if it isn't bound to the thread.
     * @deprecated in favor of releasePersistenceBroker
     * @see #releasePersistenceBroker
     */
    public static void closePersistenceBrokerIfNecessary(PersistenceBroker pb, PBKey pbKey) {
        releasePersistenceBroker(pb, pbKey);
    }

    /**
     * Close the given PersistenceBroker, created for the given PBKey,
     * if it is not managed externally (i.e. not bound to the thread).
     * @param pb PersistenceBroker to close
     * @param pbKey PBKey that the PersistenceBroker was created with
     */
    public static void releasePersistenceBroker(PersistenceBroker pb, PBKey pbKey) {
        if (pb == null) {
            return;
        }

        PersistenceBrokerHolder pbHolder = (PersistenceBrokerHolder) TransactionSynchronizationManager
                .getResource(pbKey);
        if (pbHolder != null && pb == pbHolder.getPersistenceBroker()) {
            // It's the transactional PersistenceBroker: Don't close it.
            return;
        }

        logger.debug("Closing OJB PersistenceBroker");
        pb.close();
    }

    /**
     * Callback for resource cleanup at the end of a non-OJB transaction
     * (e.g. when participating in a JtaTransactionManager transaction).
     * @see org.springframework.transaction.jta.JtaTransactionManager
     */
    private static class PersistenceBrokerSynchronization extends TransactionSynchronizationAdapter {

        private final PersistenceBrokerHolder persistenceBrokerHolder;

        private final PBKey pbKey;

        private boolean holderActive = true;

        private PersistenceBrokerSynchronization(PersistenceBrokerHolder pbHolder, PBKey pbKey) {
            this.persistenceBrokerHolder = pbHolder;
            this.pbKey = pbKey;
        }

        public int getOrder() {
            return PERSISTENCE_BROKER_SYNCHRONIZATION_ORDER;
        }

        public void suspend() {
            if (this.holderActive) {
                TransactionSynchronizationManager.unbindResource(this.pbKey);
            }
        }

        public void resume() {
            if (this.holderActive) {
                TransactionSynchronizationManager.bindResource(this.pbKey, this.persistenceBrokerHolder);
            }
        }

        public void beforeCompletion() {
            TransactionSynchronizationManager.unbindResource(this.pbKey);
            this.holderActive = false;
            releasePersistenceBroker(this.persistenceBrokerHolder.getPersistenceBroker(), this.pbKey);
        }
    }

}