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}