docs: @Override
      public void setReadListener(ReadListener arg0) {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              Tr.entry(tc, "setReadListener", this.listener);
  
          //Throw a NullPointerException if the ReadListener passed in was null
          if(arg0 == null){
              if (TraceComponent.isAnyTracingEnabled() && tc.isErrorEnabled())
                  Tr.error(tc, "readlistener.is.null");
              throw new NullPointerException(Tr.formatMessage(tc, "readlistener.is.null"));
          }
          //Throw an IllegalStateException if async has not been started
          if(!this.request.isAsyncStarted()){
              if (TraceComponent.isAnyTracingEnabled() && tc.isErrorEnabled())
                  Tr.error(tc, "readlistener.async.not.started");
              throw new IllegalStateException(Tr.formatMessage(tc, "readlistener.async.not.started"));
          }
          //Throw an IllegalStateException is there was already a ReadListener set for this InputStream
          if(this.listener != null){
              if (TraceComponent.isAnyTracingEnabled() && tc.isErrorEnabled())
                  Tr.error(tc, "readlistener.already.started");
              throw new IllegalStateException(Tr.formatMessage(tc, "readlistener.already.started"));
          }
          
          this.listener = arg0;
          
          //Create a new ThreadContextManager to pass into the read Callback
          ThreadContextManager tcm = new ThreadContextManager();
          
          // If ISC is null the inbound request would have resulted in a login being needed so
          // post data has already been read and re-populated by the security component.In 
          // this case create a callback which works for the already read data.
          if (getISC()==null) {
              this.callback = new AsyncAlreadyReadCallback(this, tcm);
          } else {
              //Create a new HttpServletCallback so we can use it for our async read callbacks
              this.callback = new AsyncReadCallback(this, tcm);
          }    
          
          AsyncContext31Impl ac = (AsyncContext31Impl)request.getAsyncContext();
  
          try {
              ac.startReadListener(tcm, this);
          } catch (Exception e) {
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                  Tr.debug(tc, "An exception occurred while setting the ReadListener : " + e);
              }
              //There was a problem with the read so we should invoke their onError, since technically it's been set now
              this.listener.onError(e);
          }
          
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              Tr.exit(tc, "setReadListener", this.listener);
      }