    001/**
    002 * Licensed under the Apache License, Version 2.0 (the "License");
    003 * you may not use this file except in compliance with the License.
    004 * You may obtain a copy of the License at
    005 *
    006 *     http://www.apache.org/licenses/LICENSE-2.0
    007 *
    008 * Unless required by applicable law or agreed to in writing, software
    009 * distributed under the License is distributed on an "AS IS" BASIS,
    010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    011 * See the License for the specific language governing permissions and
    012 * limitations under the License.
    013 */
    014package org.apache.tapestry5.internal.jpa;
    015
    016import java.util.HashMap;
    017import java.util.Map;
    018
    019import javax.persistence.EntityManager;
    020
    021import org.apache.tapestry5.ioc.Invokable;
    022import org.apache.tapestry5.ioc.ScopeConstants;
    023import org.apache.tapestry5.ioc.annotations.Scope;
    024import org.apache.tapestry5.jpa.EntityManagerManager;
    025import org.apache.tapestry5.jpa.EntityTransactionManager;
    026import org.slf4j.Logger;
    027
    028@Scope(ScopeConstants.PERTHREAD)
    029public class EntityTransactionManagerImpl implements EntityTransactionManager
    030{
    031
    032    private final Logger logger;
    033    private final EntityManagerManager entityManagerManager;
    034
    035    private final Map<String, PersistenceContextSpecificEntityTransactionManager> transactionManagerMap;
    036
    037    public EntityTransactionManagerImpl(Logger logger, EntityManagerManager entityManagerManager)
    038    {
    039        this.logger = logger;
    040        this.entityManagerManager = entityManagerManager;
    041        transactionManagerMap = new HashMap<>(entityManagerManager.getEntityManagers().size());
    042    }
    043
    044    private EntityManager getEntityManager(String unitName)
    045    {
    046        // EntityManager em = JpaInternalUtils.getEntityManager(entityManagerManager, unitName);
    047        // FIXME we should simply incorporate the logic in JpaInternalUtils.getEntityManager to
    048        // EntityManagerManager.getEntityManager(unitName)
    049        if (unitName != null)
    050            return entityManagerManager.getEntityManager(unitName);
    051        else
    052        {
    053            Map<String, EntityManager> entityManagers = entityManagerManager.getEntityManagers();
    054            if (entityManagers.size() == 1)
    055                return entityManagers.values().iterator().next();
    056            else
    057                throw new RuntimeException(
    058                        "Unable to locate a single EntityManager. "
    059                                + "You must provide the persistence unit name as defined in the persistence.xml using the @PersistenceContext annotation.");
    060        }
    061    }
    062
    063    /*
    064     * (non-Javadoc)
    065     * @see net.satago.tapestry5.jpa.EntityTransactionManager#runInTransaction(java.lang.String,
    066     * java.lang.Runnable)
    067     */
    068    @SuppressWarnings("unchecked")
    069    @Override
    070    public void runInTransaction(final String unitName, final Runnable runnable)
    071    {
    072        getPersistenceContextSpecificEntityTransactionManager(unitName).invokeInTransaction(
    073                new VoidInvokable(runnable));
    074    }
    075
    076    /*
    077     * (non-Javadoc)
    078     * @see net.satago.tapestry5.jpa.EntityTransactionManager#invokeInTransaction(java.lang.String,
    079     * org.apache.tapestry5.ioc.Invokable)
    080     */
    081    @Override
    082    public <T> T invokeInTransaction(String unitName, Invokable<T> invokable)
    083    {
    084        return getPersistenceContextSpecificEntityTransactionManager(unitName).invokeInTransaction(
    085                invokable);
    086    }
    087
    088    private PersistenceContextSpecificEntityTransactionManager getPersistenceContextSpecificEntityTransactionManager(
    089            String unitName)
    090    {
    091        if (!transactionManagerMap.containsKey(unitName))
    092        {
    093            PersistenceContextSpecificEntityTransactionManager transactionManager = new PersistenceContextSpecificEntityTransactionManager(
    094                    logger, getEntityManager(unitName));
    095            transactionManagerMap.put(unitName, transactionManager);
    096            return transactionManager;
    097        }
    098        else
    099            return transactionManagerMap.get(unitName);
    100    }
    101
    102    /*
    103     * (non-Javadoc)
    104     * @see
    105     * net.satago.tapestry5.jpa.EntityTransactionManager#invokeBeforeCommit(org.apache.tapestry5
    106     * .ioc.Invokable, java.lang.String)
    107     */
    108    @Override
    109    public void invokeBeforeCommit(String unitName, Invokable<Boolean> invokable)
    110    {
    111        getPersistenceContextSpecificEntityTransactionManager(unitName).addBeforeCommitInvokable(
    112                invokable);
    113    }
    114
    115    /*
    116     * (non-Javadoc)
    117     * @see
    118     * net.satago.tapestry5.jpa.EntityTransactionManager#invokeAfterCommit(org.apache.tapestry5.
    119     * ioc.Invokable, java.lang.String)
    120     */
    121    @Override
    122    public void invokeAfterCommit(String unitName, Invokable<Boolean> invokable)
    123    {
    124        getPersistenceContextSpecificEntityTransactionManager(unitName).addAfterCommitInvokable(
    125                invokable);
    126
    127    }
    128}