private void validateResponse(HTTPResponse response) {
   HTTPStatus status = response.status();
   if (status.code >= HTTPStatus.OK.code && status.code <= 300) return;
   try {
     if (status == HTTPStatus.BAD_REQUEST) {
       ValidationErrorResponse validationErrorResponse =
           JSON.fromJSON(ValidationErrorResponse.class, response.text());
       throw new RemoteServiceException(
           "failed to validate, message="
               + validationErrorResponse.message
               + ", fieldErrors="
               + validationErrorResponse.fieldErrors);
     } else {
       ErrorResponse errorResponse = JSON.fromJSON(ErrorResponse.class, response.text());
       throw new RemoteServiceException(errorResponse.message);
     }
   } catch (RemoteServiceException e) {
     throw e;
   } catch (Exception e) {
     logger.warn(
         "failed to decode response, statusCode={}, responseText={}",
         status.code,
         response.text(),
         e);
     throw new RemoteServiceException(
         "received non 2xx status code, status="
             + status.code
             + ", remoteMessage="
             + response.text(),
         e);
   }
 }
  public <T> T execute(
      HTTPMethod method,
      String path,
      Map<String, String> pathParams,
      Object requestBean,
      Type responseType) {
    logger.debug(
        "call web service, serviceURL={}, method={}, path={}, pathParams={}",
        serviceURL,
        method,
        path,
        pathParams);
    validateRequestBean(requestBean);

    String serviceURL = serviceURL(path, pathParams);
    HTTPRequest httpRequest = new HTTPRequest(method, serviceURL);

    linkContext(httpRequest);

    if (requestBean != null) {
      String json = JSON.toJSON(requestBean);
      if (method == HTTPMethod.GET || method == HTTPMethod.DELETE) {
        Map<String, String> queryParams =
            JSON.fromJSON(Types.map(String.class, String.class), json);
        queryParams.forEach(httpRequest::addParam);
      } else if (method == HTTPMethod.POST || method == HTTPMethod.PUT) {
        httpRequest.text(json, ContentTypes.APPLICATION_JSON);
      } else {
        throw Exceptions.error("not supported method, method={}", method);
      }
    }

    if (signer != null) {
      logger.debug("sign request, signer={}", signer.getClass().getCanonicalName());
      signer.sign(httpRequest);
    }

    HTTPResponse response = httpClient.execute(httpRequest);
    validateResponse(response);

    if (void.class != responseType) {
      return JSON.fromJSON(responseType, response.text());
    } else {
      return null;
    }
  }