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