use of org.apache.openejb.core.transaction.TransactionPolicy in project tomee by apache.
the class StatelessContainer method _invoke.
@SuppressWarnings("ThrowFromFinallyBlock")
private Object _invoke(final Method callMethod, final Method runMethod, final Object[] args, final Instance instance, final ThreadContext callContext, final InterfaceType type) throws OpenEJBException {
final BeanContext beanContext = callContext.getBeanContext();
final TransactionPolicy txPolicy = createTransactionPolicy(beanContext.getTransactionType(callMethod, type), callContext);
Object returnValue = null;
try {
if (type == InterfaceType.SERVICE_ENDPOINT) {
callContext.setCurrentOperation(Operation.BUSINESS_WS);
returnValue = invokeWebService(args, beanContext, runMethod, instance);
} else {
final List<InterceptorData> interceptors = beanContext.getMethodInterceptors(runMethod);
final Operation operation = type == InterfaceType.TIMEOUT ? Operation.TIMEOUT : Operation.BUSINESS;
final InterceptorStack interceptorStack = new InterceptorStack(instance.bean, runMethod, operation, interceptors, instance.interceptors);
returnValue = interceptorStack.invoke(args);
}
} catch (final Throwable re) {
// handle reflection exception
final ExceptionType exceptionType = beanContext.getExceptionType(re);
if (exceptionType == ExceptionType.SYSTEM) {
/* System Exception ****************************/
// The bean instance is not put into the pool via instanceManager.poolInstance
// and therefore the instance will be garbage collected and destroyed.
// In case of StrictPooling flag being set to true we also release the semaphore
// in the discardInstance method of the instanceManager.
callContext.setDiscardInstance(true);
handleSystemException(txPolicy, re, callContext);
} else {
/* Application Exception ***********************/
handleApplicationException(txPolicy, re, exceptionType == ExceptionType.APPLICATION_ROLLBACK);
}
} finally {
try {
afterInvoke(txPolicy, callContext);
} catch (final SystemException | RuntimeException e) {
callContext.setDiscardInstance(true);
throw e;
}
}
return returnValue;
}
use of org.apache.openejb.core.transaction.TransactionPolicy in project tomee by apache.
the class StatefulContainer method createEJBObject.
protected ProxyInfo createEJBObject(final BeanContext beanContext, final Method callMethod, final Object[] args, final InterfaceType interfaceType) throws OpenEJBException {
// generate a new primary key
final Object primaryKey = newPrimaryKey();
final ThreadContext createContext = new ThreadContext(beanContext, primaryKey);
final ThreadContext oldCallContext = ThreadContext.enter(createContext);
Object runAs = null;
try {
if (oldCallContext != null) {
final BeanContext oldBc = oldCallContext.getBeanContext();
if (oldBc.getRunAsUser() != null || oldBc.getRunAs() != null) {
runAs = AbstractSecurityService.class.cast(securityService).overrideWithRunAsContext(createContext, beanContext, oldBc);
}
}
// Security check
checkAuthorization(callMethod, interfaceType);
// Create the extended entity managers for this instance
final Index<EntityManagerFactory, JtaEntityManagerRegistry.EntityManagerTracker> entityManagers = createEntityManagers(beanContext);
// Register the newly created entity managers
if (entityManagers != null) {
try {
entityManagerRegistry.addEntityManagers((String) beanContext.getDeploymentID(), primaryKey, entityManagers);
} catch (final EntityManagerAlreadyRegisteredException e) {
throw new EJBException(e);
}
}
createContext.setCurrentOperation(Operation.CREATE);
createContext.setCurrentAllowedStates(null);
// Start transaction
final TransactionPolicy txPolicy = EjbTransactionUtil.createTransactionPolicy(createContext.getBeanContext().getTransactionType(callMethod, interfaceType), createContext);
Instance instance = null;
try {
try {
final InstanceContext context = beanContext.newInstance();
// Wrap-up everthing into a object
instance = new Instance(beanContext, primaryKey, containerID, context.getBean(), context.getCreationalContext(), context.getInterceptors(), entityManagers, lockFactory.newLock(primaryKey.toString()));
} catch (final Throwable throwable) {
final ThreadContext callContext = ThreadContext.getThreadContext();
EjbTransactionUtil.handleSystemException(callContext.getTransactionPolicy(), throwable, callContext);
// should never be reached
throw new IllegalStateException(throwable);
}
// add to cache
if (isPassivable(beanContext)) {
// no need to cache it it will never expires
cache.add(primaryKey, instance);
}
// instance starts checked-out
checkedOutInstances.put(primaryKey, instance);
// Register for synchronization callbacks
registerSessionSynchronization(instance, createContext);
// Invoke create for legacy beans
if (!callMethod.getDeclaringClass().equals(BeanContext.BusinessLocalHome.class) && !callMethod.getDeclaringClass().equals(BeanContext.BusinessRemoteHome.class) && !callMethod.getDeclaringClass().equals(BeanContext.BusinessLocalBeanHome.class)) {
// Setup for business invocation
final Method createOrInit = beanContext.getMatchingBeanMethod(callMethod);
createContext.set(Method.class, createOrInit);
// Initialize interceptor stack
final InterceptorStack interceptorStack = new InterceptorStack(instance.bean, createOrInit, Operation.CREATE, new ArrayList<InterceptorData>(), new HashMap<String, Object>());
// Invoke
if (args == null) {
interceptorStack.invoke();
} else {
interceptorStack.invoke(args);
}
}
} catch (final Throwable e) {
handleException(createContext, txPolicy, e);
} finally {
// un register EntityManager
unregisterEntityManagers(instance, createContext);
afterInvoke(createContext, txPolicy, instance);
}
return new ProxyInfo(beanContext, primaryKey);
} finally {
if (runAs != null) {
try {
securityService.associate(runAs);
} catch (final LoginException e) {
// no-op
}
}
ThreadContext.exit(oldCallContext);
}
}
use of org.apache.openejb.core.transaction.TransactionPolicy in project tomee by apache.
the class StatefulContainer method getTransaction.
private Transaction getTransaction(final ThreadContext callContext) {
final TransactionPolicy policy = callContext.getTransactionPolicy();
Transaction currentTransaction = null;
if (policy instanceof JtaTransactionPolicy) {
final JtaTransactionPolicy jtaPolicy = (JtaTransactionPolicy) policy;
currentTransaction = jtaPolicy.getCurrentTransaction();
}
return currentTransaction;
}
use of org.apache.openejb.core.transaction.TransactionPolicy in project tomee by apache.
the class TransactionRule method apply.
@Override
public Statement apply(final Statement base, final Description description) {
final Method mtd = getMethod(description.getTestClass(), description.getMethodName());
final Transaction tx = mtd.getAnnotation(Transaction.class);
if (tx != null) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
final TransactionManager transactionManager = SystemInstance.get().getComponent(TransactionManager.class);
final JtaTransactionPolicyFactory factory = new JtaTransactionPolicyFactory(transactionManager);
final TransactionPolicy policy = factory.createTransactionPolicy(TransactionType.RequiresNew);
try {
base.evaluate();
} finally {
if (tx.rollback()) {
policy.setRollbackOnly();
}
policy.commit();
}
}
};
} else {
return new Statement() {
@Override
public void evaluate() throws Throwable {
base.evaluate();
}
};
}
}
use of org.apache.openejb.core.transaction.TransactionPolicy in project tomee by apache.
the class EntityInstanceManager method poolInstance.
public void poolInstance(final ThreadContext callContext, final EntityBean bean, final Object primaryKey) throws OpenEJBException {
if (bean == null) {
return;
}
// primary key is null if its a servicing a home methods (create, find, ejbHome)
final TransactionPolicy txPolicy = callContext.getTransactionPolicy();
if (primaryKey != null && txPolicy != null && txPolicy.isTransactionActive()) {
final Key key = new Key(callContext.getBeanContext().getDeploymentID(), primaryKey);
SynchronizationWrapper wrapper = (SynchronizationWrapper) txPolicy.getResource(key);
if (wrapper != null) {
if (callContext.getCurrentOperation() == Operation.REMOVE) {
/*
* The bean is being returned to the pool after it has been removed. Its
* important at this point to mark the bean as disassociated to prevent
* it's ejbStore method from bean called (see SynchronizationWrapper.beforeCompletion() method)
* and that subsequent methods can not be invoked on the bean identity (see obtainInstance() method).
*/
wrapper.disassociate();
/*
* If the bean has been removed then the bean instance is no longer needed and can return to the methodReadyPool
* to service another identity.
*/
final Stack methodReadyPool = poolMap.get(callContext.getBeanContext().getDeploymentID());
methodReadyPool.push(bean);
} else {
if (callContext.getCurrentOperation() == Operation.CREATE) {
// Bean is being recreated (new-delete-new) so we need to reassociate it
wrapper.associate();
}
wrapper.setEntityBean(bean);
}
} else {
/*
A wrapper will not exist if the bean is being returned after a create operation.
In this case the transaction scope is broader then the create method itself; its a client
initiated transaction, so the bean must be registered with the tranaction and moved to the
tx ready pool
*/
wrapper = new SynchronizationWrapper(callContext.getBeanContext(), primaryKey, bean, true, key, txPolicy);
txPolicy.registerSynchronization(wrapper);
txPolicy.putResource(key, wrapper);
}
} else {
if (primaryKey != null && callContext.getCurrentOperation() != Operation.REMOVE) {
/*
* If the bean has a primary key; And its not being returned following a remove operation;
* then the bean is being returned to the method ready pool after successfully executing a business method or create
* method. In this case we need to call the bean instance's ejbPassivate before returning it to the pool per EJB 1.1
* Section 9.1.
*/
final Operation currentOp = callContext.getCurrentOperation();
callContext.setCurrentOperation(Operation.PASSIVATE);
try {
/*
In the event of an exception, OpenEJB is required to log the exception, evict the instance,
and mark the transaction for rollback. If there is a transaction to rollback, then the a
javax.transaction.TransactionRolledbackException must be throw to the client.
See EJB 1.1 specification, section 12.3.2
*/
bean.ejbPassivate();
} catch (final Throwable e) {
if (txPolicy.isTransactionActive()) {
txPolicy.setRollbackOnly(e);
throw new ApplicationException(new TransactionRolledbackException("Reflection exception thrown while attempting to call ejbPassivate() on the instance", e));
}
throw new ApplicationException(new RemoteException("Reflection exception thrown while attempting to call ejbPassivate() on the instance. Exception message = " + e.getMessage(), e));
} finally {
callContext.setCurrentOperation(currentOp);
}
}
/*
* The bean is returned to the method ready pool if its returned after servicing a find, ejbHome, business or create
* method and is not still part of a tx. While in the method ready pool the bean instance is not associated with a
* primary key and may be used to service a request for any bean of the same class.
*/
final Stack methodReadyPool = poolMap.get(callContext.getBeanContext().getDeploymentID());
methodReadyPool.push(bean);
}
}
Aggregations