docs: @Override
      public void afterCompletion(int status)
      {
  
          boolean committed = true;
          boolean reLoad = false;
          final boolean isTraceOn = TraceComponent.isAnyTracingEnabled(); // d532639.2
  
          if (status != Status.STATUS_COMMITTED) {
              committed = false;
          }
  
          if (isTraceOn && TETxLifeCycleInfo.isTraceEnabled()) // PQ74774
          { // PQ74774
              String tid = getTxId();
              if (tid != null)
              {
                  if (globalTransaction)
                  {
                      TETxLifeCycleInfo.traceGlobalTxAfterCompletion(tid, "Global/User Tx AfterCompletion");
                  } else
                  {
                      TETxLifeCycleInfo.traceLocalTxAfterCompletion(tid, "Local Tx AfterCompletion");
                  }
              }
          } // PQ74774
  
          //d139562.11
          if (finderSyncList != null) // d173022.12
          { // d173022.12
              int numberofCallers = finderSyncList.size();
              for (int i = 0; i < numberofCallers; ++i) {
                  finderSyncList.get(i).afterCompletion(status);
              }
          } // d173022.12
  
          if (isTraceOn && tc.isEntryEnabled()) // d144064
              Tr.entry(tc, "afterCompletion"
                       , new Object[] { Boolean.valueOf(globalTransaction), this,
                                       Boolean.valueOf(committed),
                                       Boolean.valueOf(isActivitySessionCompleting) }
                              ); //123293
  
          // When an EJB method ends, we need to remove bean-specific contexts from
          // the thread.  Those contexts need to be present for beforeCompletion for
          // JPA @PreUpdate, so postInvoke cannot pop the contexts prior to
          // transaction completion, but the calls to Activator.commit/.rollbackBean
          // below might unpin the currently invoked bean from the current
          // transaction, which would allow the bean to be active concurrently on
          // another thread while other transaction callbacks are running on this
          // thread.  To avoid that, pop the contexts now if this transaction is
          // being completed because an EJB method is ending.              RTC107108
          if (ivPostInvokeContext != null)
          {
              ivContainer.postInvokePopCallbackContexts(ivPostInvokeContext);
              ivPostInvokeContext = null;
          }
  
          try {
  
              if (committed) {
  
                  // d126930.3
                  // By default activitSessionCompleting is set to true.  Even if there
                  // is no activitySession present.  This simply means we follow the noraml
                  // ContainerTx logic for ending a transaction.
  
                  if (isActivitySessionCompleting == true) {
  
                      becomeCommitted();
  
                      // Since we're committing, we can now allow timers queued to
                      // start to be started (not in this list if also cancelled).
                      if (timersQueuedToStart != null) {
                          for (TimerNpImpl timer : timersQueuedToStart.values()) {
                              timer.start();
                          }
                      }
  
                      // Any timers canceled in this global tran were added to
                      // timersCanceled in case they needed to be re-created in
                      // rollback.  Since we're not rolling back, go ahead and
                      // destroy these, then clear this map
                      if (timersCanceled != null) {
                          for (TimerNpImpl timer : timersCanceled.values()) {
                              timer.remove(true); // RTC107334
                          }
                      }
  
                      // d111555  Only perform if a beanO has been enlisted
                      if (ivBeanOsEnlistedInTx) {
                          //115597 changed to use afterList
                          int afterListSize = afterList.size(); // d122418-5
                          for (int i = 0; i < afterListSize; i++) // d122418-5
                          {
                              BeanO beanO = afterList.get(i); // d122418-5
                              try {
                                  beanO.commit(this);
                              } catch (Throwable ex) {
                                  FFDCFilter.processException(ex,
                                                              CLASS_NAME + ".afterCompletion",
                                                              "795", this);
                                  if (isTraceOn && tc.isEventEnabled()) // d144064
                                      Tr.event(tc, "Exception thrown in commit()",
                                               new Object[] { beanO, ex });
                              } finally {
                                  // Perform the Activation Strategy afterCompletion -
                                  // commit processing. Ignore any exception that may
                                  // occur, as the transaction has already committed
                                  // and insure the rest of the beans in the list
                                  // get processed to minimize side effects of any
                                  // failure here.                                 d145697
                                  try {
                                      ivContainer.activator.commitBean(this, beanO);
                                  } catch (Throwable ex) {
                                      FFDCFilter.processException(ex,
                                                                  CLASS_NAME +
                                                                                  ".afterCompletion",
                                                                  "811", this);
                                      if (isTraceOn && tc.isEventEnabled())
                                          Tr.event(tc, "Exception thrown in commitBean()",
                                                   new Object[] { beanO, ex });
                                  }
                              }
                          } // end for
                      } // if ivBeanOsEnlistedInTx               // d111555
  
                      // d126930.3
                      // --------------------------------------------------------------
                      // Special case added for mid-activitySession checkpoint.  Entity
                      // beans enlisted in local transactions must be stored during
                      // the checkpoint.  This occured at beforeCompletion time.  Here
                      // we just do nothing, to make sure the bean's state does not
                      // not change.
                      // --------------------------------------------------------------
  
                  } else { //checkpoint/reset processing
  
                      reLoad = true;
  
                  } // end else (special case for mid-ActivitySession checkpoint)
  
              } else { // JTS Status is Rollback
  
                  // d126930.3
                  // By default activitSessionCompleting is set to true.  Even if there
                  // is no activitySession present.  This simply means we follow the normal
                  // ContainerTx logic for ending a transaction.
  
                  if (isActivitySessionCompleting == true) {
  
                      becomeRolledback();
  
                      // re-start any timers that had been cancelled in this global tran
                      if (timersCanceled != null) {
                          for (TimerNpImpl timer : timersCanceled.values()) {
                              timer.start();
                              if (isTraceOn && tc.isDebugEnabled()) {
                                  Tr.debug(tc, "rollback re-started queued-as-canceled timer: " + timer);
                              }
                          }
                      }
  
                      // Do not start timers queued to start.  Rather, mark them
                      // destroyed and clear the queue.
                      if (timersQueuedToStart != null) {
                          for (TimerNpImpl timer : timersQueuedToStart.values()) {
                              timer.remove(true); // RTC107334
                              if (isTraceOn && tc.isDebugEnabled()) {
                                  Tr.debug(tc, "rollback destroyed queued-to-start timer: " + timer);
                              }
                          }
                      }
  
                      // d111555 only preform if one or more beans in tx
                      if (ivBeanOsEnlistedInTx) { // d111555
                          int afterListSize = afterList.size(); // d122418-5
                          //d115597 changed to use afterList
                          for (int i = 0; i < afterListSize; i++) // d122418-5
                          {
                              BeanO beanO = afterList.get(i); // d122418-5
                              try {
                                  beanO.rollback(this);
                              } catch (Throwable ex) {
                                  FFDCFilter.processException(ex,
                                                              CLASS_NAME + ".afterCompletion",
                                                              "863", this);
                                  if (isTraceOn && tc.isEventEnabled()) // d144064
                                      Tr.event(tc, "Exception thrown in rollback()",
                                               new Object[] { beanO, ex });
                              } finally {
                                  // Perform the Activation Strategy afterCompletion -
                                  // commit processing. Ignore any exception that may
                                  // occur, as the transaction has already committed
                                  // and insure the rest of the beans in the list
                                  // get processed to minimize side effects of any
                                  // failure here.                                 d145697
                                  try {
                                      ivContainer.activator.rollbackBean(this, beanO);
                                  } catch (Throwable ex) {
                                      FFDCFilter.processException(ex,
                                                                  CLASS_NAME +
                                                                                  ".afterCompletion",
                                                                  "879", this);
                                      if (isTraceOn && tc.isEventEnabled())
                                          Tr.event(tc, "Exception thrown in rollbackBean()",
                                                   new Object[] { beanO, ex });
                                  }
                              }
                          } // while
                      } // if ivBeanOsEnlistedInTx              // d111555
  
                      // d126930.3
                      // -------------------------------------------------------------
                      // Special case added for mid-activitySession reset.  Entity
                      // beans enlisted in local transactions must be reloaded
                      // from the backing store to erase any in-memory updates that
                      // were done up to this point (ie. reset them).  For other bean
                      // types, we do nothing on mid-activitySession reset. The local
                      // transaction service will make a setCompleting = false call on
                      // the containerSynchronization interface, followed by an
                      // afterCompletion call.  These calls are not preceeded a
                      // a beforeCompletion call.  The beans' state should not be
                      // changed.  We just reload them.
                      // -------------------------------------------------------------
  
                  } else {
                      reLoad = true;
                  }
  
              } // end else (rollback)
  
          } catch (Throwable t) {
  
              FFDCFilter.processException(t, CLASS_NAME + ".afterCompletion",
                                          "913", this);
              if (isTraceOn && tc.isEventEnabled()) // d144064
                  Tr.event(tc, "Exception during afterCompletion", t);
              throw new RuntimeException(t.toString());
  
          } finally { //110762.1
  
              // Persistence Manager wants notified
  
              try {
                  if (txListener != null)
                      try {
                          txListener.afterCompletion(status); // d160445
                          txListener = null;
                      } catch (Throwable e) {
                          FFDCFilter.processException(e, CLASS_NAME + ".afterCompletion",
                                                      "929", this);
                          throw new Exception("txListener exception" + e.toString());
                      }
              } catch (Throwable e) {
                  FFDCFilter.processException(e, CLASS_NAME + ".afterCompletion",
                                              "934", this);
              }
  
              if (!reLoad)
                  ivContainer.containerTxCompleted(this); //d153430 added reLoad flag
          } // end finally
  
          // Activity session checkpoint.
  
          if (reLoad && afterList != null && !afterList.isEmpty()) { // d630940
              // Reset flag so beans will return to normal ContainerTx logic
              // unless another activitySession checkpoint or reset call is made.
  
              // Save the BeanOs processed in the following loop in an instance variable
              // so methods called from the customer callbacks can determine which beanO
              // is active on the thread. Access the BeanO in the loop in a local
              // variable for performance.                                       d168509
              EJBThreadData threadData = EJSContainer.getThreadData(); // d630940
              boolean popCallbackBeanO = false;
              ComponentMetaData prevCMD = null;
              boolean resetCMD = false;
              ClassLoader prevClassLoader = null;
              Object origClassLoader = ThreadContextAccessor.UNCHANGED;
  
              try
              {
                  int afterListSize = afterList.size();
                  for (int i = 0; i < afterListSize; i++)
                  {
                      BeanO beanO = afterList.get(i);
                      try
                      {
                          BeanMetaData bmd = beanO.home.beanMetaData;
  
                          if (bmd.type == InternalConstants.TYPE_CONTAINER_MANAGED_ENTITY ||
                              bmd.type == InternalConstants.TYPE_BEAN_MANAGED_ENTITY)
                          {
                              attachListener();
                              if (txListener != null) {
                                  txListener.afterBegin();
                              } else {
                                  throw new Exception("Error: Null Transaction Listener");
                              }
  
                              // If the Entity bean has exclusive access to the data
                              // (OptA) or the LoadPolicy has defined a reload interval
                              // (ReadOnly), then there is no need to re-load the
                              // bean.  Otherwise, the Entity bean must be reloaded
                              // to acquire the proper DB locks. The forUpdate = false
                              // parameter has no effect because these are EJB 2.0
                              // beans.  Both BMP and CMP entities must use the
                              // access intent information from the application
                              // profile to determine the locking requirements.
                              // Also, we make sure the correct ComponentMetaData
                              // and local transaction context is on the thread before
                              // loading the bean.
                              if (bmd.optionACommitOption ||
                                  bmd.ivCacheReloadType != BeanMetaData.CACHE_RELOAD_NONE)
                              {
                                  // Bean is not re-loaded, but PM needs to be informed
                                  // the bean is enlisted with the tran.               LI3408
                                  ((EntityBeanO) beanO).enlistForOptionA(this);
                              }
                              else
                              {
                                  threadData.pushCallbackBeanO(beanO); // d168509, d630940
                                  popCallbackBeanO = true;
  
                                  // Update the thread CMD if it's not the same as the
                                  // previous bean and this is a bean-managed bean.
                                  if (bmd != prevCMD &&
                                      bmd.type == InternalConstants.TYPE_BEAN_MANAGED_ENTITY)
                                  {
                                      if (resetCMD)
                                      {
                                          cmdAccessor.endContext();
                                      }
  
                                      cmdAccessor.beginContext(bmd);
                                      prevCMD = bmd;
                                      resetCMD = true;
  
                                      // Update the class loader if it's not the same as the
                                      // previous bean.                         PK51366, PK83186
                                      ClassLoader classLoader = bmd.ivContextClassLoader; // F85059
                                      if (classLoader != prevClassLoader)
                                      {
                                          prevClassLoader = classLoader;
                                          origClassLoader = EJBThreadData.svThreadContextAccessor.repushContextClassLoaderForUnprivileged(origClassLoader, classLoader);
                                      }
                                  }
  
                                  Object cmdCtxSet = null;
                                  TxContextChange changedContext = null;
                                  try {
                                      cmdCtxSet = cmdAccessor.beginContext(bmd);
                                      changedContext = uowCtrl.setupLocalTxContext(beanO.getId());
                                      ((EntityBeanO) beanO).load(this, false);
                                  } finally {
                                      uowCtrl.teardownLocalTxContext(changedContext);
                                      if (cmdCtxSet != null) {
                                          cmdAccessor.endContext();
                                      }
                                  }
  
                                  popCallbackBeanO = false;
                                  threadData.popCallbackBeanO();
                              }
                          }
  
                      } catch (Throwable ex) {
                          FFDCFilter.processException(ex,
                                                      CLASS_NAME + ".afterCompletion",
                                                      "978", this);
                          if (isTraceOn && tc.isEventEnabled()) // d144064
                              Tr.event(tc, "Exception thrown attempting to reload bean " +
                                           "due to activitySession reset",
                                       new Object[] { beanO, ex });
  
                          //d135218 - added destroy, setRollbackOnly, logException, &
                          //          throw exception below to match beforeCompletion
                          //          logic since ActiviySession reset occurs during
                          //          the middle of a local transaction, not at the
                          //          end, like afterCompletion usually handles.
  
                          // Destroy the beanO, too late to delist. Destroying it should
                          // take care of the state when the transaction is rolled back
                          beanO.destroy();
  
                          ivContainer.uowCtrl.setRollbackOnly();
  
                          // Log the exception
                          ExceptionUtil.logException(tc, ex, null, beanO);
  
                          // Inform the activitySession service that reset
                          // failed.
                          throw new RuntimeException(ex.toString());
  
                      }
                  } // end for loop
              } finally
              {
                  EJBThreadData.svThreadContextAccessor.popContextClassLoaderForUnprivileged(origClassLoader);
  
                  if (resetCMD)
                  {
                      cmdAccessor.endContext();
                  }
  
                  if (popCallbackBeanO)
                  {
                      threadData.popCallbackBeanO();
                  }
              }
  
          } // end else (special case for mid-ActivitySession reset)
  
          if (isTraceOn && tc.isEntryEnabled())
              Tr.exit(tc, "afterCompletion"); // d144064
  
      }