docs: @Override
      @FFDCIgnore(IOException.class)
      public void complete(VirtualConnection vc) {
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.entry(tc, "complete",  vc);
          }
          synchronized( this.in.getCompleteLockObj()){
              
              SRTServletRequestThreadData.getInstance().init(_requestDataAsyncReadCallbackThread);
              
              //Push the original thread's context onto the current thread, also save off the current thread's context
              this.threadContextManager.pushContextData();
  
              //Call into the user's ReadListener to indicate there is data available
              try{
                  if (!in.isFinished()) {
                      this.in.getReadListener().onDataAvailable();
                  }   
              } catch (Throwable onDataAvailableException){
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                      Tr.debug(tc, "Exception occurred during ReadListener.onDataAvailable : " + onDataAvailableException + ", " + this.in.getReadListener());
                  }
                  this.threadContextManager.popContextData();
                  error(vc, onDataAvailableException);
                  if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
                      Tr.exit(tc, "complete");
                  }
                  return;
              }
  
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                   Tr.debug(tc, "Message is fully read, calling ReadListener onAllDataRead : " + this.in.getReadListener());
              }
              
              if(this.in.getReadListener() != null){
                  // if all the data has been read we are done.
                  if (in.isFinished()) {
                      try{
                          this.in.getReadListener().onAllDataRead();
                      } catch (Throwable onAllDataReadException){
                          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                              Tr.debug(tc, "Exception occurred during ReadListener.onAllDataRead : " + onAllDataReadException + ", " + this.in.getReadListener());
                          }
                          this.threadContextManager.popContextData();
                          error(vc, onAllDataReadException);
                          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
                              Tr.exit(tc, "complete");
                          }
                          return;
                      }
                  } else if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                      Tr.debug(tc, "onDataAavailabe returned without reading all data. Read Listener will no be called again : "  + this.in.getReadListener());
                  }
                  else{
                      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                          Tr.debug(tc, "ReadListener is not set , stream must be closed, cannot call onAllDataRead()");
                      }
                  }
              }
              
              //Revert back to the thread's current context
              this.threadContextManager.popContextData();
  
          }
          
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.exit(tc, "complete");
          }
      }