code: protected Object callMethod(MethodHandle method, ParameterExtractor[] extractors, Session session,
                                  boolean callOnError, Object... params) {
          Object[] paramValues = new Object[extractors.length + 1];
  
          try {
              // TYRUS-325: Server do not close session properly if non-instantiable endpoint class is provided
              if (callOnError && getEndpoint() == null) {
                  try {
                      session.close(CloseReasons.UNEXPECTED_CONDITION.getCloseReason());
                  } catch (Exception e) {
                      logger.error(e.getMessage(), e);
                  }
                  return null;
              }
              paramValues[0] = getEndpoint();
              for (int i = 0; i < extractors.length; i++) {
                  paramValues[i + 1] = extractors[i].value(session, params);
              }
  
              return method.invokeWithArguments(paramValues);
          } catch (Throwable e) {
              if (callOnError) {
                  onError(session, (e instanceof InvocationTargetException ? e.getCause() : e));
              } else {
                  logger.error(Messages.get("web.socket.error.endpoint"), e);
              }
          }
  
          return null;
      }
docs: <p>callMethod.</p>
  
  @param method a {@link java.lang.invoke.MethodHandle} object.
  @param extractors an array of {@link ameba.websocket.internal.EndpointMeta.ParameterExtractor} objects.
  @param session a {@link javax.websocket.Session} object.
  @param callOnError a boolean.
  @param params a {@link java.lang.Object} object.
  @return a {@link java.lang.Object} object.