Элегантный способ сохранить ответ POST (сущность, заголовки и статус) в базе данных - PullRequest
0 голосов
/ 11 января 2020

Мне нужно, чтобы POST-запросы моего приложения были идемпотентными. И для этого мне нужно сохранить весь контент Response (javax.ws.rs.core) (включая заголовки, сущность и состояние) в виде BLOB-файла в моей базе данных с UUID, а затем каждый раз, когда выполняется вызов POST, получает UUID из заголовка и проверяет, есть ли регистр для этого в БД, если это так, весь процесс пропускается и возвращается сохраненный Ответ, в противном случае код выполняется и перед возвратом Ответа сохраняется вместе с UUID .

РЕШЕНИЕ I - Не работает:

1 - преобразовать из ответа в Json, а затем в байтбуфер и сохранить в БД

Bytebuffer responseBytes = ByteBuffer.wrap(GsonUtil.toJson(response).getBytes(StandardCharsets.UTF_8));

2 - получить из БД, преобразовать из байтового буфера в Json, а затем в ответ:

public Response getResponse(ByteBuffer byteBuffer) {
  byte[] bytesResponse = byteBuffer.array();
  String responseJson = new String(bytesResponse, StandardCharsets.UTF_8.name());
  return GsonUtil.fromJson(responseJson, Response.class);
}

Однако это не сработало, но выдает ошибку: «Попытка сериализации java .lang.Class: java .lang.String. Забыли зарегистрировать адаптер типа? "

РЕШЕНИЕ II - Сработало, но кажется сложным: (

1 - я извлекаю заголовки, сущность и статус для класс, который я создал:

import com.google.gson.JsonElement;

import lombok.Data;

@Data
public class SerializeableResponse
{
  private String responseBody;
  private JsonElement headers;
  private int status;
}

public static SerializeableResponse makeResponseSerializeable(Response response)
{
    String responseBody = Optional.ofNullable(response.getEntity()).orElse("").toString();
    JsonElement headers = RequestUtil.serializeHeaders(response.getHeaders());
    int status = response.getStatus();

    SerializeableResponse serializeableResponse = new SerializeableResponse();

    serializeableResponse.setResponseBody(responseBody);
    serializeableResponse.setHeaders(headers);
    serializeableResponse.setStatus(status);

    return serializeableResponse;
}

private static JsonElement serializeHeaders(MultivaluedMap<String, Object> headers)
{
    Map<String, List<String>> map = new HashMap<>();
    headers.entrySet().forEach(entry ->
    {
        List<String> values = entry.getValue().stream().map(Object::toString).collect(Collectors.toList());
        map.put(entry.getKey(), values);
    });

    return GsonUtil.toJsonTree(map);
}

2 - Затем я создаю P метод задницы для построения ответа

public static Response parseResponse(SerializeableResponse serializeableResponse)
{
    if(serializeableResponse == null) {
        return null;
    }

    ResponseBuilder responseBuilder = Response.status(serializeableResponse.getStatus());

    responseBuilder.entity(serializeableResponse.getResponseBody());

    serializeableResponse.getHeaders().getAsJsonObject().entrySet().forEach(entry -> entry.getValue().getAsJsonArray()
            .forEach(value -> responseBuilder.header(entry.getKey(), value.getAsString())));

    return responseBuilder.build();
}

Итак, с моим классом SerializeableResponse я могу использовать решение 1, и оно работает нормально, однако кажется сложным, поэтому мне интересно, есть ли лучшее решение для Эта проблема, однажды сделав POST-запрос идемпотентом, выглядит обычным делом. Если кто-то может помочь, я буду очень признателен.

...