private void releaseInstance(Instance instance) { // Don't pool if the bean has been undeployed if (instance.beanContext.isDestroyed()) return; // verify the instance is not associated with a bean-managed transaction if (instance.getBeanTransaction() != null) { new IllegalStateException("Instance has an active bean-managed transaction"); } // no longer in use instance.setInUse(false); if (instance.getTransaction() == null) { // return to cache cache.checkIn(instance.primaryKey); // no longer checked out checkedOutInstances.remove(instance.primaryKey); } }
protected Object businessMethod( BeanContext beanContext, Object primKey, Class callInterface, Method callMethod, Object[] args, InterfaceType interfaceType) throws OpenEJBException { ThreadContext callContext = new ThreadContext(beanContext, primKey); ThreadContext oldCallContext = ThreadContext.enter(callContext); try { // Security check checkAuthorization(callMethod, interfaceType); // Start transaction TransactionPolicy txPolicy = createTransactionPolicy( callContext.getBeanContext().getTransactionType(callMethod, interfaceType), callContext); Object returnValue = null; Instance instance = null; try { // Obtain instance instance = obtainInstance(primKey, callContext); // Resume previous Bean transaction if there was one if (txPolicy instanceof BeanTransactionPolicy) { SuspendedTransaction suspendedTransaction = instance.getBeanTransaction(); if (suspendedTransaction != null) { instance.setBeanTransaction(null); BeanTransactionPolicy beanTxEnv = (BeanTransactionPolicy) txPolicy; beanTxEnv.resumeUserTransaction(suspendedTransaction); } } // Register the entity managers registerEntityManagers(instance, callContext); // Register for synchronization callbacks registerSessionSynchronization(instance, callContext); // Setup for business invocation callContext.setCurrentOperation(Operation.BUSINESS); callContext.setCurrentAllowedStates(null); callContext.setInvokedInterface(callInterface); Method runMethod = beanContext.getMatchingBeanMethod(callMethod); callContext.set(Method.class, runMethod); // Initialize interceptor stack List<InterceptorData> interceptors = beanContext.getMethodInterceptors(runMethod); InterceptorStack interceptorStack = new InterceptorStack( instance.bean, runMethod, Operation.BUSINESS, interceptors, instance.interceptors); // Invoke returnValue = interceptorStack.invoke(args); } catch (Throwable e) { handleException(callContext, txPolicy, e); } finally { // Commit transaction afterInvoke(callContext, txPolicy, instance); } return returnValue; } finally { ThreadContext.exit(oldCallContext); } }
protected Object removeEJBObject( BeanContext beanContext, Object primKey, Class callInterface, Method callMethod, Object[] args, InterfaceType interfaceType) throws OpenEJBException { if (primKey == null) throw new NullPointerException("primKey is null"); ThreadContext callContext = new ThreadContext(beanContext, primKey); ThreadContext oldCallContext = ThreadContext.enter(callContext); try { // Security check checkAuthorization(callMethod, interfaceType); // If a bean managed transaction is active, the bean can not be removed if (interfaceType.isComponent()) { Instance instance = checkedOutInstances.get(primKey); /** * According to EJB 3.0 "4.4.4 Restrictions for Transactions" any remove methods from home * or component interfaces must not be allowed if the bean instance is in a transaction. * Unfortunately, the Java EE 5 TCK has tests that ignore the restrictions in 4.4.4 and * expect beans in transactions can be removed via their home or component interface. The * test to see if the bean instance implements javax.ejb.SessionBean is a workaround for * passing the TCK while the tests in question can be challenged or the spec can be * changed/updated. */ if (instance != null && instance.bean instanceof javax.ejb.SessionBean) { throw new ApplicationException( new RemoveException("A stateful EJB enrolled in a transaction can not be removed")); } } // Start transaction TransactionPolicy txPolicy = createTransactionPolicy( callContext.getBeanContext().getTransactionType(callMethod, interfaceType), callContext); Object returnValue = null; boolean retain = false; Instance instance = null; Method runMethod = null; try { // Obtain instance instance = obtainInstance(primKey, callContext); // Resume previous Bean transaction if there was one if (txPolicy instanceof BeanTransactionPolicy) { // Resume previous Bean transaction if there was one SuspendedTransaction suspendedTransaction = instance.getBeanTransaction(); if (suspendedTransaction != null) { instance.setBeanTransaction(null); BeanTransactionPolicy beanTxEnv = (BeanTransactionPolicy) txPolicy; beanTxEnv.resumeUserTransaction(suspendedTransaction); } } // Register the entity managers registerEntityManagers(instance, callContext); // Register for synchronization callbacks registerSessionSynchronization(instance, callContext); // Setup for remove invocation callContext.setCurrentOperation(Operation.REMOVE); callContext.setCurrentAllowedStates(null); callContext.setInvokedInterface(callInterface); runMethod = beanContext.getMatchingBeanMethod(callMethod); callContext.set(Method.class, runMethod); // Do not pass arguments on home.remove(remote) calls Class<?> declaringClass = callMethod.getDeclaringClass(); if (declaringClass.equals(EJBHome.class) || declaringClass.equals(EJBLocalHome.class)) { args = new Object[] {}; } // Initialize interceptor stack List<InterceptorData> interceptors = beanContext.getMethodInterceptors(runMethod); InterceptorStack interceptorStack = new InterceptorStack( instance.bean, runMethod, Operation.REMOVE, interceptors, instance.interceptors); // Invoke if (args == null) { returnValue = interceptorStack.invoke(); } else { returnValue = interceptorStack.invoke(args); } } catch (InvalidateReferenceException e) { throw e; } catch (Throwable e) { if (interfaceType.isBusiness()) { retain = beanContext.retainIfExeption(runMethod); handleException(callContext, txPolicy, e); } else { try { handleException(callContext, txPolicy, e); } catch (ApplicationException ae) { // Don't throw application exceptions for non-business interface removes } } } finally { if (!retain) { try { callContext.setCurrentOperation(Operation.PRE_DESTROY); List<InterceptorData> callbackInterceptors = beanContext.getCallbackInterceptors(); InterceptorStack interceptorStack = new InterceptorStack( instance.bean, null, Operation.PRE_DESTROY, callbackInterceptors, instance.interceptors); interceptorStack.invoke(); } catch (Throwable callbackException) { String logMessage = "An unexpected exception occured while invoking the preDestroy method on the removed Stateful SessionBean instance; " + callbackException.getClass().getName() + " " + callbackException.getMessage(); /* [1] Log the exception or error */ logger.error(logMessage); } finally { callContext.setCurrentOperation(Operation.REMOVE); } // todo destroy extended persistence contexts discardInstance(callContext); } // Commit transaction afterInvoke(callContext, txPolicy, instance); } return returnValue; } finally { ThreadContext.exit(oldCallContext); } }