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 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 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 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 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); } }
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); } }
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); } }