docs: @FFDCIgnore(IOException.class)
      public boolean processWithWholeMessageHandler(DATA_TYPE dt) throws CharacterCodingException {
          if ((appTextMessageHandler != null) && (dt == DATA_TYPE.TEXT)) {
  
              Class<?> clazz = appTextMessageHandlerClass;
  
              if (clazz.equals(String.class)) {
                  String message = convertMessageToString();
  
                  // call the application's MessageHandler.onMessage(<String> x) method
                  connLink.setReadLinkStatus(READ_LINK_STATUS.ON_READ_THREAD);
                  ((MessageHandler.Whole<String>) appTextMessageHandler).onMessage(message);
                  return true;
              }
  
              else if (clazz.equals(Reader.class)) {
                  Reader message = convertMessageToReader();
  
                  // call the application's MessageHandler.onMessage(<Reader> x) method
                  connLink.setReadLinkStatus(READ_LINK_STATUS.ON_READ_THREAD);
                  ((MessageHandler.Whole<Reader>) appTextMessageHandler).onMessage(message);
                  return true;
              }
          }
  
          if ((appBinaryMessageHandler != null) && (dt == DATA_TYPE.BINARY)) {
              Class<?> clazz = appBinaryMessageHandlerClass;
  
              if (clazz.equals(ByteBuffer.class)) {
                  ByteBuffer message = convertMessageToByteBuffer();
  
                  // call the application's MessageHandler.onMessage(<ByteBuffer> x) method
                  connLink.setReadLinkStatus(READ_LINK_STATUS.ON_READ_THREAD);
                  ((MessageHandler.Whole<ByteBuffer>) appBinaryMessageHandler).onMessage(message);
                  return true;
              }
  
              else if (clazz.equals(byte[].class)) {
                  byte[] message = convertPayloadToByteArray();
  
                  // call the application's MessageHandler.onMessage(<byte[]> x) method
                  connLink.setReadLinkStatus(READ_LINK_STATUS.ON_READ_THREAD);
                  ((MessageHandler.Whole<byte[]>) appBinaryMessageHandler).onMessage(message);
                  return true;
              }
  
              else if (clazz.equals(InputStream.class)) {
                  InputStream message = convertMessageToInputStream();
  
                  // call the application's MessageHandler.onMessage(<InputStream> x) method
                  connLink.setReadLinkStatus(READ_LINK_STATUS.ON_READ_THREAD);
                  ((MessageHandler.Whole<InputStream>) appBinaryMessageHandler).onMessage(message);
                  return true;
              }
          }
          if ((appPongMessageHandler != null) && (dt == DATA_TYPE.PONG)) {
              Class<?> clazz = appPongMessageHandlerClass;
              if (clazz.equals(PongMessage.class)) {
                  ByteBuffer message = convertMessageToByteBuffer(true);
                  PongMessage msg = new PongMessageImpl(message);
  
                  // call the application's MessageHandler.onMessage(<Reader> x) method
                  connLink.setReadLinkStatus(READ_LINK_STATUS.ON_READ_THREAD);
                  ((MessageHandler.Whole<PongMessage>) appPongMessageHandler).onMessage(msg);
                  return true;
              }
          }
  
          // if the generic type for this MessageHandler.Whole equals one of the configured decoder generic types, then use that decoder
          // clazz: is the generic class that the MessageHandler.Whole specifies
          // then go through the decoders that also have been specified with this same (or assignable) generic class.
          // in other words, let me see if I have any decoders<X> to use with this  MessageHandler<X>.
          if ((appTextMessageHandler != null) && (dt == DATA_TYPE.TEXT)) {
  
              Class<?> clazz = appTextMessageHandlerClass;
              ArrayList<Decoder> dcList = findDecoderFromAppDecoderType(clazz, dt);
  
              if (dcList != null && dcList.size() > 0) {
                  Decoder firstDecoder = dcList.get(0);
                  if (firstDecoder instanceof Decoder.Text) {
                      String message = convertMessageToString();
                      //user might have declared multiple decoders of same type for this endpoint. In this case, check
                      //decoder list and find the first decoder in the list which has implemented willDecode(..) to return
                      //'true'
                      Decoder dc = findWillDecodeDecoder(dcList, message);
                      if (dc != null) {
                          try {
                              dc.init(endpointConfig);
                              Object appObj = ((Decoder.Text) dc).decode(message);
                              connLink.setReadLinkStatus(READ_LINK_STATUS.ON_READ_THREAD);
                              ((MessageHandler.Whole) appTextMessageHandler).onMessage(appObj);
                              return true;
                          } catch (DecodeException e) {
                              connLink.callOnError(e, true);
                              return true;
                          }
                      }
                  } else if (firstDecoder instanceof Decoder.TextStream) {
                      Reader message = convertMessageToReader();
                      try {
                          //WebSocket API does not support willDecode() method for Decoder.BinaryStream type. Hence, even if
                          //user has declared multiple same type of decoder, just pick the first one in the list and use it.
  
                          firstDecoder.init(endpointConfig);
                          Object appObj = ((Decoder.TextStream) firstDecoder).decode(message);
                          connLink.setReadLinkStatus(READ_LINK_STATUS.ON_READ_THREAD);
                          ((MessageHandler.Whole) appTextMessageHandler).onMessage(appObj);
                          return true;
                      } catch (DecodeException e) {
                          connLink.callOnError(e, true);
                          return true;
                      } catch (IOException e) {
                          if (tc.isDebugEnabled()) {
                              Tr.debug(tc, "IOException calling onMessage on class " + clazz.getName() + " while decoding Decoder.TextStream type "
                                           + ((Decoder.TextStream) firstDecoder).toString()
                                           + "Exception is: " + e.getMessage());
                          }
                          //Since IOexception has occurred, there is no point in attempting to read message TextStream to convert into
                          //message string to pass as first param to form DecodeException. Hence passing just a error message
                          //"IOException decoding BinaryStream" as first parameter here
                          String msg = Tr.formatMessage(tc,
                                                        "decoder.ioexception",
                                                        appTextMessageHandler.getClass().getName(), firstDecoder.getClass().getName());
  
                          DecodeException de = new DecodeException(msg, e.getMessage(), e);
                          connLink.callOnError(de, true);
                          return true;
                      }
                  }
              }
          }
  
          if ((appBinaryMessageHandler != null) && (dt == DATA_TYPE.BINARY)) {
              Class<?> clazz = appBinaryMessageHandlerClass;
              ArrayList<Decoder> dcList = findDecoderFromAppDecoderType(clazz, dt);
  
              if (dcList != null && dcList.size() > 0) {
                  Decoder firstDecoder = dcList.get(0);
                  if (firstDecoder instanceof Decoder.Binary) {
                      // Decode the given bytes into an object of type T
                      ByteBuffer message = convertMessageToByteBuffer();
                      //user might have declared multiple decoders of same type for this endpoint. In this case, check
                      //decoder list and find the first decoder in the list which has implemented willDecode(..) to return
                      //'true'
                      Decoder dc = findWillDecodeDecoder(dcList, message);
                      if (dc != null) {
                          try {
                              dc.init(endpointConfig);
                              Object appObj = ((Decoder.Binary) dc).decode(message);
                              connLink.setReadLinkStatus(READ_LINK_STATUS.ON_READ_THREAD);
                              ((MessageHandler.Whole) appBinaryMessageHandler).onMessage(appObj);
                              return true;
                          } catch (DecodeException e) {
                              connLink.callOnError(e, true);
                              return true;
                          }
                      } else {
                          if (tc.isDebugEnabled()) {
                              Tr.debug(tc, "willDecode returned false");
                          }
                          return true;
                      }
                  } else if (firstDecoder instanceof Decoder.BinaryStream) {
                      InputStream message = convertMessageToInputStream();
                      try {
                          //WebSocket API does not support willDecode() method for Decoder.BinaryStream type. Hence, even if
                          //user has declared multiple same type of decoder, just pick the first one in the list and use it.
                          firstDecoder.init(endpointConfig);
                          Object appObj = ((Decoder.BinaryStream) firstDecoder).decode(message);
                          connLink.setReadLinkStatus(READ_LINK_STATUS.ON_READ_THREAD);
                          ((MessageHandler.Whole) appBinaryMessageHandler).onMessage(appObj);
                          return true;
                      } catch (DecodeException e) {
                          connLink.callOnError(e, true);
                          return true;
                      } catch (IOException e) {
                          // do NOT allow instrumented FFDC to be used here
                          if (tc.isDebugEnabled()) {
                              Tr.debug(tc, "IOException calling onMessage on class " + clazz.getName() + " while decoding Decoder.BinaryStream type "
                                           + ((Decoder.BinaryStream) firstDecoder).toString()
                                           + "Exception is: " + e.getMessage());
                          }
                          //Since IOexception has occurred, there is no point in attempting to read message BinaryStream to convert into
                          //message string to pass as first param to form DecodeException. Hence passing just a error message
                          //"IOException decoding BinaryStream" as first parameter here
                          String msg = Tr.formatMessage(tc,
                                                        "decoder.ioexception",
                                                        appBinaryMessageHandler.getClass().getName(), ((Decoder.BinaryStream) firstDecoder).getClass().getName());
                          DecodeException de = new DecodeException(msg, e.getMessage(), e);
                          connLink.callOnError(de, true);
                          return true;
                      }
                  }
              }
          }
          return false;
      }