All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wisdom.framework.jpa.TransactionalEntityManager Maven / Gradle / Ivy

The newest version!
/*
 * #%L
 * Wisdom-Framework
 * %%
 * Copyright (C) 2013 - 2014 Wisdom Framework
 * %%
 * 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.
 * #L%
 */
package org.wisdom.framework.jpa;


import javax.persistence.*;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.metamodel.Metamodel;
import javax.transaction.Synchronization;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import java.util.Map;

/**
 * A Transactional Entity Manager delegates all requests to another Entity
 * Manager. The delegate is created when it is needed for the first time in a
 * transaction and later reused. The delegate is automatically closed at the end
 * of the transaction.
 */
@SuppressWarnings("rawtypes")
class TransactionalEntityManager implements EntityManager {

    private final TransactionManager transactionManager;
    private final EntityManagerFactory entityManagerFactory;
    private final PersistenceUnitComponent unit;
    final ThreadLocal perThreadEntityManager = new ThreadLocal<>();
    volatile boolean open = true;

    //TODO Manage transaction manager in the request scope.

    public TransactionalEntityManager(TransactionManager tm, EntityManagerFactory emf, PersistenceUnitComponent unit) {
        this.transactionManager = tm;
        this.entityManagerFactory = emf;
        this.unit = unit;
    }


    /**
     * The delegated methods call this method to get the delegate. This method
     * verifies if we're still open, if there already is an Entity Manager for
     * this thread and otherwise creates it and enlists it for auto close at the
     * current transaction.
     *
     * @return an Entity Manager
     */
    private EntityManager getEM() throws IllegalStateException {
        if (!open) {
            throw new IllegalStateException("The JPA bridge has closed");
        }

        try {

            // Do we already have one on this thread?

            EntityManager em = perThreadEntityManager.get();
            if (em != null) {
                return em;
            }


            // Nope, so we need to check if there actually is a transaction
            final Transaction transaction = transactionManager.getTransaction();
            if (transaction == null) {
                throw new TransactionRequiredException("Cannot create an EM since no transaction active");
            }

            em = entityManagerFactory.createEntityManager();


            try {
                // Register a callback at the end of the transaction
                transaction.registerSynchronization(new Synchronization() {

                    @Override
                    public void beforeCompletion() {
                        if (!open) {
                            throw new IllegalStateException(
                                    "The Transaction Entity Manager was closed in the mean time");
                        }
                    }

                    @Override
                    public void afterCompletion(int arg0) {
                        EntityManager em = perThreadEntityManager.get();
                        perThreadEntityManager.set(null);
                        em.close();
                    }
                });
            } catch (Exception e) {
                em.close();
                throw new IllegalStateException("Registering synchronization to close EM", e);
            }

            // Make it available for later calls on this thread
            perThreadEntityManager.set(em);

            // And make sure it joins the current transaction.
            em.joinTransaction();
            return em;
        } catch (Exception e) {
            throw new IllegalStateException("Error while retrieving entity manager", e);
        }

    }

    void shutdown() {
        open = false;
    }

    /**
     * We automatically close so ignore.
     */
    @Override
    public void close() {
    }

    @Override
    public void clear() {
        getEM().clear();
    }

    @Override
    public boolean contains(Object arg0) {
        return getEM().contains(arg0);
    }

    @Override
    public  TypedQuery createNamedQuery(String arg0, Class arg1) {
        return getEM().createNamedQuery(arg0, arg1);
    }

    @Override
    public Query createNamedQuery(String arg0) {
        return getEM().createNamedQuery(arg0);
    }

    @Override
    public Query createNativeQuery(String arg0, Class arg1) {
        return getEM().createNativeQuery(arg0, arg1);
    }

    @Override
    public Query createNativeQuery(String arg0, String arg1) {
        return getEM().createNativeQuery(arg0, arg1);
    }

    @Override
    public Query createNativeQuery(String arg0) {
        return getEM().createNativeQuery(arg0);
    }

    @Override
    public  TypedQuery createQuery(CriteriaQuery arg0) {
        return getEM().createQuery(arg0);
    }

    @Override
    public  TypedQuery createQuery(String arg0, Class arg1) {
        return getEM().createQuery(arg0, arg1);
    }

    @Override
    public Query createQuery(String arg0) {
        return getEM().createQuery(arg0);
    }

    @Override
    public void detach(Object arg0) {
        getEM().detach(arg0);
    }

    @Override
    public  T find(Class arg0, Object arg1, LockModeType arg2, Map arg3) {
        return getEM().find(arg0, arg1, arg2, arg3);
    }

    @Override
    public  T find(Class arg0, Object arg1, LockModeType arg2) {
        return getEM().find(arg0, arg1, arg2);
    }

    @Override
    public  T find(Class arg0, Object arg1, Map arg2) {
        return getEM().find(arg0, arg1, arg2);
    }

    @Override
    public  T find(Class arg0, Object arg1) {
        return getEM().find(arg0, arg1);
    }

    @Override
    public void flush() {
        getEM().flush();
    }

    @Override
    public CriteriaBuilder getCriteriaBuilder() {
        return getEM().getCriteriaBuilder();
    }

    @Override
    public Object getDelegate() {
        return getEM().getDelegate();
    }

    @Override
    public EntityManagerFactory getEntityManagerFactory() {
        return getEM().getEntityManagerFactory();
    }

    @Override
    public FlushModeType getFlushMode() {
        return getEM().getFlushMode();
    }

    @Override
    public LockModeType getLockMode(Object arg0) {
        return getEM().getLockMode(arg0);
    }

    @Override
    public Metamodel getMetamodel() {
        return getEM().getMetamodel();
    }

    @Override
    public Map getProperties() {
        return getEM().getProperties();
    }

    @Override
    public  T getReference(Class arg0, Object arg1) {
        return getEM().getReference(arg0, arg1);
    }

    @Override
    public EntityTransaction getTransaction() {
        return getEM().getTransaction();
    }

    @Override
    public boolean isOpen() {
        return getEM().isOpen();
    }

    @Override
    public void joinTransaction() {
        getEM().joinTransaction();
    }

    @Override
    public void lock(Object arg0, LockModeType arg1, Map arg2) {
        getEM().lock(arg0, arg1, arg2);
    }

    @Override
    public void lock(Object arg0, LockModeType arg1) {
        getEM().lock(arg0, arg1);
    }

    @Override
    public  T merge(T arg0) {
        return getEM().merge(arg0);
    }

    @Override
    public void persist(Object arg0) {
        getEM().persist(arg0);
    }

    @Override
    public void refresh(Object arg0, LockModeType arg1, Map arg2) {
        getEM().refresh(arg0, arg1, arg2);
    }

    @Override
    public void refresh(Object arg0, LockModeType arg1) {
        getEM().refresh(arg0, arg1);
    }

    @Override
    public void refresh(Object arg0, Map arg1) {
        getEM().refresh(arg0, arg1);
    }

    @Override
    public void refresh(Object arg0) {
        getEM().refresh(arg0);
    }

    @Override
    public void remove(Object arg0) {
        getEM().remove(arg0);
    }

    @Override
    public void setFlushMode(FlushModeType arg0) {
        getEM().setFlushMode(arg0);
    }

    @Override
    public void setProperty(String arg0, Object arg1) {
        getEM().setProperty(arg0, arg1);
    }

    @Override
    public  T unwrap(Class arg0) {
        return getEM().unwrap(arg0);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy