public void timedOut(Instance instance) { BeanContext beanContext = instance.beanContext; ThreadContext threadContext = new ThreadContext(beanContext, instance.primaryKey, Operation.PRE_DESTROY); threadContext.setCurrentAllowedStates(null); ThreadContext oldContext = ThreadContext.enter(threadContext); try { Method remove = instance.bean instanceof SessionBean ? SessionBean.class.getMethod("ejbRemove") : null; List<InterceptorData> callbackInterceptors = beanContext.getCallbackInterceptors(); InterceptorStack interceptorStack = new InterceptorStack( instance.bean, remove, Operation.PRE_DESTROY, callbackInterceptors, instance.interceptors); interceptorStack.invoke(); } catch (Throwable e) { logger.error( "An unexpected exception occured while invoking the ejbRemove method on the timed-out Stateful SessionBean instance", e); } finally { logger.info("Removing the timed-out stateful session bean instance " + instance.primaryKey); ThreadContext.exit(oldContext); } }
public void afterLoad(Instance instance) throws SystemException, ApplicationException { BeanContext beanContext = instance.beanContext; ThreadContext threadContext = new ThreadContext(instance.beanContext, instance.primaryKey, Operation.ACTIVATE); ThreadContext oldContext = ThreadContext.enter(threadContext); try { Method remove = instance.bean instanceof SessionBean ? SessionBean.class.getMethod("ejbActivate") : null; List<InterceptorData> callbackInterceptors = beanContext.getCallbackInterceptors(); InterceptorStack interceptorStack = new InterceptorStack( instance.bean, remove, Operation.ACTIVATE, callbackInterceptors, instance.interceptors); interceptorStack.invoke(); } catch (Throwable callbackException) { discardInstance(threadContext); handleSystemException( threadContext.getTransactionPolicy(), callbackException, threadContext); } finally { ThreadContext.exit(oldContext); } }
public void beforeStore(Instance instance) { BeanContext beanContext = instance.beanContext; ThreadContext threadContext = new ThreadContext(beanContext, instance.primaryKey, Operation.PASSIVATE); ThreadContext oldContext = ThreadContext.enter(threadContext); try { Method passivate = instance.bean instanceof SessionBean ? SessionBean.class.getMethod("ejbPassivate") : null; List<InterceptorData> callbackInterceptors = beanContext.getCallbackInterceptors(); InterceptorStack interceptorStack = new InterceptorStack( instance.bean, passivate, Operation.PASSIVATE, callbackInterceptors, instance.interceptors); interceptorStack.invoke(); } catch (Throwable e) { logger.error( "An unexpected exception occured while invoking the ejbPassivate method on the Stateful SessionBean instance", e); } finally { ThreadContext.exit(oldContext); } }
public void afterCompletion(Status status) { Throwable firstException = null; for (Synchronization synchronization : registry.values()) { Instance instance = synchronization.instance; ThreadContext callContext = new ThreadContext( instance.beanContext, instance.primaryKey, Operation.AFTER_COMPLETION); callContext.setCurrentAllowedStates(null); ThreadContext oldCallContext = ThreadContext.enter(callContext); try { instance.setInUse(true); if (synchronization.isCallSessionSynchronization()) { BeanContext beanContext = instance.beanContext; List<InterceptorData> interceptors = beanContext.getCallbackInterceptors(); InterceptorStack interceptorStack = new InterceptorStack( instance.bean, null, Operation.AFTER_COMPLETION, interceptors, instance.interceptors); interceptorStack.invoke(status == Status.COMMITTED); } instance.setTransaction(null); releaseInstance(instance); } catch (InvalidateReferenceException inv) { // exception has alredy been handled } catch (Throwable e) { String message = "An unexpected system exception occured while invoking the afterCompletion method on the SessionSynchronization object"; // [1] Log the exception or error logger.error(message, e); // Transaction is complete so can not be rolled back // [3] Discard the instance discardInstance(callContext); // [4] throw throw first exception to the client if (firstException == null) firstException = e; } finally { ThreadContext.exit(oldCallContext); } } if (firstException != null) { throw new RuntimeException( "An unexpected system exception occured while invoking the afterCompletion method on the SessionSynchronization object", firstException); } }
public void beforeCompletion() { for (Synchronization synchronization : registry.values()) { Instance instance = synchronization.instance; // don't call beforeCompletion when transaction is marked rollback only if (txPolicy.isRollbackOnly()) return; // only call beforeCompletion on beans with session synchronization if (!synchronization.isCallSessionSynchronization()) continue; // Invoke beforeCompletion ThreadContext callContext = new ThreadContext( instance.beanContext, instance.primaryKey, Operation.BEFORE_COMPLETION); callContext.setCurrentAllowedStates(null); ThreadContext oldCallContext = ThreadContext.enter(callContext); try { instance.setInUse(true); BeanContext beanContext = instance.beanContext; List<InterceptorData> interceptors = beanContext.getCallbackInterceptors(); InterceptorStack interceptorStack = new InterceptorStack( instance.bean, null, Operation.BEFORE_COMPLETION, interceptors, instance.interceptors); interceptorStack.invoke(); instance.setInUse(false); } catch (InvalidateReferenceException e) { // exception has alredy been handled } catch (Exception e) { String message = "An unexpected system exception occured while invoking the beforeCompletion method on the SessionSynchronization object"; // [1] Log the exception or error logger.error(message, e); // [2] Mark the transaction for rollback. txPolicy.setRollbackOnly(e); // [3] Discard the instance discardInstance(callContext); // [4] throw the java.rmi.RemoteException to the client throw new RuntimeException(message, e); } finally { ThreadContext.exit(oldCallContext); } } }
private Instance createInstance(ThreadContext callContext, BeanContext beanContext) throws ApplicationException { try { initializeDependencies(beanContext); final InstanceContext context = beanContext.newInstance(); if (context.getBean() instanceof SessionBean) { final Operation originalOperation = callContext.getCurrentOperation(); try { callContext.setCurrentOperation(Operation.CREATE); final Method create = beanContext.getCreateMethod(); final InterceptorStack ejbCreate = new InterceptorStack( context.getBean(), create, Operation.CREATE, new ArrayList<InterceptorData>(), new HashMap()); ejbCreate.invoke(); } finally { callContext.setCurrentOperation(originalOperation); } } ReadWriteLock lock; if (beanContext.isBeanManagedConcurrency()) { // Bean-Managed Concurrency lock = new BeanManagedLock(); } else { // Container-Managed Concurrency lock = new ReentrantReadWriteLock(); } return new Instance( context.getBean(), context.getInterceptors(), context.getCreationalContext(), lock); } catch (Throwable e) { if (e instanceof java.lang.reflect.InvocationTargetException) { e = ((java.lang.reflect.InvocationTargetException) e).getTargetException(); } String t = "The bean instance " + beanContext.getDeploymentID() + " threw a system exception:" + e; logger.error(t, e); throw new ApplicationException( new NoSuchEJBException("Singleton failed to initialize").initCause(e)); } }
private void registerSessionSynchronization( Instance instance, BeanContext beanContext, Object primaryKey, boolean synchronize) { Synchronization synchronization = registry.get(primaryKey); if (synchronization == null) { synchronization = new Synchronization(instance); registry.put(primaryKey, synchronization); } boolean wasSynchronized = synchronization.setCallSessionSynchronization(synchronize); // check if afterBegin has already been invoked or if this is not a session synchronization // bean if (wasSynchronized || !synchronize) { return; } // Invoke afterBegin ThreadContext callContext = new ThreadContext(instance.beanContext, instance.primaryKey, Operation.AFTER_BEGIN); callContext.setCurrentAllowedStates(null); ThreadContext oldCallContext = ThreadContext.enter(callContext); try { List<InterceptorData> interceptors = beanContext.getCallbackInterceptors(); InterceptorStack interceptorStack = new InterceptorStack( instance.bean, null, Operation.AFTER_BEGIN, interceptors, instance.interceptors); interceptorStack.invoke(); } catch (Exception e) { String message = "An unexpected system exception occured while invoking the afterBegin method on the SessionSynchronization object"; // [1] Log the exception or error logger.error(message, e); // Caller handles transaction rollback and discardInstance // [4] throw the java.rmi.RemoteException to the client throw new RuntimeException(message, e); } finally { ThreadContext.exit(oldCallContext); } }
private Object invokeWebService( Object[] args, BeanContext beanContext, Method runMethod, Instance instance, Object returnValue) throws Exception { if (args.length < 2) { throw new IllegalArgumentException( "WebService calls must follow format {messageContext, interceptor, [arg...]}."); } Object messageContext = args[0]; // This object will be used as an interceptor in the stack and will be responsible // for unmarshalling the soap message parts into an argument list that will be // used for the actual method invocation. // // We just need to make it an interceptor in the OpenEJB sense and tack it on the end // of our stack. Object interceptor = args[1]; // Add the webservice interceptor to the list of interceptor instances Map<String, Object> interceptors = new HashMap<String, Object>(instance.interceptors); { interceptors.put(interceptor.getClass().getName(), interceptor); } // Create an InterceptorData for the webservice interceptor to the list of interceptorDatas for // this method List<InterceptorData> interceptorDatas = new ArrayList<InterceptorData>(); { InterceptorData providerData = new InterceptorData(interceptor.getClass()); ClassFinder finder = new ClassFinder(interceptor.getClass()); providerData.getAroundInvoke().addAll(finder.findAnnotatedMethods(AroundInvoke.class)); // interceptorDatas.add(providerData); interceptorDatas.add(0, providerData); interceptorDatas.addAll(beanContext.getMethodInterceptors(runMethod)); } InterceptorStack interceptorStack = new InterceptorStack( instance.bean, runMethod, Operation.BUSINESS_WS, interceptorDatas, interceptors); Object[] params = new Object[runMethod.getParameterTypes().length]; if (messageContext instanceof javax.xml.rpc.handler.MessageContext) { ThreadContext.getThreadContext() .set( javax.xml.rpc.handler.MessageContext.class, (javax.xml.rpc.handler.MessageContext) messageContext); returnValue = interceptorStack.invoke((javax.xml.rpc.handler.MessageContext) messageContext, params); } else if (messageContext instanceof javax.xml.ws.handler.MessageContext) { AddressingSupport wsaSupport = NoAddressingSupport.INSTANCE; for (int i = 2; i < args.length; i++) { if (args[i] instanceof AddressingSupport) { wsaSupport = (AddressingSupport) args[i]; } } ThreadContext.getThreadContext().set(AddressingSupport.class, wsaSupport); ThreadContext.getThreadContext() .set( javax.xml.ws.handler.MessageContext.class, (javax.xml.ws.handler.MessageContext) messageContext); returnValue = interceptorStack.invoke((javax.xml.ws.handler.MessageContext) messageContext, params); } return returnValue; }
protected Object _invoke( Method callMethod, Method runMethod, Object[] args, Instance instance, ThreadContext callContext, InterfaceType type) throws OpenEJBException { BeanContext beanContext = callContext.getBeanContext(); 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, returnValue); } else { List<InterceptorData> interceptors = beanContext.getMethodInterceptors(runMethod); InterceptorStack interceptorStack = new InterceptorStack( instance.bean, runMethod, type == InterfaceType.TIMEOUT ? Operation.TIMEOUT : Operation.BUSINESS, interceptors, instance.interceptors); returnValue = interceptorStack.invoke(args); } } catch (Throwable re) { // handle reflection exception 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 (SystemException e) { callContext.setDiscardInstance(true); throw e; } catch (ApplicationException e) { throw e; } catch (RuntimeException e) { callContext.setDiscardInstance(true); throw e; } } return returnValue; }
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); } }
protected ProxyInfo createEJBObject( BeanContext beanContext, Method callMethod, Object[] args, InterfaceType interfaceType) throws OpenEJBException { // generate a new primary key Object primaryKey = newPrimaryKey(); ThreadContext createContext = new ThreadContext(beanContext, primaryKey); ThreadContext oldCallContext = ThreadContext.enter(createContext); try { // Security check checkAuthorization(callMethod, interfaceType); // Create the extended entity managers for this instance 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 (EntityManagerAlreadyRegisteredException e) { throw new EJBException(e); } } createContext.setCurrentOperation(Operation.CREATE); createContext.setCurrentAllowedStates(null); // Start transaction TransactionPolicy txPolicy = createTransactionPolicy( createContext.getBeanContext().getTransactionType(callMethod, interfaceType), createContext); Instance instance = null; try { // Create new instance try { final InstanceContext context = beanContext.newInstance(); // Wrap-up everthing into a object instance = new Instance( beanContext, primaryKey, context.getBean(), context.getInterceptors(), context.getCreationalContext(), entityManagers); } catch (Throwable throwable) { ThreadContext callContext = ThreadContext.getThreadContext(); handleSystemException(callContext.getTransactionPolicy(), throwable, callContext); throw new IllegalStateException(throwable); // should never be reached } // add to cache 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 Method createOrInit = beanContext.getMatchingBeanMethod(callMethod); createContext.set(Method.class, createOrInit); // Initialize interceptor stack 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 (Throwable e) { handleException(createContext, txPolicy, e); } finally { afterInvoke(createContext, txPolicy, instance); } return new ProxyInfo(beanContext, primaryKey); } finally { ThreadContext.exit(oldCallContext); } }
public void freeInstance(ThreadContext callContext) { BeanContext beanContext = callContext.getBeanContext(); Data data = (Data) beanContext.getContainerData(); Future<Instance> instanceFuture = data.singleton.get(); // Possible the instance was never created if (instanceFuture == null) return; Instance instance; try { instance = instanceFuture.get(); } catch (InterruptedException e) { Thread.interrupted(); logger.error( "Singleton shutdown failed because the thread was interrupted: " + beanContext.getDeploymentID(), e); return; } catch (ExecutionException e) { // Instance was never initialized return; } try { callContext.setCurrentOperation(Operation.PRE_DESTROY); callContext.setCurrentAllowedStates(null); Method remove = instance.bean instanceof SessionBean ? beanContext.getCreateMethod() : null; List<InterceptorData> callbackInterceptors = beanContext.getCallbackInterceptors(); InterceptorStack interceptorStack = new InterceptorStack( instance.bean, remove, Operation.PRE_DESTROY, callbackInterceptors, instance.interceptors); // Transaction Demarcation for Singleton PostConstruct method TransactionType transactionType; if (beanContext.getComponentType() == BeanType.SINGLETON) { Set<Method> callbacks = callbackInterceptors.get(callbackInterceptors.size() - 1).getPreDestroy(); if (callbacks.isEmpty()) { transactionType = TransactionType.RequiresNew; } else { transactionType = beanContext.getTransactionType(callbacks.iterator().next()); if (transactionType == TransactionType.Required) { transactionType = TransactionType.RequiresNew; } } } else { transactionType = beanContext.isBeanManagedTransaction() ? TransactionType.BeanManaged : TransactionType.NotSupported; } TransactionPolicy transactionPolicy = EjbTransactionUtil.createTransactionPolicy(transactionType, callContext); try { // Call the chain interceptorStack.invoke(); if (instance.creationalContext != null) { instance.creationalContext.release(); } } catch (Throwable e) { // RollBack Transaction EjbTransactionUtil.handleSystemException(transactionPolicy, e, callContext); } finally { EjbTransactionUtil.afterInvoke(transactionPolicy, callContext); } } catch (Throwable re) { logger.error("Singleton shutdown failed: " + beanContext.getDeploymentID(), re); } }
protected Object _invoke( Method callMethod, Method runMethod, Object[] args, Instance instance, ThreadContext callContext, InterfaceType callType) throws OpenEJBException { BeanContext beanContext = callContext.getBeanContext(); Duration accessTimeout = getAccessTimeout(beanContext, runMethod); boolean read = beanContext.getConcurrencyAttribute(runMethod) == javax.ejb.LockType.READ; final Lock lock = aquireLock(read, accessTimeout, instance, runMethod); Object returnValue; try { TransactionPolicy txPolicy = createTransactionPolicy( beanContext.getTransactionType(callMethod, callType), callContext); returnValue = null; try { if (callType == InterfaceType.SERVICE_ENDPOINT) { callContext.setCurrentOperation(Operation.BUSINESS_WS); returnValue = invokeWebService(args, beanContext, runMethod, instance); } else { List<InterceptorData> interceptors = beanContext.getMethodInterceptors(runMethod); InterceptorStack interceptorStack = new InterceptorStack( instance.bean, runMethod, callType == InterfaceType.TIMEOUT ? Operation.TIMEOUT : Operation.BUSINESS, interceptors, instance.interceptors); returnValue = interceptorStack.invoke(args); } } catch (Throwable e) { // handle reflection exception ExceptionType type = beanContext.getExceptionType(e); if (type == 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. // For this reason the discardInstance method of the StatelessInstanceManager // does nothing. handleSystemException(txPolicy, e, callContext); } else { /* Application Exception ***********************/ handleApplicationException(txPolicy, e, type == ExceptionType.APPLICATION_ROLLBACK); } } finally { afterInvoke(txPolicy, callContext); } } finally { lock.unlock(); } return returnValue; }