/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package com.sun.enterprise.container.common.impl; import com.sun.enterprise.container.common.spi.JavaEEContainer; import com.sun.enterprise.container.common.spi.util.CallFlowAgent; import com.sun.enterprise.container.common.spi.util.ComponentEnvManager; import com.sun.enterprise.container.common.spi.util.EntityManagerMethod; import com.sun.enterprise.transaction.api.JavaEETransaction; import com.sun.logging.LogDomains; import org.glassfish.api.invocation.ComponentInvocation; import org.glassfish.api.invocation.InvocationManager; import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.internal.api.Globals; import javax.persistence.criteria.*; import javax.persistence.*; import javax.persistence.metamodel.Metamodel; import javax.transaction.Transaction; import javax.transaction.TransactionManager; import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; /** * Implementation of a container-managed entity manager. * A new instance of this class will be created for each injected * EntityManager reference or each lookup of an EntityManager * reference within the component jndi environment. * The underlying EntityManager object does not support concurrent access. * Likewise, this wrapper does not support concurrent access. * * @author Kenneth Saks */ public class EntityManagerWrapper implements EntityManager, Serializable { static Logger _logger=LogDomains.getLogger(EntityManagerWrapper.class, LogDomains.UTIL_LOGGER); // Serializable state private String unitName; private PersistenceContextType contextType; private Map emProperties; // transient state transient private EntityManagerFactory entityManagerFactory; transient private TransactionManager txManager; transient private InvocationManager invMgr; // Only used to cache entity manager with EXTENDED persistence context transient private EntityManager extendedEntityManager; // set and cleared after each non-tx, non EXTENDED call to _getDelegate() transient private EntityManager nonTxEntityManager; transient private ComponentEnvManager compEnvMgr; transient private CallFlowAgent callFlowAgent; public EntityManagerWrapper(TransactionManager txManager, InvocationManager invMgr, ComponentEnvManager compEnvMgr, CallFlowAgent callFlowAgent) { this.txManager = txManager; this.invMgr = invMgr; this.compEnvMgr = compEnvMgr; this.callFlowAgent = callFlowAgent; } public void initializeEMWrapper(String unitName, PersistenceContextType contextType, Map emProperties) { this.unitName = unitName; this.contextType = contextType; this.emProperties = emProperties; if(contextType == PersistenceContextType.EXTENDED) { // We are initializing an extended EM. The physical em is already created and stored in SessionContext to // enable persistence context propagation. // Initialize the delegate eagerly to support use cases like issue 11805 _getDelegate(); } } private void init() { entityManagerFactory = EntityManagerFactoryWrapper. lookupEntityManagerFactory(invMgr, compEnvMgr, unitName); if( entityManagerFactory == null ) { throw new IllegalStateException ("Unable to retrieve EntityManagerFactory for unitName " + unitName); } } private void doTransactionScopedTxCheck() { if( contextType != PersistenceContextType.TRANSACTION) { return; } doTxRequiredCheck(); } private void doTxRequiredCheck() { if( entityManagerFactory == null ) { init(); } Transaction tx = null; try { tx = txManager.getTransaction(); } catch(Exception e) { throw new IllegalStateException("exception retrieving tx", e); } if( tx == null ) { throw new TransactionRequiredException(); } } private EntityManager _getDelegate() { // Populate any transient objects the first time // this method is called. if( entityManagerFactory == null ) { init(); } EntityManager delegate = null; if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if( contextType == PersistenceContextType.TRANSACTION ) { JavaEETransaction tx = null; try { tx = (JavaEETransaction) txManager.getTransaction(); } catch(Exception e) { throw new IllegalStateException("exception retrieving tx", e); } if( tx != null ) { // If there is an active extended persistence context // for the same entity manager factory and the same tx, // it takes precendence. delegate = tx.getExtendedEntityManager(entityManagerFactory); if( delegate == null ) { delegate = tx.getTxEntityManager(entityManagerFactory); if( delegate == null ) { // If there is a transaction and this is the first // access of the wrapped entity manager, create an // actual entity manager and associate it with the // entity manager factory. delegate = entityManagerFactory. createEntityManager(emProperties); tx.addTxEntityManagerMapping(entityManagerFactory, delegate); } } } else { nonTxEntityManager = entityManagerFactory.createEntityManager (emProperties); // Return a new non-transactional entity manager. delegate = nonTxEntityManager; } } else { // EXTENDED Persitence Context if( extendedEntityManager == null ) { ComponentInvocation ci = invMgr.getCurrentInvocation(); if (ci != null) { Object cc = ci.getContainer(); if (cc instanceof JavaEEContainer) { extendedEntityManager = ((JavaEEContainer) cc).lookupExtendedEntityManager( entityManagerFactory); } } } delegate = extendedEntityManager; } if( _logger.isLoggable(Level.FINE) ) { _logger.fine("In EntityManagerWrapper::_getDelegate(). " + "Logical entity manager = " + this); _logger.fine("Physical entity manager = " + delegate); } return delegate; } private void cleanupNonTxEntityManager() { if( nonTxEntityManager != null ) { nonTxEntityManager.close(); nonTxEntityManager = null; } } public void persist(Object entity) { doTransactionScopedTxCheck(); try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.PERSIST); } _getDelegate().persist(entity); } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } // tx is required so there's no need to do any non-tx cleanup } public <T> T merge(T entity) { doTransactionScopedTxCheck(); try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.MERGE); } return _getDelegate().merge(entity); } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } // tx is required so there's no need to do any non-tx cleanup } public void remove(Object entity) { doTransactionScopedTxCheck(); try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.REMOVE); } _getDelegate().remove(entity); } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } // tx is required so there's no need to do any non-tx cleanup } public <T> T find(Class<T> entityClass, Object primaryKey) { T returnValue = null; try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.FIND); } returnValue = _getDelegate().find(entityClass, primaryKey); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } return returnValue; } public <T> T find(Class<T> entityClass, Object primaryKey, Map<String, Object> properties) { T returnValue = null; try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.FIND); } returnValue = _getDelegate().find(entityClass, primaryKey, properties); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } return returnValue; } public <T> T find(Class<T> entityClass, Object primaryKey, LockModeType lockMode) { T returnValue = null; try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.FIND_CLASS_OBJECT_LOCKMODETYPE); } returnValue = _getDelegate().find(entityClass, primaryKey, lockMode); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } return returnValue; } public <T> T find(Class<T> entityClass, Object primaryKey, LockModeType lockMode, Map<String, Object> properties) { T returnValue = null; try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.FIND_CLASS_OBJECT_LOCKMODETYPE_PROPERTIES); } returnValue = _getDelegate().find(entityClass, primaryKey, lockMode, properties); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } return returnValue; } public <T> T getReference(Class<T> entityClass, Object primaryKey) { T returnValue = null; try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_REFERENCE); } returnValue = _getDelegate().getReference(entityClass, primaryKey); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } return returnValue; } public void flush() { // tx is ALWAYS required, regardless of persistence context type. doTxRequiredCheck(); try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.FLUSH); } _getDelegate().flush(); } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } // tx is required so there's no need to do any non-tx cleanup } public Query createQuery(String ejbqlString) { Query returnValue = null; try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_QUERY); } EntityManager delegate = _getDelegate(); returnValue = delegate.createQuery(ejbqlString); if( nonTxEntityManager != null ) { Query queryDelegate = returnValue; returnValue = QueryWrapper.createQueryWrapper (entityManagerFactory, emProperties, delegate, queryDelegate, ejbqlString); // It's now the responsibility of the QueryWrapper to // close the non-tx EM delegate nonTxEntityManager = null; } } catch(RuntimeException re) { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } throw re; } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } return returnValue; } public <T> TypedQuery<T> createQuery(String ejbqlString, Class<T> resultClass) { TypedQuery<T> returnValue = null; try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_QUERY_STRING_CLASS); } EntityManager delegate = _getDelegate(); returnValue = delegate.createQuery(ejbqlString, resultClass); if( nonTxEntityManager != null ) { TypedQuery<T> queryDelegate = returnValue; returnValue = TypedQueryWrapper.createQueryWrapper (entityManagerFactory, emProperties, delegate, queryDelegate, ejbqlString, resultClass); // It's now the responsibility of the QueryWrapper to // close the non-tx EM delegate nonTxEntityManager = null; } } catch(RuntimeException re) { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } throw re; } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } return returnValue; } public <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery) { TypedQuery<T> returnValue = null; try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_QUERY_CRITERIA_QUERY); } EntityManager delegate = _getDelegate(); returnValue = delegate.createQuery(criteriaQuery); if( nonTxEntityManager != null ) { TypedQuery<T> queryDelegate = returnValue; returnValue = TypedQueryWrapper.createQueryWrapper (entityManagerFactory, emProperties, delegate, queryDelegate, criteriaQuery); // It's now the responsibility of the QueryWrapper to // close the non-tx EM delegate nonTxEntityManager = null; } } catch(RuntimeException re) { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } throw re; } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } return returnValue; } public Query createNamedQuery(String name) { Query returnValue = null; try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_NAMED_QUERY); } EntityManager delegate = _getDelegate(); returnValue = delegate.createNamedQuery(name); if( nonTxEntityManager != null ) { Query queryDelegate = returnValue; returnValue = QueryWrapper.createNamedQueryWrapper (entityManagerFactory, emProperties, delegate, queryDelegate, name); // It's now the responsibility of the QueryWrapper to // close the non-tx EM delegate nonTxEntityManager = null; } } catch(RuntimeException re) { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } throw re; } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } return returnValue; } public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass) { TypedQuery<T> returnValue = null; try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_NAMED_QUERY); } EntityManager delegate = _getDelegate(); returnValue = delegate.createNamedQuery(name, resultClass); if( nonTxEntityManager != null ) { TypedQuery<T> queryDelegate = returnValue; returnValue = TypedQueryWrapper.createNamedQueryWrapper (entityManagerFactory, emProperties, delegate, queryDelegate, name, resultClass); // It's now the responsibility of the QueryWrapper to // close the non-tx EM delegate nonTxEntityManager = null; } } catch(RuntimeException re) { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } throw re; } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } return returnValue; } public Query createNativeQuery(String sqlString) { Query returnValue = null; try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_NATIVE_QUERY_STRING); } EntityManager delegate = _getDelegate(); returnValue = delegate.createNativeQuery(sqlString); if( nonTxEntityManager != null ) { Query queryDelegate = returnValue; returnValue = QueryWrapper.createNativeQueryWrapper (entityManagerFactory, emProperties, delegate, queryDelegate, sqlString); // It's now the responsibility of the QueryWrapper to // close the non-tx EM delegate nonTxEntityManager = null; } } catch(RuntimeException re) { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } throw re; } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } return returnValue; } public Query createNativeQuery(String sqlString, Class resultClass) { Query returnValue = null; try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_NATIVE_QUERY_STRING_CLASS); } EntityManager delegate = _getDelegate(); returnValue = delegate.createNativeQuery(sqlString, resultClass); if( nonTxEntityManager != null ) { Query queryDelegate = returnValue; returnValue = QueryWrapper.createNativeQueryWrapper (entityManagerFactory, emProperties, delegate, queryDelegate, sqlString, resultClass); // It's now the responsibility of the QueryWrapper to // close the non-tx EM delegate nonTxEntityManager = null; } } catch(RuntimeException re) { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } throw re; } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } return returnValue; } public Query createNativeQuery(String sqlString, String resultSetMapping) { Query returnValue = null; try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_NATIVE_QUERY_STRING_STRING); } EntityManager delegate = _getDelegate(); returnValue = delegate.createNativeQuery (sqlString, resultSetMapping); if( nonTxEntityManager != null ) { Query queryDelegate = returnValue; returnValue = QueryWrapper.createNativeQueryWrapper (entityManagerFactory, emProperties, delegate, queryDelegate, sqlString, resultSetMapping); // It's now the responsibility of the QueryWrapper to // close the non-tx EM delegate nonTxEntityManager = null; } } catch(RuntimeException re) { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } throw re; } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } return returnValue; } public void refresh(Object entity) { doTransactionScopedTxCheck(); try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.REFRESH); } _getDelegate().refresh(entity); } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } // tx is required so there's no need to do any non-tx cleanup } public void refresh(Object entity, Map<String, Object> properties) { doTransactionScopedTxCheck(); try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.REFRESH_OBJECT_PROPERTIES); } _getDelegate().refresh(entity, properties); } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } // tx is required so there's no need to do any non-tx cleanup } public void refresh(Object entity, LockModeType lockMode) { doTransactionScopedTxCheck(); try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.REFRESH_OBJECT_LOCKMODETYPE); } _getDelegate().refresh(entity, lockMode); } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } // tx is required so there's no need to do any non-tx cleanup } public void refresh(Object entity, LockModeType lockMode, Map<String, Object> properties) { doTransactionScopedTxCheck(); try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.REFRESH_OBJECT_LOCKMODETYPE_MAP); } _getDelegate().refresh(entity, lockMode, properties); } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } // tx is required so there's no need to do any non-tx cleanup } public boolean contains(Object entity) { try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CONTAINS); } EntityManager delegate = _getDelegate(); return delegate.contains(entity); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } } public LockModeType getLockMode(Object o) { doTxRequiredCheck(); try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_LOCK_MODE); } return _getDelegate().getLockMode(o); } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } // tx is required so there's no need to do any non-tx cleanup } public void setProperty(String propertyName, Object value) { try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.SET_PROPERTY); } _getDelegate().setProperty(propertyName, value); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } // tx is required so there's no need to do any non-tx cleanup } public Map<String, Object> getProperties() { try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_PROPERTIES); } return _getDelegate().getProperties(); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } } public void close() { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CLOSE); callFlowAgent.entityManagerMethodEnd(); } // close() not allowed on container-managed EMs. throw new IllegalStateException(); } public boolean isOpen() { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.IS_OPEN); callFlowAgent.entityManagerMethodEnd(); } // Not relevant for container-managed EMs. Just return true. return true; } public EntityTransaction getTransaction() { try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_TRANSACTION); } return _getDelegate().getTransaction(); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } } public EntityManagerFactory getEntityManagerFactory() { try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_ENTITY_MANAGER_FACTORY); } if( entityManagerFactory == null ) { init(); } // Spec requires to throw IllegalStateException if this em has been closed. // No need to perform the check here as this can not happen for managed em. // No need to go to delegate for this. return entityManagerFactory; } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } } public CriteriaBuilder getCriteriaBuilder() { try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_CRITERIA_BUILDER); } return _getDelegate().getCriteriaBuilder(); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } } public Metamodel getMetamodel() { try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_METAMODEL); } return _getDelegate().getMetamodel(); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } } public void lock(Object entity, LockModeType lockMode) { try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.LOCK); } _getDelegate().lock(entity, lockMode); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } } public void lock(Object entity, LockModeType lockMode, Map<String, Object> properties) { try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.LOCK_LOCKMODETYPE_MAP); } _getDelegate().lock(entity, lockMode, properties); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } } public void clear() { try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CLEAR); } _getDelegate().clear(); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } } public void detach(Object o) { //TODO revisit this check once Linda confirms whether it is required or not. doTransactionScopedTxCheck(); try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.DETATCH); } _getDelegate().detach(o); } finally { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } // tx is required so there's no need to do any non-tx cleanup } public Object getDelegate() { try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_DELEGATE); } return _getDelegate(); } finally { if( nonTxEntityManager != null ) { // In this case we can't close the physical EntityManager // before returning it to the application, so we just clear // the EM wrapper's reference to it. nonTxEntityManager = null; } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } } public FlushModeType getFlushMode() { try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_FLUSH_MODE); } return _getDelegate().getFlushMode(); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } } public void setFlushMode(FlushModeType flushMode) { try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.SET_FLUSH_MODE); } _getDelegate().setFlushMode(flushMode); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } } public void joinTransaction() { // Doesn't apply to the container-managed case, but all the // spec says is that an exception should be thrown if called // without a tx. doTxRequiredCheck(); if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.JOIN_TRANSACTION); callFlowAgent.entityManagerMethodEnd(); } // There's no point in calling anything on the physical // entity manager since in all tx cases it will be // correctly associated with a tx already. } public <T> T unwrap(Class<T> tClass) { try { if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodStart(EntityManagerMethod.UNWRAP); } return _getDelegate().unwrap(tClass); } finally { if( nonTxEntityManager != null ) { cleanupNonTxEntityManager(); } if(callFlowAgent.isEnabled()) { callFlowAgent.entityManagerMethodEnd(); } } } private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); //Initialize the transients that were passed at ctor. ServiceLocator defaultServiceLocator = Globals.getDefaultHabitat(); txManager = defaultServiceLocator.getService(TransactionManager.class); invMgr = defaultServiceLocator.getService(InvocationManager.class); compEnvMgr = defaultServiceLocator.getService(ComponentEnvManager.class); callFlowAgent = defaultServiceLocator.getService(CallFlowAgent.class); } public StoredProcedureQuery createNamedStoredProcedureQuery(String name) { // TODO: implement throw new RuntimeException("Not implemented ... WIP ..."); } public Query createQuery(CriteriaUpdate updateQuery) { // TODO: implement throw new RuntimeException("Not implemented ... WIP ..."); } public Query createQuery(CriteriaDelete deleteQuery) { // TODO: implement throw new RuntimeException("Not implemented ... WIP ..."); } public StoredProcedureQuery createStoredProcedureQuery(String procedureName) { // TODO: implement throw new RuntimeException("Not implemented ... WIP ..."); } public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) { // TODO: implement throw new RuntimeException("Not implemented ... WIP ..."); } public StoredProcedureQuery createStoredProcedureQuery(String procedureName, String... resultSetMappings) { // TODO: implement throw new RuntimeException("Not implemented ... WIP ..."); } public boolean isJoinedToTransaction() { // TODO: implement throw new RuntimeException("Not implemented ... WIP ..."); } }