private void linkContext(HTTPRequest httpRequest) {
    ActionLogContext.get(ActionLogContext.REQUEST_ID)
        .ifPresent(requestId -> httpRequest.header(HTTPServerHandler.HEADER_REQUEST_ID, requestId));

    ActionLogContext.get(ActionLogContext.TRACE)
        .ifPresent(
            trace -> {
              if ("true".equals(trace)) {
                httpRequest.header(HTTPServerHandler.HEADER_TRACE, "true");
              }
            });
  }
  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;
    }
  }