|
16 | 16 |
|
17 | 17 | package org.springframework.integration.webflux.outbound;
|
18 | 18 |
|
19 |
| -import java.nio.charset.StandardCharsets; |
20 | 19 | import java.time.Duration;
|
| 20 | +import java.util.Map; |
| 21 | +import java.util.concurrent.atomic.AtomicReference; |
21 | 22 |
|
22 | 23 | import org.junit.jupiter.api.Test;
|
23 | 24 | import reactor.core.publisher.Flux;
|
24 | 25 | import reactor.core.publisher.Mono;
|
25 | 26 | import reactor.test.StepVerifier;
|
26 | 27 |
|
| 28 | +import org.springframework.beans.factory.BeanFactory; |
27 | 29 | import org.springframework.core.io.buffer.DataBuffer;
|
28 | 30 | import org.springframework.core.io.buffer.DataBufferFactory;
|
29 | 31 | import org.springframework.core.io.buffer.DataBufferLimitException;
|
| 32 | +import org.springframework.expression.Expression; |
| 33 | +import org.springframework.expression.spel.standard.SpelExpressionParser; |
30 | 34 | import org.springframework.http.HttpStatus;
|
31 | 35 | import org.springframework.http.MediaType;
|
32 | 36 | import org.springframework.http.client.reactive.ClientHttpConnector;
|
|
40 | 44 | import org.springframework.messaging.MessageHandlingException;
|
41 | 45 | import org.springframework.messaging.support.ErrorMessage;
|
42 | 46 | import org.springframework.test.web.reactive.server.HttpHandlerConnector;
|
| 47 | +import org.springframework.web.reactive.function.client.ClientRequest; |
| 48 | +import org.springframework.web.reactive.function.client.ClientResponse; |
| 49 | +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; |
| 50 | +import org.springframework.web.reactive.function.client.ExchangeFunction; |
43 | 51 | import org.springframework.web.reactive.function.client.ExchangeStrategies;
|
44 | 52 | import org.springframework.web.reactive.function.client.WebClient;
|
45 | 53 | import org.springframework.web.reactive.function.client.WebClientResponseException;
|
46 | 54 |
|
47 | 55 | import static org.assertj.core.api.Assertions.assertThat;
|
| 56 | +import static org.mockito.Mockito.mock; |
48 | 57 |
|
49 | 58 | /**
|
50 | 59 | * @author Shiliang Li
|
51 | 60 | * @author Artem Bilan
|
52 | 61 | * @author David Graff
|
| 62 | + * @author Jatin Saxena |
53 | 63 | *
|
54 | 64 | * @since 5.0
|
55 | 65 | */
|
@@ -289,15 +299,16 @@ void testClientHttpResponseErrorAsReply() {
|
289 | 299 |
|
290 | 300 | Flux<DataBuffer> data =
|
291 | 301 | Flux.just(
|
292 |
| - bufferFactory.wrap("{".getBytes(StandardCharsets.UTF_8)), |
293 |
| - bufferFactory.wrap(" \"error\": \"Not Found\",".getBytes(StandardCharsets.UTF_8)), |
294 |
| - bufferFactory.wrap(" \"message\": \"404 NOT_FOUND\",".getBytes(StandardCharsets.UTF_8)), |
295 |
| - bufferFactory.wrap(" \"path\": \"/spring-integration\",".getBytes(StandardCharsets.UTF_8)), |
296 |
| - bufferFactory.wrap(" \"status\": 404,".getBytes(StandardCharsets.UTF_8)), |
297 |
| - bufferFactory.wrap(" \"timestamp\": \"1970-01-01T00:00:00.000+00:00\",".getBytes(StandardCharsets.UTF_8)), |
298 |
| - bufferFactory.wrap(" \"trace\": \"some really\nlong\ntrace\",".getBytes(StandardCharsets.UTF_8)), |
299 |
| - bufferFactory.wrap("}".getBytes(StandardCharsets.UTF_8)) |
300 |
| - ); |
| 302 | + "{", |
| 303 | + " \"error\": \"Not Found\",", |
| 304 | + " \"message\": \"404 NOT_FOUND\",", |
| 305 | + " \"path\": \"/spring-integration\",", |
| 306 | + " \"status\": 404,", |
| 307 | + " \"timestamp\": \"1970-01-01T00:00:00.000+00:00\",", |
| 308 | + " \"trace\": \"some really\nlong\ntrace\",", |
| 309 | + "}") |
| 310 | + .map(String::getBytes) |
| 311 | + .map(bufferFactory::wrap); |
301 | 312 |
|
302 | 313 | return response.writeWith(data)
|
303 | 314 | .then(Mono.defer(response::setComplete));
|
@@ -376,4 +387,60 @@ void testMaxInMemorySizeExceeded() {
|
376 | 387 | .isEqualTo("Exceeded limit on max bytes to buffer : 1");
|
377 | 388 | }
|
378 | 389 |
|
| 390 | + @Test |
| 391 | + @SuppressWarnings("unchecked") |
| 392 | + void testFluxReplyWithRequestAttribute() { |
| 393 | + ClientHttpConnector httpConnector = new HttpHandlerConnector((request, response) -> { |
| 394 | + response.setStatusCode(HttpStatus.OK); |
| 395 | + response.getHeaders().setContentType(MediaType.TEXT_PLAIN); |
| 396 | + |
| 397 | + DataBufferFactory bufferFactory = response.bufferFactory(); |
| 398 | + |
| 399 | + Mono<DataBuffer> data = Mono.just(bufferFactory.wrap("foo\nbar\nbaz".getBytes())); |
| 400 | + |
| 401 | + return response.writeWith(data) |
| 402 | + .then(Mono.defer(response::setComplete)); |
| 403 | + }); |
| 404 | + |
| 405 | + class AttributeFilter implements ExchangeFilterFunction { |
| 406 | + |
| 407 | + final AtomicReference<Object> attributeValueName = new AtomicReference<>(); |
| 408 | + |
| 409 | + @Override |
| 410 | + public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) { |
| 411 | + this.attributeValueName.set(request.attribute("name").orElse(null)); |
| 412 | + return next.exchange(request); |
| 413 | + } |
| 414 | + } |
| 415 | + |
| 416 | + AttributeFilter attributeFilter = new AttributeFilter(); |
| 417 | + WebClient webClient = WebClient.builder() |
| 418 | + .clientConnector(httpConnector) |
| 419 | + .filter(attributeFilter) |
| 420 | + .build(); |
| 421 | + |
| 422 | + String destinationUri = "https://www.springsource.org/spring-integration"; |
| 423 | + WebFluxRequestExecutingMessageHandler reactiveHandler = |
| 424 | + new WebFluxRequestExecutingMessageHandler(destinationUri, webClient); |
| 425 | + |
| 426 | + QueueChannel replyChannel = new QueueChannel(); |
| 427 | + reactiveHandler.setOutputChannel(replyChannel); |
| 428 | + reactiveHandler.setExpectedResponseType(String.class); |
| 429 | + reactiveHandler.setReplyPayloadToFlux(true); |
| 430 | + Expression expr = new SpelExpressionParser().parseExpression("{name:{first:'Nikola'}}"); |
| 431 | + reactiveHandler.setAttributeVariablesExpression(expr); |
| 432 | + reactiveHandler.setBeanFactory(mock(BeanFactory.class)); |
| 433 | + reactiveHandler.afterPropertiesSet(); |
| 434 | + |
| 435 | + reactiveHandler.handleMessage(MessageBuilder.withPayload(Mono.just("hello, world")).build()); |
| 436 | + |
| 437 | + Message<?> receive = replyChannel.receive(10_000); |
| 438 | + |
| 439 | + assertThat(attributeFilter.attributeValueName.get()).isNotNull(); |
| 440 | + |
| 441 | + Map<String, String> attributeValueNameMap = (Map<String, String>) attributeFilter.attributeValueName.get(); |
| 442 | + assertThat(attributeValueNameMap.get("first")).isEqualTo("Nikola"); |
| 443 | + assertThat(receive).isNotNull(); |
| 444 | + } |
| 445 | + |
379 | 446 | }
|
0 commit comments