docs: void processTimeoutMetaData(BeanMetaData bmd) //d738042
                      throws EJBConfigurationException, ContainerException {
          final boolean isTraceOn = TraceComponent.isAnyTracingEnabled();
  
          if (isTraceOn && tc.isEntryEnabled())
              Tr.entry(tc, "processTimeoutMetaData : " + bmd.j2eeName);
  
          // local variable ultimately set as value of bmd.ivTimeoutMethod //d738042
          Method timeoutMethod = null; //d738042
  
          // -----------------------------------------------------------------------
          // First - determine if the bean implements the TimedObject interface.
          // -----------------------------------------------------------------------
          if (BeanMetaData.svTimedObjectClass.isAssignableFrom(bmd.enterpriseBeanClass)) {
              if (isTraceOn && tc.isDebugEnabled())
                  Tr.debug(tc, "processTimeoutMetaData : implements TimedObject");
              bmd.isTimedObject = true;
          } else {
              // The default is 'false', but if a bean fails to start, and a 2nd
              // attempt is made to start the bean, then insure it is reset to the
              // default value before executing timer metadata processing.    d547849
              bmd.isTimedObject = false;
          }
  
          // -----------------------------------------------------------------------
          // Second - For Session beans, look for <timeout-method> in XML.
          // -----------------------------------------------------------------------
  
          String timeoutName = null; //F743-15870
          int timeoutMethodParmCount = -1; //Compiler requires us to initialize variable.
  
          if (bmd.wccm.enterpriseBean != null &&
              bmd.wccm.enterpriseBean instanceof Session) {
              NamedMethod toMethod = ((Session) bmd.wccm.enterpriseBean).getTimeoutMethod();
  
              if (isTraceOn && tc.isDebugEnabled())
                  Tr.debug(tc, "processTimeoutMetaData : timeout-method = " + toMethod);
  
              if (toMethod != null) {
                  timeoutName = toMethod.getMethodName();
                  timeoutMethodParmCount = verifyXMLTimerParmList(toMethod.getMethodParamList(), //F743-15870
                                                                  bmd,
                                                                  timeoutName,
                                                                  true);
  
                  // If the EJB implements the timed object interface, the timed object method must be named "ejbTimeout".
                  if (bmd.isTimedObject) {
                      if (!"ejbTimeout".equals(timeoutName)) {
                          Tr.error(tc, "TIMER_BEAN_MUST_IMPLEMENT_EJBTIMEOUT_CNTR0160E",
                                   new Object[] { bmd.enterpriseBeanName, bmd._moduleMetaData.ivName });
                          throw new EJBConfigurationException("The bean: " + bmd.enterpriseBeanName + " in module: " + bmd._moduleMetaData.ivName + " inherits from TimedObject " +
                                                              "but does not implement the required method: ejbTimeout");
                      }
  
                      timeoutName = null;
                  }
  
                  if (isTraceOn && tc.isDebugEnabled())
                      Tr.debug(tc, "processTimeoutMetaData : timeout-method = " +
                                   timeoutName);
              }
          }
  
          // -----------------------------------------------------------------------
          // Third - If <timeout-method> was specified then loop through the
          //         methods looking for the right one.... or if XML metadata is
          //         NOT complete, thn loop through the methods looking for
          //         all @Timeout annotations.
          // -----------------------------------------------------------------------
  
          if (timeoutName != null ||
              !bmd.metadataComplete) {
              Method annotationMethod = null;
              Method[] xmlMethods = new Method[2];
              Class<?> clazz = bmd.enterpriseBeanClass;
  
              Collection<MethodMap.MethodInfo> methodInfos = MethodMap.getAllDeclaredMethods(clazz); // d659779, d666251
  
              if (isTraceOn && tc.isDebugEnabled())
                  Tr.debug(tc, "processTimeoutMetaData : looking through methods of " +
                               clazz.getName() + " : " + methodInfos.size());
  
              for (MethodMap.MethodInfo methodInfo : methodInfos) {
                  Method method = methodInfo.getMethod();
  
                  if (method.getName().equals(timeoutName) &&
                      hasTimeoutCallbackParameters(methodInfo)) {
                      int numParms = methodInfo.getNumParameters();
                      // If the expected number of parameters is unspecified or 0,
                      // defer the selection between no-param and 1-param.
                      if (timeoutMethodParmCount <= 0) {
                          if (xmlMethods[numParms] == null) {
                              xmlMethods[numParms] = method;
                          }
                      } else if (numParms == 1) {
                          if (timeoutMethod == null) {
                              timeoutMethod = method; //d738042
                          }
                      }
                  }
  
                  if (!bmd.metadataComplete) {
                      Object annotation = method.getAnnotation(Timeout.class);
  
                      if (annotation != null) {
                          if (!hasTimeoutCallbackParameters(methodInfo)) {
                              Tr.error(tc, "TIMEOUT_METHOD_MISSING_REQUIRED_PARM_CNTR0158E",
                                       new Object[] { bmd.enterpriseBeanName, bmd._moduleMetaData.ivName, method.getName() });
                              throw new EJBConfigurationException("The bean: " + bmd.enterpriseBeanName + " in module: " + bmd._moduleMetaData.ivName + " has timeout method: " +
                                                                  method.getName() + " configured, but the required javax.ejb.Timer parameter is missing.");
                          }
  
                          if (bmd.isTimedObject &&
                              !("ejbTimeout".equals(method.getName()))) {
                              Tr.error(tc, "TIMER_BEAN_MUST_IMPLEMENT_EJBTIMEOUT_CNTR0160E",
                                       new Object[] { bmd.enterpriseBeanName, bmd._moduleMetaData.ivName });
                              throw new EJBConfigurationException("The bean: " + bmd.enterpriseBeanName + " in module: " + bmd._moduleMetaData.ivName + " inherits from TimedObject "
                                                                  +
                                                                  "but does not implement the required method: ejbTimeout");
                          }
  
                          if (annotationMethod == null) {
                              annotationMethod = method;
                          } else {
                              Tr.error(tc, "TIMEOUT_ANNOTATION_OVERSPECIFIED_CNTR0161E",
                                       new Object[] { bmd.enterpriseBeanName, bmd._moduleMetaData.ivName });
                              throw new EJBConfigurationException("The bean: " + bmd.enterpriseBeanName + " in module: " + bmd._moduleMetaData.ivName +
                                                                  " has specified the @Timeout annotation on more than one method");
                          }
                      }
                  }
              }
  
              // -----------------------------------------------------------------------
              // Fourth - If <timeout-method> was specified without <method-params>
              //          or with empty <method-params>, we need to pick the best
              //          matching method now.                                   d659928
              // -----------------------------------------------------------------------
  
              if (timeoutName != null) {
                  if (timeoutMethodParmCount == 0) {
                      // Per the spec, "<method-params/>" can refer to either no-param
                      // or 1-param, with preference for no-param.
                      timeoutMethod = xmlMethods[0] != null ? xmlMethods[0] : xmlMethods[1]; // d738042
                  } else if (timeoutMethodParmCount == -1) {
                      // The user did not specify <method-params/>.  Prefer to use the
                      // annotated method if possible.  For backwards compatibility,
                      // prefer to use the 1-param method rather than no-param.
                      if (annotationMethod != null &&
                          annotationMethod.getName().equals(timeoutName)) {
                          timeoutMethod = annotationMethod; // d738042
                      } else {
                          timeoutMethod = xmlMethods[1] != null ? xmlMethods[1] : xmlMethods[0]; //d738042
                      }
                  }
              }
  
              // --------------------------------------------------------------------
              // Finally - Perform validation of results of method loop.
              //           Most validation checking is not required when the EJB
              //           implements TimedObject, as java forces the signature.
              // --------------------------------------------------------------------
  
              if (timeoutName != null &&
                  timeoutMethod == null) {
                  // The configured timeout method was not found on the bean implementation.
                  Tr.error(tc, "CONFIGURED_TIMEOUT_METHOD_NOT_FOUND_CNTR0162E",
                           new Object[] { bmd.enterpriseBeanName, bmd._moduleMetaData.ivName, timeoutName });
                  throw new EJBConfigurationException("The bean: " + bmd.enterpriseBeanName + " in module: " + bmd._moduleMetaData.ivName +
                                                      " has configured timeout method: " + timeoutName + ", but this method was not found on the bean implementation.");
              }
  
              if (timeoutMethod != null && //d738042
                  annotationMethod != null &&
                  timeoutMethod != annotationMethod) {
                  // Timeout method configuration conflict:
                  // XML has one configured timeout method name, and an @Timeout annotation has a different timeout method name
                  Tr.error(tc, "CONFLICTING_TIMEOUT_METHOD_NAMES_CNTR0163E",
                           new Object[] { bmd.enterpriseBeanName, bmd._moduleMetaData.ivName, timeoutMethod.getName(), annotationMethod.getName() }); // d738042
                  throw new EJBConfigurationException("The bean: " + bmd.enterpriseBeanName + " in module: " + bmd._moduleMetaData.ivName + " has configured timeout method: "
                                                      + timeoutMethod.getName() + " in XML, and timeout method: " + annotationMethod.getName() + " via an @Timeout annotation."); // d738042
              }
  
              if (timeoutMethod == null) {
                  timeoutMethod = annotationMethod; //d738042
              }
  
              if (timeoutMethod != null) {
                  if (!hasEmptyThrowsClause(timeoutMethod)) {
                      Tr.error(tc, "TIMEOUT_METHOD_THROWS_APP_EXCEPTION_CNTR0164E",
                               new Object[] { bmd.enterpriseBeanName, bmd._moduleMetaData.ivName, timeoutMethod.getName() }); // d738042
                      throw new EJBConfigurationException("The bean: " + bmd.enterpriseBeanName + " in module: " + bmd._moduleMetaData.ivName + " has timeout method "
                                                          + timeoutMethod.getName() + " which must not throw application exceptions."); //d738042
                  }
  
                  Class<?> returnType = timeoutMethod.getReturnType(); //d738042
                  if (returnType != Void.TYPE) {
                      Tr.error(tc, "TIMEOUT_METHOD_MUST_RETURN_VOID_CNTR0165E",
                               new Object[] { bmd.enterpriseBeanName, bmd._moduleMetaData.ivName, timeoutMethod.getName() }); //d738042
                      throw new EJBConfigurationException("The bean: " + bmd.enterpriseBeanName + " in module: " + bmd._moduleMetaData.ivName + " has timeout method: "
                                                          + timeoutMethod.getName() + " which must return void."); //d738042
                  }
  
                  int modifiers = timeoutMethod.getModifiers(); //d738042
                  if (Modifier.isStatic(modifiers) ||
                      Modifier.isFinal(modifiers)) {
                      Tr.error(tc, "TIMEOUT_METHOD_STATIC_OR_FINAL_CNTR0166E",
                               new Object[] { bmd.enterpriseBeanName, bmd._moduleMetaData.ivName, timeoutMethod.getName() }); //d738042
                      throw new EJBConfigurationException("The bean: " + bmd.enterpriseBeanName + " in module: " + bmd._moduleMetaData.ivName + " has timeout method: "
                                                          + timeoutMethod.getName() + " which must not be declared as static or final."); //d738042
                  }
  
                  bmd.isTimedObject = true;
  
              }
          }
  
          bmd.ivTimeoutMethod = timeoutMethod; //d738042
  
          // -----------------------------------------------------------------------
          // If this EJB has been identified as implementing TimedObject or
          // a Timeout method, then the TimerService Scheduler needs to be
          // started and available for use, if not alread.
          // Note: Timer Service does not run in z adjunct.                  d259812
          //
          // For EJBDeployed modules, the EJB runtime already started the timer
          // service during module start if needed.  For JITDEployed modules, the
          // EJB runtime tentatively scanned the database to determine whether to
          // start the timer service during module start.  If it chose not to, then
          // we need to try to start it now so that we can fail the bean
          // initialization if the timer service is unavailable.
          // -----------------------------------------------------------------------
  
          if (bmd.isTimedObject &&
              !bmd._moduleMetaData.isEJBDeployed()) {
              bmd.container.getEJBRuntime().setupTimers(bmd); // F743-13022
          }
  
          if (isTraceOn && tc.isEntryEnabled())
              Tr.exit(tc, "processTimeoutMetaData : " + bmd.j2eeName +
                          " : isTimedObject = " + bmd.isTimedObject +
                          " : ivTimeoutMethod = " + bmd.ivTimeoutMethod);
      }