INT-4208: Add WebFlux-Based HttpMessageHandler
JIRA: https://jira.spring.io/browse/INT-4208 Since `AsyncRestTemplate` is deprecated in Spring 5.0, it doesn't make sense to promote that feature via our new `AsyncHttpRequestExecutingMessageHandler` component * Rework (and rename) `AsyncHttpRequestExecutingMessageHandler` to `ReactiveHttpRequestExecutingMessageHandler` and make it based on the WebFlux `WebClient` * Fix Java DSL (`ReactiveHttpMessageHandlerSpec`) and all tests according a new logic in the `ReactiveHttpRequestExecutingMessageHandler` * Fix XML namespace support to use new `ReactiveHttpRequestExecutingMessageHandler` and don't expose unused options like `converters` and `request-factory` * Fix `What's New` and `http.adoc` * To remain with `async` mode for the `ReactiveHttpRequestExecutingMessageHandler` behavior support fix `AbstractMessageProducingHandler` to adapt reply `Mono` to the `SettableListenableFuture` * Introduce new `reactive` behavior for the `AbstractMessageProducingHandler` when `outputChannel` is `ReactiveSubscribableChannel` and perform `.subscribeTo(Publisher)` for `Publisher` reply * Upgrade to Spring AMQP `2.0 M3` * Downgrade to Spring Security `4.2.2` Address PR comments Add async error handling to the one-way case Minor polishing and checkstyle fix
This commit is contained in:
committed by
Gary Russell
parent
d954e6a66f
commit
19c5402079
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans
|
||||
xmlns="http://www.springframework.org/schema/integration/http"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd
|
||||
xmlns="http://www.springframework.org/schema/integration/http"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
|
||||
@@ -14,29 +14,32 @@
|
||||
|
||||
<outbound-channel-adapter id="minimalConfig" url="http://localhost/test1" channel="requests"/>
|
||||
|
||||
<outbound-channel-adapter id="restTemplateConfig" url="http://localhost/test1" channel="requests" rest-template="customRestTemplate"/>
|
||||
<outbound-channel-adapter id="restTemplateConfig" url="http://localhost/test1" channel="requests"
|
||||
rest-template="customRestTemplate"/>
|
||||
|
||||
<outbound-async-channel-adapter id="asyncMinimalConfig" url="http://localhost/test1" channel="requests" />
|
||||
<outbound-reactive-channel-adapter id="reactiveMinimalConfig" url="http://localhost/test1" channel="requests"/>
|
||||
|
||||
<outbound-async-channel-adapter id="asyncRestTemplateConfig" url="http://localhost/test1" channel="requests" async-rest-template="asyncRestTemplate" />
|
||||
<outbound-reactive-channel-adapter id="reactiveWebClientConfig" url="http://localhost/test1" channel="requests"
|
||||
web-client="webClient"/>
|
||||
|
||||
<beans:bean id="customRestTemplate" class="org.springframework.web.client.RestTemplate"/>
|
||||
|
||||
<beans:bean id="asyncRestTemplate" class="org.springframework.web.client.AsyncRestTemplate"/>
|
||||
<beans:bean id="webClient" class="org.springframework.web.reactive.function.client.WebClient"
|
||||
factory-method="create"/>
|
||||
|
||||
<outbound-channel-adapter id="fullConfig"
|
||||
url="http://localhost/test2/{foo}"
|
||||
http-method="GET"
|
||||
channel="requests"
|
||||
charset="UTF-8"
|
||||
message-converters="converterList"
|
||||
extract-payload="false"
|
||||
expected-response-type="java.lang.Boolean"
|
||||
mapped-request-headers="requestHeader1, requestHeader2"
|
||||
request-factory="testRequestFactory"
|
||||
error-handler="testErrorHandler"
|
||||
order="77"
|
||||
auto-startup="false">
|
||||
url="http://localhost/test2/{foo}"
|
||||
http-method="GET"
|
||||
channel="requests"
|
||||
charset="UTF-8"
|
||||
message-converters="converterList"
|
||||
extract-payload="false"
|
||||
expected-response-type="java.lang.Boolean"
|
||||
mapped-request-headers="requestHeader1, requestHeader2"
|
||||
request-factory="testRequestFactory"
|
||||
error-handler="testErrorHandler"
|
||||
order="77"
|
||||
auto-startup="false">
|
||||
<uri-variable name="foo" expression="headers.bar"/>
|
||||
|
||||
</outbound-channel-adapter>
|
||||
@@ -47,21 +50,22 @@
|
||||
</util:map>
|
||||
|
||||
<outbound-channel-adapter id="withUrlAndTemplate"
|
||||
url="http://localhost/test1" channel="requests"
|
||||
uri-variables-expression="@uriVariables"
|
||||
rest-template="customRestTemplate"/>
|
||||
url="http://localhost/test1" channel="requests"
|
||||
uri-variables-expression="@uriVariables"
|
||||
rest-template="customRestTemplate"/>
|
||||
|
||||
<outbound-channel-adapter id="withUrlExpression" url-expression="'http://localhost/test1'" channel="requests"/>
|
||||
|
||||
<outbound-channel-adapter id="withAdvice" url-expression="'http://localhost/test1'" channel="requests">
|
||||
<request-handler-advice-chain>
|
||||
<beans:bean class="org.springframework.integration.http.config.HttpOutboundChannelAdapterParserTests$FooAdvice" />
|
||||
<beans:bean
|
||||
class="org.springframework.integration.http.config.HttpOutboundChannelAdapterParserTests$FooAdvice"/>
|
||||
</request-handler-advice-chain>
|
||||
</outbound-channel-adapter>
|
||||
|
||||
<outbound-channel-adapter id="withUrlExpressionAndTemplate"
|
||||
url-expression="'http://localhost/test1'" channel="requests"
|
||||
rest-template="customRestTemplate"/>
|
||||
url-expression="'http://localhost/test1'" channel="requests"
|
||||
rest-template="customRestTemplate"/>
|
||||
|
||||
<si:channel id="queueChannel">
|
||||
<si:queue capacity="10"/>
|
||||
@@ -102,7 +106,8 @@
|
||||
|
||||
<beans:bean id="testAsyncRequestFactory" class="org.springframework.http.client.SimpleClientHttpRequestFactory"/>
|
||||
|
||||
<beans:bean id="testErrorHandler" class="org.springframework.integration.http.config.HttpOutboundChannelAdapterParserTests$StubErrorHandler"/>
|
||||
<beans:bean id="testErrorHandler"
|
||||
class="org.springframework.integration.http.config.HttpOutboundChannelAdapterParserTests$StubErrorHandler"/>
|
||||
|
||||
<util:list id="converterList">
|
||||
<beans:bean class="org.springframework.integration.http.config.StubHttpMessageConverter"/>
|
||||
|
||||
@@ -41,14 +41,12 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpression;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.client.AsyncClientHttpRequestFactory;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
import org.springframework.integration.endpoint.PollingConsumer;
|
||||
import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
|
||||
import org.springframework.integration.http.outbound.AsyncHttpRequestExecutingMessageHandler;
|
||||
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
@@ -58,9 +56,9 @@ import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.client.AsyncRestTemplate;
|
||||
import org.springframework.web.client.ResponseErrorHandler;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
@@ -75,40 +73,51 @@ import org.springframework.web.client.RestTemplate;
|
||||
@DirtiesContext
|
||||
public class HttpOutboundChannelAdapterParserTests {
|
||||
|
||||
@Autowired @Qualifier("minimalConfig")
|
||||
@Autowired
|
||||
@Qualifier("minimalConfig")
|
||||
private AbstractEndpoint minimalConfig;
|
||||
|
||||
@Autowired @Qualifier("fullConfig")
|
||||
@Autowired
|
||||
@Qualifier("fullConfig")
|
||||
private AbstractEndpoint fullConfig;
|
||||
|
||||
@Autowired @Qualifier("restTemplateConfig")
|
||||
@Autowired
|
||||
@Qualifier("restTemplateConfig")
|
||||
private AbstractEndpoint restTemplateConfig;
|
||||
|
||||
@Autowired @Qualifier("asyncMinimalConfig")
|
||||
private AbstractEndpoint asyncMinimalConfig;
|
||||
@Autowired
|
||||
@Qualifier("reactiveMinimalConfig")
|
||||
private AbstractEndpoint reactiveMinimalConfig;
|
||||
|
||||
@Autowired @Qualifier("asyncRestTemplateConfig")
|
||||
private AbstractEndpoint asyncRestTemplateConfig;
|
||||
@Autowired
|
||||
@Qualifier("reactiveWebClientConfig")
|
||||
private AbstractEndpoint reactiveWebClientConfig;
|
||||
|
||||
@Autowired @Qualifier("customRestTemplate")
|
||||
@Autowired
|
||||
@Qualifier("customRestTemplate")
|
||||
private RestTemplate customRestTemplate;
|
||||
|
||||
@Autowired @Qualifier("asyncRestTemplate")
|
||||
private AsyncRestTemplate asyncRestTemplate;
|
||||
@Autowired
|
||||
private WebClient webClient;
|
||||
|
||||
@Autowired @Qualifier("withUrlAndTemplate")
|
||||
@Autowired
|
||||
@Qualifier("withUrlAndTemplate")
|
||||
private AbstractEndpoint withUrlAndTemplate;
|
||||
|
||||
@Autowired @Qualifier("withUrlExpression")
|
||||
@Autowired
|
||||
@Qualifier("withUrlExpression")
|
||||
private AbstractEndpoint withUrlExpression;
|
||||
|
||||
@Autowired @Qualifier("withAdvice")
|
||||
@Autowired
|
||||
@Qualifier("withAdvice")
|
||||
private AbstractEndpoint withAdvice;
|
||||
|
||||
@Autowired @Qualifier("withUrlExpressionAndTemplate")
|
||||
@Autowired
|
||||
@Qualifier("withUrlExpressionAndTemplate")
|
||||
private AbstractEndpoint withUrlExpressionAndTemplate;
|
||||
|
||||
@Autowired @Qualifier("withPoller1")
|
||||
@Autowired
|
||||
@Qualifier("withPoller1")
|
||||
private AbstractEndpoint withPoller1;
|
||||
|
||||
@Autowired
|
||||
@@ -120,7 +129,7 @@ public class HttpOutboundChannelAdapterParserTests {
|
||||
public void minimalConfig() {
|
||||
DirectFieldAccessor endpointAccessor = new DirectFieldAccessor(this.minimalConfig);
|
||||
RestTemplate restTemplate =
|
||||
TestUtils.getPropertyValue(this.minimalConfig, "handler.restTemplate", RestTemplate.class);
|
||||
TestUtils.getPropertyValue(this.minimalConfig, "handler.restTemplate", RestTemplate.class);
|
||||
assertNotSame(customRestTemplate, restTemplate);
|
||||
HttpRequestExecutingMessageHandler handler = (HttpRequestExecutingMessageHandler) endpointAccessor.getPropertyValue("handler");
|
||||
DirectFieldAccessor handlerAccessor = new DirectFieldAccessor(handler);
|
||||
@@ -179,23 +188,20 @@ public class HttpOutboundChannelAdapterParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asyncMinimalConfig() {
|
||||
DirectFieldAccessor endpointAccessor = new DirectFieldAccessor(this.asyncMinimalConfig);
|
||||
AsyncRestTemplate asyncRestTemplate =
|
||||
TestUtils.getPropertyValue(this.asyncMinimalConfig, "handler.asyncRestTemplate", AsyncRestTemplate.class);
|
||||
assertNotSame(this.asyncRestTemplate, asyncRestTemplate);
|
||||
AsyncHttpRequestExecutingMessageHandler handler = (AsyncHttpRequestExecutingMessageHandler) endpointAccessor.getPropertyValue("handler");
|
||||
public void reactiveMinimalConfig() {
|
||||
DirectFieldAccessor endpointAccessor = new DirectFieldAccessor(this.reactiveMinimalConfig);
|
||||
WebClient webClient =
|
||||
TestUtils.getPropertyValue(this.reactiveMinimalConfig, "handler.webClient", WebClient.class);
|
||||
assertNotSame(this.webClient, webClient);
|
||||
Object handler = endpointAccessor.getPropertyValue("handler");
|
||||
DirectFieldAccessor handlerAccessor = new DirectFieldAccessor(handler);
|
||||
assertEquals(false, handlerAccessor.getPropertyValue("expectReply"));
|
||||
assertEquals(this.applicationContext.getBean("requests"), endpointAccessor.getPropertyValue("inputChannel"));
|
||||
assertNull(handlerAccessor.getPropertyValue("outputChannel"));
|
||||
DirectFieldAccessor templateAccessor = new DirectFieldAccessor(handlerAccessor.getPropertyValue("asyncRestTemplate"));
|
||||
AsyncClientHttpRequestFactory asyncRequestFactory = (AsyncClientHttpRequestFactory)
|
||||
templateAccessor.getPropertyValue("asyncRequestFactory");
|
||||
assertTrue(asyncRequestFactory instanceof SimpleClientHttpRequestFactory);
|
||||
Expression uriExpression = (Expression) handlerAccessor.getPropertyValue("uriExpression");
|
||||
assertEquals("http://localhost/test1", uriExpression.getValue());
|
||||
assertEquals(HttpMethod.POST.name(), TestUtils.getPropertyValue(handler, "httpMethodExpression", Expression.class).getExpressionString());
|
||||
assertEquals(HttpMethod.POST.name(),
|
||||
TestUtils.getPropertyValue(handler, "httpMethodExpression", Expression.class).getExpressionString());
|
||||
assertEquals(Charset.forName("UTF-8"), handlerAccessor.getPropertyValue("charset"));
|
||||
assertEquals(true, handlerAccessor.getPropertyValue("extractPayload"));
|
||||
}
|
||||
@@ -203,16 +209,13 @@ public class HttpOutboundChannelAdapterParserTests {
|
||||
@Test
|
||||
public void restTemplateConfig() {
|
||||
RestTemplate restTemplate =
|
||||
TestUtils.getPropertyValue(this.restTemplateConfig, "handler.restTemplate", RestTemplate.class);
|
||||
TestUtils.getPropertyValue(this.restTemplateConfig, "handler.restTemplate", RestTemplate.class);
|
||||
assertEquals(customRestTemplate, restTemplate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asyncRestTemplateConfig() {
|
||||
AsyncRestTemplate asyncRestTemplate = TestUtils.getPropertyValue(
|
||||
this.asyncRestTemplateConfig,
|
||||
"handler.asyncRestTemplate", AsyncRestTemplate.class);
|
||||
assertSame(this.asyncRestTemplate, asyncRestTemplate);
|
||||
public void reactiveWebClientConfig() {
|
||||
assertSame(this.webClient, TestUtils.getPropertyValue(this.reactiveWebClientConfig, "handler.webClient"));
|
||||
}
|
||||
|
||||
@Test(expected = BeanDefinitionParsingException.class)
|
||||
@@ -225,7 +228,7 @@ public class HttpOutboundChannelAdapterParserTests {
|
||||
public void withUrlAndTemplate() {
|
||||
DirectFieldAccessor endpointAccessor = new DirectFieldAccessor(this.withUrlAndTemplate);
|
||||
RestTemplate restTemplate =
|
||||
TestUtils.getPropertyValue(this.withUrlAndTemplate, "handler.restTemplate", RestTemplate.class);
|
||||
TestUtils.getPropertyValue(this.withUrlAndTemplate, "handler.restTemplate", RestTemplate.class);
|
||||
assertSame(customRestTemplate, restTemplate);
|
||||
HttpRequestExecutingMessageHandler handler = (HttpRequestExecutingMessageHandler) endpointAccessor.getPropertyValue("handler");
|
||||
DirectFieldAccessor handlerAccessor = new DirectFieldAccessor(handler);
|
||||
@@ -255,7 +258,7 @@ public class HttpOutboundChannelAdapterParserTests {
|
||||
public void withUrlExpression() {
|
||||
DirectFieldAccessor endpointAccessor = new DirectFieldAccessor(this.withUrlExpression);
|
||||
RestTemplate restTemplate =
|
||||
TestUtils.getPropertyValue(this.withUrlExpression, "handler.restTemplate", RestTemplate.class);
|
||||
TestUtils.getPropertyValue(this.withUrlExpression, "handler.restTemplate", RestTemplate.class);
|
||||
assertNotSame(customRestTemplate, restTemplate);
|
||||
HttpRequestExecutingMessageHandler handler = (HttpRequestExecutingMessageHandler) endpointAccessor.getPropertyValue("handler");
|
||||
DirectFieldAccessor handlerAccessor = new DirectFieldAccessor(handler);
|
||||
@@ -285,7 +288,7 @@ public class HttpOutboundChannelAdapterParserTests {
|
||||
public void withUrlExpressionAndTemplate() {
|
||||
DirectFieldAccessor endpointAccessor = new DirectFieldAccessor(this.withUrlExpressionAndTemplate);
|
||||
RestTemplate restTemplate =
|
||||
TestUtils.getPropertyValue(this.withUrlExpressionAndTemplate, "handler.restTemplate", RestTemplate.class);
|
||||
TestUtils.getPropertyValue(this.withUrlExpressionAndTemplate, "handler.restTemplate", RestTemplate.class);
|
||||
assertSame(customRestTemplate, restTemplate);
|
||||
HttpRequestExecutingMessageHandler handler = (HttpRequestExecutingMessageHandler) endpointAccessor.getPropertyValue("handler");
|
||||
DirectFieldAccessor handlerAccessor = new DirectFieldAccessor(handler);
|
||||
@@ -325,6 +328,7 @@ public class HttpOutboundChannelAdapterParserTests {
|
||||
@Override
|
||||
public void handleError(ClientHttpResponse response) throws IOException {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class FooAdvice extends AbstractRequestHandlerAdvice {
|
||||
@@ -336,4 +340,5 @@ public class HttpOutboundChannelAdapterParserTests {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration/http"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
@@ -14,7 +14,8 @@
|
||||
|
||||
<si:channel id="requests"/>
|
||||
|
||||
<beans:bean id="asyncRestTemplate" class="org.springframework.web.client.AsyncRestTemplate"/>
|
||||
<beans:bean id="webClient" class="org.springframework.web.reactive.function.client.WebClient"
|
||||
factory-method="create"/>
|
||||
|
||||
<outbound-gateway id="minimalConfig" url="http://localhost/test1" request-channel="requests"/>
|
||||
|
||||
@@ -23,46 +24,44 @@
|
||||
</si:channel>
|
||||
|
||||
<outbound-gateway id="fullConfig"
|
||||
url="http://localhost/test2"
|
||||
http-method="PUT"
|
||||
request-channel="requests"
|
||||
request-factory="testRequestFactory"
|
||||
reply-timeout="1234"
|
||||
message-converters="converterList"
|
||||
extract-request-payload="false"
|
||||
expected-response-type="java.lang.String"
|
||||
mapped-request-headers="requestHeader1, requestHeader2"
|
||||
mapped-response-headers="responseHeader"
|
||||
error-handler="testErrorHandler"
|
||||
reply-channel="replies"
|
||||
charset="UTF-8"
|
||||
order="77"
|
||||
auto-startup="false"
|
||||
transfer-cookies="true">
|
||||
url="http://localhost/test2"
|
||||
http-method="PUT"
|
||||
request-channel="requests"
|
||||
request-factory="testRequestFactory"
|
||||
reply-timeout="1234"
|
||||
message-converters="converterList"
|
||||
extract-request-payload="false"
|
||||
expected-response-type="java.lang.String"
|
||||
mapped-request-headers="requestHeader1, requestHeader2"
|
||||
mapped-response-headers="responseHeader"
|
||||
error-handler="testErrorHandler"
|
||||
reply-channel="replies"
|
||||
charset="UTF-8"
|
||||
order="77"
|
||||
auto-startup="false"
|
||||
transfer-cookies="true">
|
||||
<uri-variable name="foo" expression="headers.bar"/>
|
||||
</outbound-gateway>
|
||||
|
||||
<outbound-async-gateway id="asyncMinimalConfig" url="http://localhost/test1" request-channel="requests" async-rest-template="asyncRestTemplate"/>
|
||||
<outbound-reactive-gateway id="reactiveMinimalConfig" url="http://localhost/test1" request-channel="requests"
|
||||
web-client="webClient"/>
|
||||
|
||||
<outbound-async-gateway id="asyncFullConfig"
|
||||
url="http://localhost/test2"
|
||||
http-method="PUT"
|
||||
request-channel="requests"
|
||||
async-request-factory="testRequestFactory"
|
||||
reply-timeout="1234"
|
||||
message-converters="converterList"
|
||||
extract-request-payload="false"
|
||||
expected-response-type="java.lang.String"
|
||||
mapped-request-headers="requestHeader1, requestHeader2"
|
||||
mapped-response-headers="responseHeader"
|
||||
error-handler="testErrorHandler"
|
||||
reply-channel="replies"
|
||||
charset="UTF-8"
|
||||
order="77"
|
||||
auto-startup="false"
|
||||
transfer-cookies="true">
|
||||
<outbound-reactive-gateway id="reactiveFullConfig"
|
||||
url="http://localhost/test2"
|
||||
http-method="PUT"
|
||||
request-channel="requests"
|
||||
reply-timeout="1234"
|
||||
extract-request-payload="false"
|
||||
expected-response-type="java.lang.String"
|
||||
mapped-request-headers="requestHeader1, requestHeader2"
|
||||
mapped-response-headers="responseHeader"
|
||||
reply-channel="replies"
|
||||
charset="UTF-8"
|
||||
order="77"
|
||||
auto-startup="false"
|
||||
transfer-cookies="true">
|
||||
<uri-variable name="foo" expression="headers.bar"/>
|
||||
</outbound-async-gateway>
|
||||
</outbound-reactive-gateway>
|
||||
|
||||
<util:map id="uriVariables">
|
||||
<beans:entry key="foo1" value="bar1"/>
|
||||
@@ -74,7 +73,7 @@
|
||||
|
||||
<outbound-gateway id="withAdvice" url-expression="'http://localhost/test1'" request-channel="requests">
|
||||
<request-handler-advice-chain>
|
||||
<beans:bean class="org.springframework.integration.http.config.HttpOutboundGatewayParserTests$FooAdvice" />
|
||||
<beans:bean class="org.springframework.integration.http.config.HttpOutboundGatewayParserTests$FooAdvice"/>
|
||||
</request-handler-advice-chain>
|
||||
</outbound-gateway>
|
||||
|
||||
@@ -116,7 +115,8 @@
|
||||
|
||||
<beans:bean id="testRequestFactory" class="org.springframework.http.client.SimpleClientHttpRequestFactory"/>
|
||||
|
||||
<beans:bean id="testErrorHandler" class="org.springframework.integration.http.config.HttpOutboundGatewayParserTests$StubErrorHandler"/>
|
||||
<beans:bean id="testErrorHandler"
|
||||
class="org.springframework.integration.http.config.HttpOutboundGatewayParserTests$StubErrorHandler"/>
|
||||
|
||||
<util:list id="converterList">
|
||||
<beans:bean class="org.springframework.integration.http.config.StubHttpMessageConverter"/>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.integration.http.config;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
@@ -41,14 +42,12 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpression;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.client.AsyncClientHttpRequestFactory;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
import org.springframework.integration.endpoint.PollingConsumer;
|
||||
import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
|
||||
import org.springframework.integration.http.outbound.AsyncHttpRequestExecutingMessageHandler;
|
||||
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
@@ -58,8 +57,8 @@ import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.client.AsyncRestTemplate;
|
||||
import org.springframework.web.client.ResponseErrorHandler;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
@@ -72,29 +71,36 @@ import org.springframework.web.client.ResponseErrorHandler;
|
||||
@DirtiesContext
|
||||
public class HttpOutboundGatewayParserTests {
|
||||
|
||||
@Autowired @Qualifier("minimalConfig")
|
||||
@Autowired
|
||||
@Qualifier("minimalConfig")
|
||||
private AbstractEndpoint minimalConfigEndpoint;
|
||||
|
||||
@Autowired @Qualifier("fullConfig")
|
||||
@Autowired
|
||||
@Qualifier("fullConfig")
|
||||
private AbstractEndpoint fullConfigEndpoint;
|
||||
|
||||
@Autowired @Qualifier("asyncMinimalConfig")
|
||||
private AbstractEndpoint asyncMinimalConfigEndpoint;
|
||||
@Autowired
|
||||
@Qualifier("reactiveMinimalConfig")
|
||||
private AbstractEndpoint reactiveMinimalConfigEndpoint;
|
||||
|
||||
@Autowired @Qualifier("asyncFullConfig")
|
||||
private AbstractEndpoint asyncFullConfigEndpoint;
|
||||
@Autowired
|
||||
@Qualifier("reactiveFullConfig")
|
||||
private AbstractEndpoint reactiveFullConfigEndpoint;
|
||||
|
||||
@Autowired @Qualifier("withUrlExpression")
|
||||
@Autowired
|
||||
@Qualifier("withUrlExpression")
|
||||
private AbstractEndpoint withUrlExpressionEndpoint;
|
||||
|
||||
@Autowired @Qualifier("withAdvice")
|
||||
@Autowired
|
||||
@Qualifier("withAdvice")
|
||||
private AbstractEndpoint withAdvice;
|
||||
|
||||
@Autowired @Qualifier("withPoller1")
|
||||
@Autowired
|
||||
@Qualifier("withPoller1")
|
||||
private AbstractEndpoint withPoller1;
|
||||
|
||||
@Autowired @Qualifier("asyncRestTemplate")
|
||||
private AsyncRestTemplate asyncRestTemplate;
|
||||
@Autowired
|
||||
private WebClient webClient;
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
@@ -173,22 +179,19 @@ public class HttpOutboundGatewayParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asyncMinimalConfig() {
|
||||
AsyncHttpRequestExecutingMessageHandler handler = (AsyncHttpRequestExecutingMessageHandler) new DirectFieldAccessor(
|
||||
this.asyncMinimalConfigEndpoint).getPropertyValue("handler");
|
||||
MessageChannel requestChannel = (MessageChannel) new DirectFieldAccessor(
|
||||
this.minimalConfigEndpoint).getPropertyValue("inputChannel");
|
||||
public void reactiveMinimalConfig() {
|
||||
Object handler = new DirectFieldAccessor(this.reactiveMinimalConfigEndpoint).getPropertyValue("handler");
|
||||
Object requestChannel = new DirectFieldAccessor(this.reactiveMinimalConfigEndpoint)
|
||||
.getPropertyValue("inputChannel");
|
||||
assertEquals(this.applicationContext.getBean("requests"), requestChannel);
|
||||
DirectFieldAccessor handlerAccessor = new DirectFieldAccessor(handler);
|
||||
Object replyChannel = handlerAccessor.getPropertyValue("outputChannel");
|
||||
assertNull(replyChannel);
|
||||
DirectFieldAccessor templateAccessor = new DirectFieldAccessor(handlerAccessor.getPropertyValue("asyncRestTemplate"));
|
||||
AsyncClientHttpRequestFactory requestFactory = (AsyncClientHttpRequestFactory)
|
||||
templateAccessor.getPropertyValue("asyncRequestFactory");
|
||||
assertTrue(requestFactory instanceof SimpleClientHttpRequestFactory);
|
||||
assertSame(this.webClient, handlerAccessor.getPropertyValue("webClient"));
|
||||
Expression uriExpression = (Expression) handlerAccessor.getPropertyValue("uriExpression");
|
||||
assertEquals("http://localhost/test1", uriExpression.getValue());
|
||||
assertEquals(HttpMethod.POST.name(), TestUtils.getPropertyValue(handler, "httpMethodExpression", Expression.class).getExpressionString());
|
||||
assertEquals(HttpMethod.POST.name(),
|
||||
TestUtils.getPropertyValue(handler, "httpMethodExpression", Expression.class).getExpressionString());
|
||||
assertEquals(Charset.forName("UTF-8"), handlerAccessor.getPropertyValue("charset"));
|
||||
assertEquals(true, handlerAccessor.getPropertyValue("extractPayload"));
|
||||
assertEquals(false, handlerAccessor.getPropertyValue("transferCookies"));
|
||||
@@ -196,11 +199,11 @@ public class HttpOutboundGatewayParserTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void asyncFullConfig() {
|
||||
DirectFieldAccessor endpointAccessor = new DirectFieldAccessor(this.asyncFullConfigEndpoint);
|
||||
AsyncHttpRequestExecutingMessageHandler handler = (AsyncHttpRequestExecutingMessageHandler) endpointAccessor.getPropertyValue("handler");
|
||||
public void reactiveFullConfig() {
|
||||
DirectFieldAccessor endpointAccessor = new DirectFieldAccessor(this.reactiveFullConfigEndpoint);
|
||||
Object handler = endpointAccessor.getPropertyValue("handler");
|
||||
MessageChannel requestChannel = (MessageChannel) new DirectFieldAccessor(
|
||||
this.asyncFullConfigEndpoint).getPropertyValue("inputChannel");
|
||||
this.reactiveFullConfigEndpoint).getPropertyValue("inputChannel");
|
||||
assertEquals(this.applicationContext.getBean("requests"), requestChannel);
|
||||
DirectFieldAccessor handlerAccessor = new DirectFieldAccessor(handler);
|
||||
assertEquals(77, handlerAccessor.getPropertyValue("order"));
|
||||
@@ -208,24 +211,15 @@ public class HttpOutboundGatewayParserTests {
|
||||
Object replyChannel = handlerAccessor.getPropertyValue("outputChannel");
|
||||
assertNotNull(replyChannel);
|
||||
assertEquals(this.applicationContext.getBean("replies"), replyChannel);
|
||||
DirectFieldAccessor asyncTemplateAccessor = new DirectFieldAccessor(handlerAccessor.getPropertyValue("asyncRestTemplate"));
|
||||
DirectFieldAccessor syncTemplateAccessor = new DirectFieldAccessor(asyncTemplateAccessor.getPropertyValue("syncTemplate"));
|
||||
AsyncClientHttpRequestFactory requestFactory = (AsyncClientHttpRequestFactory)
|
||||
asyncTemplateAccessor.getPropertyValue("asyncRequestFactory");
|
||||
assertTrue(requestFactory instanceof SimpleClientHttpRequestFactory);
|
||||
Object converterListBean = this.applicationContext.getBean("converterList");
|
||||
assertEquals(converterListBean, syncTemplateAccessor.getPropertyValue("messageConverters"));
|
||||
|
||||
assertEquals(String.class.getName(), TestUtils.getPropertyValue(handler, "expectedResponseTypeExpression", Expression.class).getValue());
|
||||
assertEquals(String.class.getName(),
|
||||
TestUtils.getPropertyValue(handler, "expectedResponseTypeExpression", Expression.class).getValue());
|
||||
Expression uriExpression = (Expression) handlerAccessor.getPropertyValue("uriExpression");
|
||||
assertEquals("http://localhost/test2", uriExpression.getValue());
|
||||
assertEquals(HttpMethod.PUT.name(), TestUtils.getPropertyValue(handler, "httpMethodExpression", Expression.class).getExpressionString());
|
||||
assertEquals(HttpMethod.PUT.name(),
|
||||
TestUtils.getPropertyValue(handler, "httpMethodExpression", Expression.class).getExpressionString());
|
||||
assertEquals(Charset.forName("UTF-8"), handlerAccessor.getPropertyValue("charset"));
|
||||
assertEquals(false, handlerAccessor.getPropertyValue("extractPayload"));
|
||||
Object requestFactoryBean = this.applicationContext.getBean("testRequestFactory");
|
||||
assertEquals(requestFactoryBean, requestFactory);
|
||||
Object errorHandlerBean = this.applicationContext.getBean("testErrorHandler");
|
||||
assertEquals(errorHandlerBean, syncTemplateAccessor.getPropertyValue("errorHandler"));
|
||||
Object sendTimeout = new DirectFieldAccessor(
|
||||
handlerAccessor.getPropertyValue("messagingTemplate")).getPropertyValue("sendTimeout");
|
||||
assertEquals(new Long("1234"), sendTimeout);
|
||||
@@ -302,7 +296,6 @@ public class HttpOutboundGatewayParserTests {
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static class StubErrorHandler implements ResponseErrorHandler {
|
||||
|
||||
@Override
|
||||
@@ -324,4 +317,5 @@ public class HttpOutboundGatewayParserTests {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,16 +18,12 @@ package org.springframework.integration.http.dsl;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
|
||||
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -37,13 +33,15 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.reactive.ClientHttpConnector;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.config.EnableIntegration;
|
||||
import org.springframework.integration.dsl.IntegrationFlow;
|
||||
import org.springframework.integration.dsl.IntegrationFlows;
|
||||
import org.springframework.integration.http.outbound.AsyncHttpRequestExecutingMessageHandler;
|
||||
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
|
||||
import org.springframework.integration.http.outbound.ReactiveHttpRequestExecutingMessageHandler;
|
||||
import org.springframework.integration.security.channel.ChannelSecurityInterceptor;
|
||||
import org.springframework.integration.security.channel.SecuredChannel;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
@@ -58,16 +56,18 @@ import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.client.MockMvcClientHttpRequestFactory;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
import org.springframework.test.web.reactive.server.HttpHandlerConnector;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.AsyncRestTemplate;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Artem Bilan
|
||||
* @author Shiliang Li
|
||||
@@ -86,7 +86,7 @@ public class HttpDslTests {
|
||||
private HttpRequestExecutingMessageHandler serviceInternalGatewayHandler;
|
||||
|
||||
@Autowired
|
||||
private AsyncHttpRequestExecutingMessageHandler serviceInternalAsyncGatewayHandler;
|
||||
private ReactiveHttpRequestExecutingMessageHandler serviceInternalReactiveGatewayHandler;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@@ -115,16 +115,21 @@ public class HttpDslTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHttpAsyncProxyFlow() throws Exception {
|
||||
AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();
|
||||
String destinationUri = "http://www.springsource.org/spring-integration";
|
||||
MockRestServiceServer
|
||||
.createServer(asyncRestTemplate)
|
||||
.expect(requestTo(Matchers.startsWith(destinationUri)))
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
.andRespond(withSuccess("FOO", MediaType.TEXT_PLAIN));
|
||||
new DirectFieldAccessor(this.serviceInternalAsyncGatewayHandler)
|
||||
.setPropertyValue("asyncRestTemplate", asyncRestTemplate);
|
||||
public void testHttpReactiveProxyFlow() throws Exception {
|
||||
ClientHttpConnector httpConnector = new HttpHandlerConnector((request, response) -> {
|
||||
response.setStatusCode(HttpStatus.OK);
|
||||
response.getHeaders().setContentType(MediaType.TEXT_PLAIN);
|
||||
|
||||
return response.writeWith(Mono.just(response.bufferFactory().wrap("FOO".getBytes())))
|
||||
.then(response::setComplete);
|
||||
});
|
||||
|
||||
WebClient webClient = WebClient.builder()
|
||||
.clientConnector(httpConnector)
|
||||
.build();
|
||||
|
||||
new DirectFieldAccessor(this.serviceInternalReactiveGatewayHandler)
|
||||
.setPropertyValue("webClient", webClient);
|
||||
|
||||
this.mockMvc.perform(
|
||||
get("/service2")
|
||||
@@ -191,17 +196,18 @@ public class HttpDslTests {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow httpAsyncProxyFlow() {
|
||||
public IntegrationFlow httpReactiveProxyFlow() {
|
||||
return IntegrationFlows
|
||||
.from(Http.inboundGateway("/service2")
|
||||
.requestMapping(r -> r.params("name")))
|
||||
.handle(Http.<MultiValueMap<String, String>>outboundAsyncGateway(m ->
|
||||
.handle(Http.<MultiValueMap<String, String>>outboundReactiveGateway(m ->
|
||||
UriComponentsBuilder.fromUriString("http://www.springsource.org/spring-integration")
|
||||
.queryParams(m.getPayload())
|
||||
.build()
|
||||
.toUri())
|
||||
.httpMethod(HttpMethod.GET)
|
||||
.expectedResponseType(String.class),
|
||||
e -> e.id("serviceInternalAsyncGateway"))
|
||||
e -> e.id("serviceInternalReactiveGateway"))
|
||||
.get();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.http.outbound;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.dsl.channel.MessageChannels;
|
||||
import org.springframework.integration.http.HttpHeaders;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.test.web.client.MockRestServiceServer;
|
||||
import org.springframework.web.client.AsyncRestTemplate;
|
||||
|
||||
/**
|
||||
* @author Shiliang Li
|
||||
* @since 5.0
|
||||
*/
|
||||
public class AsyncHttpRequestExecutingMessageHandlerTests {
|
||||
|
||||
@Test
|
||||
public void testAsyncReturn() {
|
||||
AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();
|
||||
String destinationUri = "http://www.springsource.org/spring-integration";
|
||||
MockRestServiceServer
|
||||
.createServer(asyncRestTemplate)
|
||||
.expect(requestTo(destinationUri))
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
.andRespond(withSuccess());
|
||||
|
||||
AsyncHttpRequestExecutingMessageHandler asyncHandler = new AsyncHttpRequestExecutingMessageHandler(
|
||||
destinationUri,
|
||||
asyncRestTemplate);
|
||||
QueueChannel ackChannel = MessageChannels.queue().get();
|
||||
asyncHandler.setOutputChannel(ackChannel);
|
||||
asyncHandler.handleMessage(MessageBuilder.withPayload("hello, world").build());
|
||||
Message<?> ack = ackChannel.receive(1000);
|
||||
assertNotNull(ack);
|
||||
assertNotNull(ack.getHeaders());
|
||||
assertEquals(ack.getHeaders().get(HttpHeaders.STATUS_CODE), HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.http.outbound;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.client.reactive.ClientHttpConnector;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.channel.ReactiveChannel;
|
||||
import org.springframework.integration.http.HttpHeaders;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.ErrorMessage;
|
||||
import org.springframework.test.web.reactive.server.HttpHandlerConnector;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Shiliang Li
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
public class ReactiveHttpRequestExecutingMessageHandlerTests {
|
||||
|
||||
@Test
|
||||
public void testReactiveReturn() throws Throwable {
|
||||
ClientHttpConnector httpConnector = new HttpHandlerConnector((request, response) -> {
|
||||
response.setStatusCode(HttpStatus.OK);
|
||||
return Mono.empty()
|
||||
.then(response::setComplete);
|
||||
});
|
||||
|
||||
WebClient webClient = WebClient.builder()
|
||||
.clientConnector(httpConnector)
|
||||
.build();
|
||||
|
||||
String destinationUri = "http://www.springsource.org/spring-integration";
|
||||
ReactiveHttpRequestExecutingMessageHandler reactiveHandler =
|
||||
new ReactiveHttpRequestExecutingMessageHandler(destinationUri, webClient);
|
||||
|
||||
ReactiveChannel ackChannel = new ReactiveChannel();
|
||||
reactiveHandler.setOutputChannel(ackChannel);
|
||||
reactiveHandler.handleMessage(MessageBuilder.withPayload("hello, world").build());
|
||||
|
||||
Message<?> ack = Mono.from(ackChannel).block(Duration.ofSeconds(10));
|
||||
|
||||
assertNotNull(ack);
|
||||
assertNotNull(ack.getHeaders());
|
||||
assertEquals(ack.getHeaders().get(HttpHeaders.STATUS_CODE), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReactiveErrorOneWay() throws Throwable {
|
||||
ClientHttpConnector httpConnector = new HttpHandlerConnector((request, response) -> {
|
||||
response.setStatusCode(HttpStatus.UNAUTHORIZED);
|
||||
return Mono.empty()
|
||||
.then(response::setComplete);
|
||||
});
|
||||
|
||||
WebClient webClient = WebClient.builder()
|
||||
.clientConnector(httpConnector)
|
||||
.build();
|
||||
|
||||
String destinationUri = "http://www.springsource.org/spring-integration";
|
||||
ReactiveHttpRequestExecutingMessageHandler reactiveHandler =
|
||||
new ReactiveHttpRequestExecutingMessageHandler(destinationUri, webClient);
|
||||
reactiveHandler.setExpectReply(false);
|
||||
|
||||
QueueChannel errorChannel = new QueueChannel();
|
||||
reactiveHandler.handleMessage(MessageBuilder.withPayload("hello, world")
|
||||
.setErrorChannel(errorChannel)
|
||||
.build());
|
||||
|
||||
Message<?> errorMessage = errorChannel.receive(10000);
|
||||
|
||||
assertNotNull(errorMessage);
|
||||
assertThat(errorMessage, instanceOf(ErrorMessage.class));
|
||||
Throwable throwable = (Throwable) errorMessage.getPayload();
|
||||
assertThat(throwable.getMessage(), containsString("401 Unauthorized"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReactiveConnectErrorOneWay() throws Throwable {
|
||||
ClientHttpConnector httpConnector = new HttpHandlerConnector((request, response) -> {
|
||||
throw new RuntimeException("Intentional connection error");
|
||||
});
|
||||
|
||||
WebClient webClient = WebClient.builder()
|
||||
.clientConnector(httpConnector)
|
||||
.build();
|
||||
|
||||
String destinationUri = "http://www.springsource.org/spring-integration";
|
||||
ReactiveHttpRequestExecutingMessageHandler reactiveHandler =
|
||||
new ReactiveHttpRequestExecutingMessageHandler(destinationUri, webClient);
|
||||
reactiveHandler.setExpectReply(false);
|
||||
|
||||
QueueChannel errorChannel = new QueueChannel();
|
||||
reactiveHandler.handleMessage(MessageBuilder.withPayload("hello, world")
|
||||
.setErrorChannel(errorChannel)
|
||||
.build());
|
||||
|
||||
Message<?> errorMessage = errorChannel.receive(10000);
|
||||
|
||||
assertNotNull(errorMessage);
|
||||
assertThat(errorMessage, instanceOf(ErrorMessage.class));
|
||||
Throwable throwable = (Throwable) errorMessage.getPayload();
|
||||
assertThat(throwable.getMessage(), containsString("Intentional connection error"));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user