private void afterInvoke(ThreadContext callContext, TransactionPolicy txPolicy, Instance instance)
     throws OpenEJBException {
   try {
     unregisterEntityManagers(instance, callContext);
     if (instance != null && txPolicy instanceof BeanTransactionPolicy) {
       // suspend the currently running transaction if any
       SuspendedTransaction suspendedTransaction = null;
       try {
         BeanTransactionPolicy beanTxEnv = (BeanTransactionPolicy) txPolicy;
         suspendedTransaction = beanTxEnv.suspendUserTransaction();
       } catch (SystemException e) {
         handleSystemException(txPolicy, e, callContext);
       } finally {
         instance.setBeanTransaction(suspendedTransaction);
       }
     }
   } finally {
     if (instance != null) {
       instance.setInUse(false);
     }
     EjbTransactionUtil.afterInvoke(txPolicy, callContext);
   }
 }
  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);
    }
  }