com.sun.enterprise.container.common.impl.EntityManagerWrapper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of payara-micro Show documentation
Show all versions of payara-micro Show documentation
Micro Distribution of the Payara Project
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2014 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.
*/
// Portions Copyright [2016-2021] [Payara Foundation]
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.ComponentInvocationHandler;
import org.glassfish.api.invocation.InvocationException;
import org.glassfish.api.invocation.InvocationManager;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.internal.api.Globals;
import org.jvnet.hk2.annotations.Service;
import static jakarta.persistence.SynchronizationType.SYNCHRONIZED;
import static jakarta.persistence.SynchronizationType.UNSYNCHRONIZED;
import jakarta.persistence.criteria.*;
import jakarta.persistence.*;
import jakarta.persistence.metamodel.Metamodel;
import jakarta.transaction.TransactionManager;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
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, false);
// Serializable state
private String unitName;
private PersistenceContextType contextType;
private Map emProperties;
private SynchronizationType synchronizationType;
// 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;
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, SynchronizationType synchronizationType, Map emProperties) {
this.unitName = unitName;
this.contextType = contextType;
this.synchronizationType = synchronizationType;
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();
}
if( getCurrentTransaction() == null ) {
throw new TransactionRequiredException();
}
}
private EntityManager _getDelegate() {
// Populate any transient objects the first time
// this method is called.
if( entityManagerFactory == null ) {
init();
}
EntityManager delegate;
if( contextType == PersistenceContextType.TRANSACTION ) {
JavaEETransaction tx = getCurrentTransaction();
if( tx != null ) {
// If there is an active extended persistence context
// for the same entity manager factory and the same tx,
// it takes precedence.
PhysicalEntityManagerWrapper propagatedPersistenceContext = getExtendedEntityManager(tx, entityManagerFactory);
if(propagatedPersistenceContext == null) {
propagatedPersistenceContext = getTxEntityManager(tx, entityManagerFactory);
if( propagatedPersistenceContext == 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.
EntityManager em = entityManagerFactory.createEntityManager(synchronizationType, emProperties);
propagatedPersistenceContext = new PhysicalEntityManagerWrapper(em, synchronizationType);
tx.addTxEntityManagerMapping(entityManagerFactory, propagatedPersistenceContext);
} else {
//Check if sync type of current persistence context is compatible with persistence context being propagated
if(synchronizationType == SYNCHRONIZED && propagatedPersistenceContext.getSynchronizationType() == UNSYNCHRONIZED) {
throw new IllegalStateException("Detected an UNSYNCHRONIZED persistence context being propagated to SYNCHRONIZED persistence context.");
}
}
}
delegate = propagatedPersistenceContext.getEM();
} else {
//Get non transactional entity manager corresponding to this wrapper from current invocation
delegate = getNonTxEMFromCurrentInvocation();
}
} 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);
}
}
}
if (extendedEntityManager == null) {
throw new IllegalStateException("No EntityManager available in current extended persistence context.");
}
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 JavaEETransaction getCurrentTransaction() {
try {
return (JavaEETransaction) txManager.getTransaction();
} catch(Exception e) {
throw new IllegalStateException("exception retrieving tx", e);
}
}
private static final Class INVOCATION_PAYLOAD_KEY = EntityManagerWrapper.class; //Key used to look up payload from current invocation
private EntityManager getNonTxEMFromCurrentInvocation() {
// We store nonTxEM as a payload in a map from EMF to EM inside current invocation.
// It will be closed during NonTxEntityManagerCleaner.beforePostInvoke() below
ComponentInvocation currentInvocation = invMgr.getCurrentInvocation();
Map nonTxEMs = getNonTxEMsFromCurrentInvocation(currentInvocation);
if(nonTxEMs == null) {
nonTxEMs = new HashMap<>();
currentInvocation.setRegistryFor(INVOCATION_PAYLOAD_KEY, nonTxEMs);
}
EntityManager nonTxEM = nonTxEMs.get(entityManagerFactory);
if(nonTxEM == null) {
// Could not find one, create new one and store it within current invocation for cleanup
nonTxEM = entityManagerFactory.createEntityManager(synchronizationType, emProperties);
nonTxEMs.put(entityManagerFactory, nonTxEM);
}
return nonTxEM;
}
@SuppressWarnings("unchecked")
private static Map getNonTxEMsFromCurrentInvocation(ComponentInvocation currentInvocation) {
return (Map)currentInvocation.getRegistryFor(INVOCATION_PAYLOAD_KEY);
}
@Override
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
}
@Override
public 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
}
@Override
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
}
@Override
public T find(Class entityClass, Object primaryKey) {
T returnValue = null;
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.FIND);
}
EntityManager delegate = _getDelegate();
returnValue = delegate.find(entityClass, primaryKey);
clearDetachedPersistenceContext (delegate);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
@Override
public T find(Class entityClass, Object primaryKey, Map properties) {
T returnValue = null;
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.FIND);
}
EntityManager delegate = _getDelegate();
returnValue = _getDelegate().find(entityClass, primaryKey, properties);
clearDetachedPersistenceContext (delegate);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
@Override
public T find(Class entityClass, Object primaryKey, LockModeType lockMode) {
T returnValue = null;
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.FIND_CLASS_OBJECT_LOCKMODETYPE);
}
EntityManager delegate = _getDelegate();
returnValue = _getDelegate().find(entityClass, primaryKey, lockMode);
clearDetachedPersistenceContext (delegate);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
@Override
public T find(Class entityClass, Object primaryKey, LockModeType lockMode, Map properties) {
T returnValue = null;
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.FIND_CLASS_OBJECT_LOCKMODETYPE_PROPERTIES);
}
EntityManager delegate = _getDelegate();
returnValue = _getDelegate().find(entityClass, primaryKey, lockMode, properties);
clearDetachedPersistenceContext (delegate);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
@Override
public T getReference(Class entityClass, Object primaryKey) {
T returnValue = null;
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_REFERENCE);
}
returnValue = _getDelegate().getReference(entityClass, primaryKey);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
@Override
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
}
@Override
public Query createQuery(String ejbqlString) {
Query returnValue = null;
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_QUERY);
}
EntityManager delegate = _getDelegate();
returnValue = delegate.createQuery(ejbqlString);
returnValue = wrapDetachedQuery(returnValue, delegate);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
@Override
public TypedQuery createQuery(String ejbqlString, Class resultClass) {
TypedQuery returnValue = null;
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_QUERY_STRING_CLASS);
}
EntityManager delegate = _getDelegate();
returnValue = delegate.createQuery(ejbqlString, resultClass);
returnValue = wrapDetachedQuery(returnValue, delegate);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
@Override
public TypedQuery createQuery(CriteriaQuery criteriaQuery) {
TypedQuery returnValue = null;
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_QUERY_CRITERIA_QUERY);
}
EntityManager delegate = _getDelegate();
returnValue = delegate.createQuery(criteriaQuery);
returnValue = wrapDetachedQuery(returnValue, delegate);
}finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
@Override
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);
returnValue = wrapDetachedQuery(returnValue, delegate);
}finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
@Override
public TypedQuery createNamedQuery(String name, Class resultClass) {
TypedQuery returnValue = null;
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_NAMED_QUERY);
}
EntityManager delegate = _getDelegate();
returnValue = delegate.createNamedQuery(name, resultClass);
returnValue = wrapDetachedQuery(returnValue, delegate);
}finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
@Override
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);
returnValue = wrapDetachedQuery(returnValue, delegate);
}finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
@Override
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);
returnValue = wrapDetachedQuery(returnValue, delegate);
}finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
@Override
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);
returnValue = wrapDetachedQuery(returnValue, delegate);
}finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
private StoredProcedureQuery wrapDetachedQuery(StoredProcedureQuery returnValue, EntityManager delegate) {
if( operatesDetached() ) {
returnValue = StoreProcedureQueryWrapper.createQueryWrapper(returnValue, delegate);
}
return returnValue;
}
private TypedQuery wrapDetachedQuery(TypedQuery returnValue, EntityManager delegate) {
if( operatesDetached() ) {
returnValue = TypedQueryWrapper.createQueryWrapper(returnValue, delegate);
}
return returnValue;
}
private Query wrapDetachedQuery(Query returnValue, EntityManager delegate) {
if( operatesDetached()) {
returnValue = QueryWrapper.createQueryWrapper(returnValue, delegate);
}
return returnValue;
}
private boolean operatesDetached() {
return getCurrentTransaction() == null && contextType != PersistenceContextType.EXTENDED;
}
@Override
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
}
@Override
public void refresh(Object entity, Map 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
}
@Override
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
}
@Override
public void refresh(Object entity, LockModeType lockMode, Map 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
}
@Override
public boolean contains(Object entity) {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CONTAINS);
}
EntityManager delegate = _getDelegate();
return delegate.contains(entity);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
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
}
@Override
public void setProperty(String propertyName, Object value) {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.SET_PROPERTY);
}
_getDelegate().setProperty(propertyName, value);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
// tx is required so there's no need to do any non-tx cleanup
}
@Override
public Map getProperties() {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_PROPERTIES);
}
return _getDelegate().getProperties();
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
public void close() {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CLOSE);
callFlowAgent.entityManagerMethodEnd();
}
// close() not allowed on container-managed EMs.
throw new IllegalStateException();
}
@Override
public boolean isOpen() {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.IS_OPEN);
callFlowAgent.entityManagerMethodEnd();
}
// Not relevant for container-managed EMs. Just return true.
return true;
}
@Override
public EntityTransaction getTransaction() {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_TRANSACTION);
}
return _getDelegate().getTransaction();
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
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();
}
}
}
@Override
public CriteriaBuilder getCriteriaBuilder() {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_CRITERIA_BUILDER);
}
return _getDelegate().getCriteriaBuilder();
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
public Metamodel getMetamodel() {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_METAMODEL);
}
return _getDelegate().getMetamodel();
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
public void lock(Object entity, LockModeType lockMode) {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.LOCK);
}
_getDelegate().lock(entity, lockMode);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
public void lock(Object entity, LockModeType lockMode, Map properties) {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.LOCK_LOCKMODETYPE_MAP);
}
_getDelegate().lock(entity, lockMode, properties);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
public void clear() {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CLEAR);
}
_getDelegate().clear();
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
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
}
@Override
public Object getDelegate() {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_DELEGATE);
}
return _getDelegate();
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
public FlushModeType getFlushMode() {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_FLUSH_MODE);
}
return _getDelegate().getFlushMode();
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
public void setFlushMode(FlushModeType flushMode) {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.SET_FLUSH_MODE);
}
_getDelegate().setFlushMode(flushMode);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
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();
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.JOIN_TRANSACTION);
}
_getDelegate().joinTransaction();
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
public T unwrap(Class tClass) {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.UNWRAP);
}
return _getDelegate().unwrap(tClass);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
public StoredProcedureQuery createNamedStoredProcedureQuery(String name) {
StoredProcedureQuery returnValue = null;
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_NAMED_STORED_PROCEDURE_QUERY);
}
EntityManager delegate = _getDelegate();
returnValue = delegate.createNamedStoredProcedureQuery(name);
returnValue = wrapDetachedQuery(returnValue, delegate);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
@Override
public StoredProcedureQuery createStoredProcedureQuery(String procedureName) {
StoredProcedureQuery returnValue = null;
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_STORED_PROCEDURE_QUERY);
}
EntityManager delegate = _getDelegate();
returnValue = delegate.createStoredProcedureQuery(procedureName);
returnValue = wrapDetachedQuery(returnValue, delegate);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
@Override
public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) {
StoredProcedureQuery returnValue = null;
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_STORED_PROCEDURE_QUERY_STRING_CLASS);
}
EntityManager delegate = _getDelegate();
returnValue = delegate.createStoredProcedureQuery(procedureName, resultClasses);
returnValue = wrapDetachedQuery(returnValue, delegate);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
@Override
public StoredProcedureQuery createStoredProcedureQuery(String procedureName, String... resultSetMappings) {
StoredProcedureQuery returnValue = null;
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_STORED_PROCEDURE_QUERY_STRING_STRING);
}
EntityManager delegate = _getDelegate();
returnValue = delegate.createStoredProcedureQuery(procedureName, resultSetMappings);
returnValue = wrapDetachedQuery(returnValue, delegate);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
return returnValue;
}
public Query createQuery(CriteriaUpdate updateQuery) {
// Unlike other create*Query() methods, there is not need to create a QueryWrapper for non trnsactional case here.
// QueryWrappers are created to ensure that entities returned by query are detatched. This is an update query and thus will not return any entities.
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_QUERY_CRITERIA_UPDATE);
}
return _getDelegate().createQuery(updateQuery);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
public Query createQuery(CriteriaDelete deleteQuery) {
// Please refer to comments in method createQuery(CriteriaUpdate) for the reason we do not create a QueryWrapper here.
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_QUERY_CRITERIA_DELETE);
}
return _getDelegate().createQuery(deleteQuery);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
public boolean isJoinedToTransaction() {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.IS_JOINED_TO_TRANSACTION);
}
return _getDelegate().isJoinedToTransaction();
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
public EntityGraph createEntityGraph(Class rootType) {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_ENTITY_GRAPH_CLASS);
}
return _getDelegate().createEntityGraph(rootType);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
public EntityGraph> createEntityGraph(String graphName) {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.CREATE_ENTITY_GRAPH_STRING);
}
return _getDelegate().createEntityGraph(graphName);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
public EntityGraph> getEntityGraph(String graphName) {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_ENTITY_GRAPH);
}
return _getDelegate().getEntityGraph(graphName);
} finally {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodEnd();
}
}
}
@Override
public List> getEntityGraphs(Class entityClass) {
try {
if(callFlowAgent.isEnabled()) {
callFlowAgent.entityManagerMethodStart(EntityManagerMethod.GET_ENTITY_GRAPHS);
}
return _getDelegate().getEntityGraphs(entityClass);
} finally {
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);
}
private void clearDetachedPersistenceContext(EntityManager em) {
if(operatesDetached()) {
em.clear();
}
}
public static PhysicalEntityManagerWrapper getExtendedEntityManager(JavaEETransaction transaction, EntityManagerFactory factory) {
return (PhysicalEntityManagerWrapper)transaction.getExtendedEntityManagerResource(factory);
}
public static PhysicalEntityManagerWrapper getTxEntityManager(JavaEETransaction transaction, EntityManagerFactory factory) {
return (PhysicalEntityManagerWrapper) transaction.getTxEntityManagerResource(factory);
}
@Service
/**
* NonTxEMs are saved as payload in current invocation. Clean them up at end of any component invocation
*/
public static class NonTxEMCleaner implements ComponentInvocationHandler {
@Override
public void beforePreInvoke(ComponentInvocation.ComponentInvocationType invType, ComponentInvocation prevInv, ComponentInvocation newInv) throws InvocationException { }
@Override
public void afterPreInvoke(ComponentInvocation.ComponentInvocationType invType, ComponentInvocation prevInv, ComponentInvocation curInv) throws InvocationException { }
@Override
public void beforePostInvoke(ComponentInvocation.ComponentInvocationType invType, ComponentInvocation prevInv, ComponentInvocation curInv) throws InvocationException {
// Close all the NonTxEMs for current invocation
Map nonTxEMs = getNonTxEMsFromCurrentInvocation(curInv);
if(nonTxEMs != null) {
for (EntityManager nonTxEM : nonTxEMs.values()) {
nonTxEM.close();
}
}
}
@Override
public void afterPostInvoke(ComponentInvocation.ComponentInvocationType invType, ComponentInvocation prevInv, ComponentInvocation curInv) throws InvocationException { }
}
}