docs: @Override
      public final synchronized void remove() throws RemoteException, RemoveException {
          final boolean isTraceOn = TraceComponent.isAnyTracingEnabled();
          if (isTraceOn && tc.isEntryEnabled())
              Tr.entry(tc, "remove: " + this);
  
          //--------------------------------------------------------------------
          // It's debatable whether a session bean whose ejbRemove fails
          // should be kept around or whether the container should
          // unilaterally destroy it. For now, allow the remove to fail and
          // allow the client to "recover" from the failure, i.e. don't
          // destroy the session bean if it raises a checked exception
          // (any subclass of RemoteException).
          //--------------------------------------------------------------------
  
          canBeRemoved();
  
          setState(REMOVING); // d159152
  
          // d367572.1  start
          String lifeCycle = null; // d367572.4
          CallbackContextHelper contextHelper = null; // d399469
          try {
              BeanMetaData bmd = home.beanMetaData;
  
              if (ivExPcContext != null) // d515803
              {
                  container.getEJBRuntime().getEJBJPAContainer().onRemoveOrDiscard(ivExPcContext); // d416151.3 d416151.3.5
              }
  
              if (ivCallbackKind != CallbackKind.None) {
                  contextHelper = new CallbackContextHelper(this); // d630940
                  beginLifecycleCallback(LifecycleInterceptorWrapper.MID_PRE_DESTROY,
                                         contextHelper, CallbackContextHelper.Contexts.All);
  
                  // Invoke the PreDestroy callback if any needs to be called.
                  if (ivCallbackKind == CallbackKind.SessionBean) {
                      if (isTraceOn && // d527372
                          TEBeanLifeCycleInfo.isTraceEnabled()) // d367572.4
                      {
                          lifeCycle = "ejbRemove";
                          TEBeanLifeCycleInfo.traceEJBCallEntry(lifeCycle); // d161864
                      }
                      sessionBean.ejbRemove();
                  } else if (ivCallbackKind == CallbackKind.InvocationContext) {
                      // Invoke the PreDestroy interceptor methods.
                      InterceptorMetaData imd = home.beanMetaData.ivInterceptorMetaData;
                      InterceptorProxy[] proxies = imd.ivPreDestroyInterceptors;
                      if (proxies != null) {
                          if (isTraceOn && // d527372
                              TEBeanLifeCycleInfo.isTraceEnabled()) // d367572.4
                          {
                              lifeCycle = "PreDestroy";
                              TEBeanLifeCycleInfo.traceEJBCallEntry(lifeCycle);
                          }
                          InvocationContextImpl<?> inv = getInvocationContext();
                          inv.doLifeCycle(proxies, bmd._moduleMetaData); //d450431, F743-14982
                      }
                  }
              }
  
              // d383586 - mark removed and destroy since no exception occurred.
              // If there is an exception, the bean will be removed in destroy().
              // We count beanRemoved (if any) in destroy() too.
              if (pmiBean != null) {
                  pmiBean.beanRemoved();
              }
              removed = true;
              destroy();
          } catch (RemoteException ex) {
              FFDCFilter.processException(ex, CLASS_NAME + ".remove", "611", this);
              if (isTraceOn && tc.isEventEnabled()) // d144064
              {
                  Tr.event(tc, "remove caught exception", new Object[] { this, ex }); // d367572.4 // d402681
              }
  
              // d383586 - discard the instance.
              discard(); // d383586
  
              // It is wrong to convert RemoteException to RemoveException, but we
              // keep this for backwards compatibility. d591915
              throw new RemoveException(ex.getMessage());
          } catch (Throwable ex) // d367572.4
          {
              FFDCFilter.processException(ex, CLASS_NAME + ".remove", "611", this);
              if (isTraceOn && tc.isEventEnabled()) // d144064
              {
                  Tr.event(tc, "remove caught exception:", new Object[] { this, ex }); // d367572.4 // d402681
              }
  
              // d383586 - discard the instance.
              // d591915
              //
              // It looks like we are non spec-compliant here.  In all cases, we
              // bury the exception that we caught from the above try block.
              // However, the spec implies that there are many cases where we do
              // want to throw an exception here.
              //
              // In the above try block, we do a number of things, including the
              // SessionBean.ejbRemove() method on the user's underlying bean instance.
              // Presumably, this is a result of the user invoking the .ejbRemove()
              // method on the interface, and in this case it seems like we would
              // fall under the goverence of section 14.3.2 (tables 17 and 18) of the EJB 3.1 spec,
              // which indicates that in all cases where we get an exception, we
              // have to re-throw some type of exception (as opposed to what we
              // are doing here, which is to not throw any exception).
              //
              // Additionally, it appears that this .remove() method gets called into
              // when the transaction that the session bean is on is either committed
              // or rolled back, which presumably can happen as the result of user
              // invoked business method...and so the argument could be made that
              // this also falls under section 14.3.1 (tables 15 and 16) of the EJB 3.1 spec, which also
              // seems to indicate that in all cases where we get an exception, we
              // have to re-throw some type of exception.
              //
              // If we ever wanted to fix this, things are further complicated
              // because it seems like in some cases its the correct behavior to
              // not throw an exception here.  In the try block above we are also
              // executing the preDestroy interceptor methods, and so that seems to
              // fall under section 14.3.3 (table 19) of the EJB 3.1 spec, which
              // says that we should swallow the exception.
              //
              discard(); // d383586
          } finally {
              if (isTraceOn && // d527372
                  TEBeanLifeCycleInfo.isTraceEnabled()) {
                  if (lifeCycle != null) // d367572.4
                  {
                      TEBeanLifeCycleInfo.traceEJBCallExit(lifeCycle);
                  }
              }
  
              // Resume the TX context if it was suspended.
              if (contextHelper != null) // d399469
              {
                  contextHelper.complete(true);
              }
  
              if (isTraceOn && tc.isEntryEnabled())
                  Tr.exit(tc, "remove: " + this);
          } // d367572.1  end
  
      }