protected void processTxAttr(
      final EJBComponentDescription ejbComponentDescription,
      final MethodIntf methodIntf,
      final Method method) {
    if (this.getTransactionManagementType().equals(TransactionManagementType.BEAN)) {
      // it's a BMT bean
      return;
    }

    MethodIntf defaultMethodIntf =
        (ejbComponentDescription instanceof MessageDrivenComponentDescription)
            ? MethodIntf.MESSAGE_ENDPOINT
            : MethodIntf.BEAN;
    TransactionAttributeType txAttr =
        ejbComponentDescription
            .getTransactionAttributes()
            .getAttribute(methodIntf, method, defaultMethodIntf);
    if (txAttr != null) {
      txAttrs.put(
          new MethodTransactionAttributeKey(
              methodIntf, MethodIdentifier.getIdentifierForMethod(method)),
          txAttr);
    }
    Integer txTimeout =
        ejbComponentDescription
            .getTransactionTimeouts()
            .getAttribute(methodIntf, method, defaultMethodIntf);
    if (txTimeout != null) {
      txTimeouts.put(
          new MethodTransactionAttributeKey(
              methodIntf, MethodIdentifier.getIdentifierForMethod(method)),
          txTimeout);
    }
  }
  /**
   * Construct a new instance.
   *
   * @param componentConfiguration the component configuration
   */
  public EJBComponentCreateService(
      final ComponentConfiguration componentConfiguration,
      final EjbJarConfiguration ejbJarConfiguration) {
    super(componentConfiguration);

    this.componentConfiguration = componentConfiguration;

    this.ejbJarConfiguration = ejbJarConfiguration;

    EJBComponentDescription ejbComponentDescription =
        (EJBComponentDescription) componentConfiguration.getComponentDescription();
    this.transactionManagementType = ejbComponentDescription.getTransactionManagementType();

    // CMTTx
    if (transactionManagementType.equals(TransactionManagementType.CONTAINER)) {
      // slurp some memory
      this.txAttrs =
          new ConcurrentHashMap<
              MethodIntf,
              ConcurrentMap<String, ConcurrentMap<ArrayKey, TransactionAttributeType>>>();
    } else {
      this.txAttrs = null;
    }
    List<ViewConfiguration> views = componentConfiguration.getViews();
    if (views != null) {
      for (ViewConfiguration view : views) {
        final MethodIntf viewType =
            ejbComponentDescription.getMethodIntf(view.getViewClass().getName());
        for (Method method : view.getProxyFactory().getCachedMethods()) {
          this.processTxAttr(ejbComponentDescription, viewType, method);
        }
      }
    }
    // FIXME: TODO: a temporary measure until EJBTHREE-2120 is fully resolved, let's create tx
    // attribute map
    // for the component methods. Once the issue is resolved, we should get rid of this block and
    // just rely on setting
    // up the tx attributes only for the views exposed by this component
    Set<Method> componentMethods = componentConfiguration.getDefinedComponentMethods();
    if (componentMethods != null) {
      for (Method method : componentMethods) {
        this.processTxAttr(ejbComponentDescription, MethodIntf.BEAN, method);
      }
    }
    final HashMap<String, ServiceName> viewServices = new HashMap<String, ServiceName>();
    for (ViewDescription view : componentConfiguration.getComponentDescription().getViews()) {
      viewServices.put(view.getViewClassName(), view.getServiceName());
    }
    this.viewServices = viewServices;
  }
 @Override
 protected boolean requiresInterceptors(
     final Method method, final ComponentConfiguration componentConfiguration) {
   if (super.requiresInterceptors(method, componentConfiguration)) {
     return true;
   }
   final EJBComponentDescription ejbComponentDescription =
       (EJBComponentDescription) componentConfiguration.getComponentDescription();
   if ((ejbComponentDescription.getTimeoutMethod() != null
           && ejbComponentDescription.getTimeoutMethod().equals(method))
       || ejbComponentDescription.getScheduleMethods().containsKey(method)) {
     return true;
   }
   return false;
 }
  private void processTxAttr(
      final EJBComponentDescription ejbComponentDescription,
      final MethodIntf methodIntf,
      final Method method) {
    if (this.getTransactionManagementType().equals(TransactionManagementType.BEAN)) {
      // it's a BMT bean
      return;
    }

    String methodName = method.getName();
    TransactionAttributeType txAttr =
        ejbComponentDescription.getTransactionAttribute(
            methodIntf, methodName, toString(method.getParameterTypes()));

    ConcurrentMap<String, ConcurrentMap<ArrayKey, TransactionAttributeType>> perMethodIntf =
        this.txAttrs.get(methodIntf);
    if (perMethodIntf == null) {
      perMethodIntf =
          new ConcurrentHashMap<String, ConcurrentMap<ArrayKey, TransactionAttributeType>>();
      this.txAttrs.put(methodIntf, perMethodIntf);
    }
    ConcurrentMap<ArrayKey, TransactionAttributeType> perMethod = perMethodIntf.get(methodName);
    if (perMethod == null) {
      perMethod = new ConcurrentHashMap<ArrayKey, TransactionAttributeType>();
      perMethodIntf.put(methodName, perMethod);
    }
    perMethod.put(new ArrayKey((Object[]) method.getParameterTypes()), txAttr);
  }
  protected void processTxAttr(
      final EJBComponentDescription ejbComponentDescription,
      final MethodIntf methodIntf,
      final Method method) {
    if (this.getTransactionManagementType().equals(TransactionManagementType.BEAN)) {
      // it's a BMT bean
      return;
    }

    TransactionAttributeType txAttr =
        ejbComponentDescription.getTransactionAttributes().getAttribute(methodIntf, method);
    txAttrs.put(
        new MethodTransactionAttributeKey(
            methodIntf, MethodIdentifier.getIdentifierForMethod(method)),
        txAttr);
    Integer txTimeout =
        ejbComponentDescription.getTransactionTimeouts().getAttribute(methodIntf, method);
    if (txTimeout != null) {
      txTimeouts.put(
          new MethodTransactionAttributeKey(
              methodIntf, MethodIdentifier.getIdentifierForMethod(method)),
          txTimeout);
    }
  }
  /**
   * Construct a new instance.
   *
   * @param componentConfiguration the component configuration
   */
  public EJBComponentCreateService(
      final ComponentConfiguration componentConfiguration,
      final ApplicationExceptions applicationExceptions) {
    super(componentConfiguration);

    this.applicationExceptions = applicationExceptions;
    final EJBComponentDescription ejbComponentDescription =
        (EJBComponentDescription) componentConfiguration.getComponentDescription();
    this.transactionManagementType = ejbComponentDescription.getTransactionManagementType();

    this.timerService = ejbComponentDescription.getTimerService();
    this.policyContextID = ejbComponentDescription.getPolicyContextID();

    // CMTTx
    if (transactionManagementType.equals(TransactionManagementType.CONTAINER)) {
      this.txAttrs = new HashMap<MethodTransactionAttributeKey, TransactionAttributeType>();
      this.txTimeouts = new HashMap<MethodTransactionAttributeKey, Integer>();
    } else {
      this.txAttrs = null;
      this.txTimeouts = null;
    }
    // Setup the security metadata for the bean
    this.securityMetaData = new EJBSecurityMetaData(componentConfiguration);

    if (ejbComponentDescription.isTimerServiceRequired()) {
      Map<Method, InterceptorFactory> timeoutInterceptors =
          new IdentityHashMap<Method, InterceptorFactory>();
      for (Method method : componentConfiguration.getDefinedComponentMethods()) {
        if ((ejbComponentDescription.getTimeoutMethod() != null
                && ejbComponentDescription.getTimeoutMethod().equals(method))
            || ejbComponentDescription.getScheduleMethods().containsKey(method)) {
          final InterceptorFactory interceptorFactory =
              Interceptors.getChainedInterceptorFactory(
                  componentConfiguration.getAroundTimeoutInterceptors(method));
          timeoutInterceptors.put(method, interceptorFactory);
        }
      }
      this.timeoutInterceptors = timeoutInterceptors;
    } else {
      timeoutInterceptors = Collections.emptyMap();
    }

    List<ViewConfiguration> views = componentConfiguration.getViews();
    if (views != null) {
      for (ViewConfiguration view : views) {
        // TODO: Move this into a configurator
        final EJBViewConfiguration ejbView = (EJBViewConfiguration) view;
        final MethodIntf viewType = ejbView.getMethodIntf();
        for (Method method : view.getProxyFactory().getCachedMethods()) {
          // TODO: proxy factory exposes non-public methods, is this a bug in the no-interface view?
          if (!Modifier.isPublic(method.getModifiers())) continue;
          final Method componentMethod =
              getComponentMethod(
                  componentConfiguration, method.getName(), method.getParameterTypes());
          if (componentMethod != null) {
            this.processTxAttr(ejbComponentDescription, viewType, componentMethod);
          } else {
            this.processTxAttr(ejbComponentDescription, viewType, method);
          }
        }
      }
    }

    this.timeoutMethod = ejbComponentDescription.getTimeoutMethod();

    // FIXME: TODO: a temporary measure until EJBTHREE-2120 is fully resolved, let's create tx
    // attribute map
    // for the component methods. Once the issue is resolved, we should get rid of this block and
    // just rely on setting
    // up the tx attributes only for the views exposed by this component
    // AS7-899: We only want to process public methods of the proper sub-class.
    // (getDefinedComponentMethods returns all in random order)
    // TODO: use ClassReflectionIndex (low prio, because we store the result without class name)
    // (which is a bug: AS7-905)
    Set<Method> lifeCycle = new HashSet<>(componentConfiguration.getLifecycleMethods());
    for (Method method : componentConfiguration.getComponentClass().getMethods()) {
      this.processTxAttr(ejbComponentDescription, MethodIntf.BEAN, method);
      lifeCycle.remove(method);
    }
    // now handle non-public lifecycle methods declared on the bean class itself
    // see WFLY-4127
    for (Method method : lifeCycle) {
      if (method.getDeclaringClass().equals(componentConfiguration.getComponentClass())) {
        this.processTxAttr(ejbComponentDescription, MethodIntf.BEAN, method);
      }
    }

    final HashMap<String, ServiceName> viewServices = new HashMap<String, ServiceName>();
    for (ViewDescription view : componentConfiguration.getComponentDescription().getViews()) {
      viewServices.put(view.getViewClassName(), view.getServiceName());
    }
    this.viewServices = viewServices;
    final EjbHomeViewDescription localHome = ejbComponentDescription.getEjbLocalHomeView();
    this.ejbLocalHome =
        localHome == null ? null : ejbComponentDescription.getEjbLocalHomeView().getServiceName();
    final EjbHomeViewDescription home = ejbComponentDescription.getEjbHomeView();
    this.ejbHome = home == null ? null : home.getServiceName();
    final EJBViewDescription ejbObject = ejbComponentDescription.getEjbRemoteView();
    this.ejbObject = ejbObject == null ? null : ejbObject.getServiceName();
    final EJBViewDescription ejbLocalObject = ejbComponentDescription.getEjbLocalView();
    this.ejbLocalObject = ejbLocalObject == null ? null : ejbLocalObject.getServiceName();
    this.applicationName = componentConfiguration.getApplicationName();
    this.earApplicationName =
        componentConfiguration
            .getComponentDescription()
            .getModuleDescription()
            .getEarApplicationName();
    this.moduleName = componentConfiguration.getModuleName();
    this.distinctName =
        componentConfiguration.getComponentDescription().getModuleDescription().getDistinctName();
    this.shutDownInterceptorFactory = ejbComponentDescription.getShutDownInterceptorFactory();
  }