#spring-integration #spring-webflux #spring-integration-dsl
Вопрос:
Я пытаюсь разработать WebClient
основанный подход к обработке и обогащению с использованием подпотока при WebFlux.outboundGateway
вызове.
Мое намерение состоит в том, чтобы обработать случай, когда HTTP/404 происходит на удаленном конце. В этом случае я обработаю ошибку с помощью известного документа, который можно обработать по потоку и направить соответствующим образом.
.enrich( e ->
e.requestSubFlow(
sf -> sf.handle(
WebFlux.outboundGateway("http://example.com/entity/name/{entityName}")
.uriVariable("entityName", "payload")
.httpMethod(HttpMethod.GET)
.expectedResponseType(String.class),
ec -> ec.customizeMonoReply(
(message,mono) ->
mono.onErrorResume(
WebClientResponseException.NotFound.class,
Mono.just("{ "id": -1, "name": null }")
.flatMap(s ->
ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(s)
)
)
)
)
)
.headerExpression("result", "payload")
)
Я получаю ошибку компиляции, аналогичную следующей:
The method onErrorResume(Class<E>, Function<? super E,? extends Mono<? extends capture#3-of ?>>) in the type Mono<capture#3-of ?> is not applicable for the arguments (Class<WebClientResponseException.NotFound>, Mono<Object>)
Я даже не знаю, правильно ли я подхожу к этому. Любой совет был бы очень признателен.
Чтобы помочь в этом, я опубликовал весь код https://github.com/djgraff209/so68637283.
ПРАВКА 8/6:
Спасибо @artem-bilan за отзывы по этому поводу. Первый момент заключался в том, что второй аргумент to onErrorResume
не был функцией. Я это исправил.
Далее, совпадение исключений оказалось неправильным. WebClientResponseException
Был брошен общий, а не более конкретный WebClientResponseException.NotFound
, на что я и надеялся.
Я обновил логику следующим образом. Этот код доступен в указанном проекте GitHub.
ec -> ec.customizeMonoReply(
(Message<?> message, Mono<?> mono) ->
mono.onErrorResume(
WebClientResponseException.class,
ex1 -> {
Mono<?> exReturn = mono;
if( ex1.getStatusCode() == HttpStatus.NOT_FOUND ) {
exReturn = Mono.just(defaultPayload);
}
return (Mono)exReturn;
}
)
)
Хотя это работает, это не так чисто, как хотелось бы. Я не в восторге от необходимости вводить условие if, чтобы разрешить тип исключения с помощью HttpStatus
, а не просто разрешить его для определенного класса.
Это может быть хорошим кандидатом на исправление/улучшение.
Отправлено #3610
Ответ №1:
Я думаю, что это должно быть так:
mono.onErrorResume(
WebClientResponseException.class,
ex1 -> Mono.just(ex1)
.filter(ex -> ex.getStatusCode() == HttpStatus.NOT_FOUND)
.map(ex -> "default")
.switchIfEmpty((Mono) mono))
Ожидается , что вторым аргументом onErrorResume()
будет a Function
, а не константа, как у вас до сих пор.
Комментарии:
1. Я попытался преобразовать это, как вы предложили, но получаю:
Type mismatch: cannot convert from Mono<Object> to Mono<? extends capture#3-of ?>
2. Да… Я понимаю вашу точку зрения. Это
Mono.just()
должно быть приведено к(Mono)
. Смотрите правку к моему ответу. Я вижу решение этойcustomizeMonoReply()
проблемы с помощью дженериков. Таким образом, в будущей версии вам не понадобится этот(Mono)
актерский состав.3. Я только что обновил базу кода на упомянутом главном посте github — обновление в ближайшее время. Я хочу, чтобы вы поняли, как это работает.
4. Видеть
.DefaultWebClientDefaultResponseSpec.statusHandlers
. Вероятно , вместо этого каким-то образом используется какой-то другой обработчикDEFAULT_STATUS_HANDLER
, которыйClientResponse::createException
выполняет обратный вызов для определенного исключения в зависимости от статуса. Или ваш статус возвращается в каком-то другом формате. Это то, что нам нужно отладить. Вероятно, вы можете поделиться каким-нибудь простым проектом, с которым можно поиграть.5. Смотрите отредактированный фрагмент кода, как избежать этого
if..else
в вашем коде.