class DaprClientHttp extends AbstractDaprClient {

  @Override
  public <T> Mono<Response<State<T>>> getState(GetStateRequest request, TypeRef<T> type) {
    try {
      final String stateStoreName = request.getStateStoreName();
      final String key = request.getKey();
      final StateOptions options = request.getStateOptions();
      final String etag = request.getEtag();
      final Context context = request.getContext();

      if ((stateStoreName == null) || (stateStoreName.trim().isEmpty())) {
        throw new IllegalArgumentException("State store name cannot be null or empty.");
      }
      if ((key == null) || (key.trim().isEmpty())) {
        throw new IllegalArgumentException("Key cannot be null or empty.");
      }
      Map<String, String> headers = new HashMap<>();
      if (etag != null && !etag.trim().isEmpty()) {
        headers.put(HEADER_HTTP_ETAG_ID, etag);
      }

      StringBuilder url = new StringBuilder(STATE_PATH)
          .append("/")
          .append(stateStoreName)
          .append("/")
          .append(key);
      Map<String, String> urlParameters = Optional.ofNullable(options)
          .map(o -> o.getStateOptionsAsMap())
          .orElse(new HashMap<>());

      request.getMetadata().forEach(urlParameters::put);

      return this.client
          .invokeApi(DaprHttp.HttpMethods.GET.name(), url.toString(), urlParameters, headers, context)
          .flatMap(s -> {
            try {
              return Mono.just(buildState(s, key, options, type));
            } catch (Exception ex) {
              return Mono.error(ex);
            }
          })
          .map(r -> new Response<>(context, r));
    } catch (Exception ex) {
      return Mono.error(ex);
    }
  }

    DaprClientHttp(DaprHttp client, DaprObjectSerializer objectSerializer, DaprObjectSerializer stateSerializer);
    DaprClientHttp(DaprHttp client);

}