W jaki sposób ładnie obsłużyć dwa potencjalne typy które mogą przyjść jako ResponseEntity<?>
Dajmy na to na 404 przychodzi jakiś ErrorDto
z całkiem inną strukturą jsona, a na 200 UserDto
.
W jaki sposób ładnie obsłużyć dwa potencjalne typy które mogą przyjść jako ResponseEntity<?>
Dajmy na to na 404 przychodzi jakiś ErrorDto
z całkiem inną strukturą jsona, a na 200 UserDto
.
Najpierw sprawdzasz status odpowiedzi, później mapujesz?
czyli poprawnym jest takie wywołanie?
ResponseEntity<?> response = restTemplate
.exchange(url, HttpMethod.GET, request, Object.class);
i potem robić mapowanie?
Ja bym robił coś w stylu:
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, request, String.class);
Aby dostać stringa który jest JSONem a później jakiegoś ifa:
if(response.getStatus().equals(OK)) {
myClass = gson.fromJson(response.getBody, My.Class);
}
Mniej więcej taki koncept.
IMO standardowo dla HTTP status != 2xx zostanie odpalony Spingowy error handler, wiec do parsowania body nawet nie dojdzie. Napisz test i dobrze się przedebuguj przez internale.
https://www.baeldung.com/spring-rest-template-error-handling
Polecam zabawki typu OpenAPI - klienta wygeneruje za ciebie i nie musisz się takimi low levelowymi rzeczami przejmować.
@Charles_Ray: mówi dobrze, RestTemplate jest zrypany i jak jest 400 albo 500 to rzuca wyjątkiem. Czemu? Nie wiem.
Tutaj jest pies pogrzebany:
https://github.com/spring-projects/spring-framework/blob/main/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java#L796
https://github.com/spring-projects/spring-framework/blob/main/spring-web/src/main/java/org/springframework/web/client/DefaultResponseErrorHandler.java#L159
Chyba musisz owrappowac RT w jakiegoś własnego klienta i w nim obsłużyć wyjątek. Inaczej nie za bardzo to widzę biorąc pod uwagę API RT.
Kiedyś poczyniłem taki kod:
public static <T> Either<ResponseEntity<ApiErrorDetails>, ResponseEntity<T>> parseAndGetResponse(ResponseEntity<String> response, Type responseType) {
if (response.getStatusCode().is2xxSuccessful()) {
T body = gson.fromJson(response.getBody(), responseType);
ResponseEntity<T> parsedResponse = new ResponseEntity<>(body, response.getHeaders(), response.getStatusCode());
return Either.right(parsedResponse);
}
ApiErrorDetails body = gson.fromJson(response.getBody(), ApiErrorDetails.class);
ResponseEntity<ApiErrorDetails> parsedResponse = new ResponseEntity<>(body, response.getHeaders(), response.getStatusCode());
return Either.left(parsedResponse);
}
ResponseEntity<String> response = restTemplate.getForEntity(...);
var parsedResponse = parseAndGetResponse(response, new TypeToken<UserDto>(){}.getType());
więcej tutaj
domenowy wrapper
pod konkretny serwis.Mapować odpowiedź na podstawie status code.
No w sumie racja w Javovym rest kliencie możesz wyciągnąc body jako Stringi jak człowiek użyć jakiegoś Jacksona do zmapowania
Pokaz przykładowe uzycie - jak to pożeniłeś z RestTemplate, który rzuca wyjątkami? Nadpisywales ErrorHandler?
Tak można nadpisać podobnie jak to robi TestRestTemplate
:
class NoOpResponseErrorHandler extends DefaultResponseErrorHandler {
public void handleError(ClientHttpResponse response) {}
}
restTemplate.setErrorHandler(new NoOpResponseErrorHandler());
ResponseEntity<String> response = restTemplate.getForEntity(..., String.class);
@Shalom:
Nie używać RestTemplate, Java ma już od dawna własnego HttpClienta
imo jest trochę niskopoziomowy w porównaniu do restTemplate.
imo jest trochę niskopoziomowy w porównaniu do restTemplate.
W jaki sposób? Poza tym że trzeba co najwyżej Jacksona jawnie użyć do zmapowania obiektu?
scibi_92 napisał(a):
W jaki sposób? Poza tym że trzeba co najwyżej Jacksona jawnie użyć do zmapowania obiektu?
W restTemplate można dodawać interceptory można ustawić root uri jakieś factory też skonfigurować
i nie trzeba za każdym razem ręcznie mapować używając jackson / gson. Nie wiem też jakie możliwości
ma javovy http client bo mało go używałem ale wydaje się, że więcej się trzeba napisać.
lookacode1 napisał(a):
scibi_92 napisał(a):
W jaki sposób? Poza tym że trzeba co najwyżej Jacksona jawnie użyć do zmapowania obiektu?
W restTemplate można dodawać interceptory można ustawić root uri jakieś factory też skonfigurować
i nie trzeba za każdym razem ręcznie mapować używając jackson / gson. Nie wiem też jakie możliwości
ma javovy http client bo mało go używałem ale wydaje się, że więcej się trzeba napisać.
Brzmi jak tight-coupling ciaśniejszy niż... może zcenzuruję tutaj.
Zrób wrapper na to, specyficzny dla Twojego przypadku po prostu.