From 7690f06eadf7062afd3241cf4220eb99795fee34 Mon Sep 17 00:00:00 2001 From: Burak KALAYCI Date: Fri, 14 Aug 2026 16:43:06 +0300 Subject: [PATCH 1/6] GH-11268: Suppress RestTemplate removal warnings Fixes: https://github.com/spring-projects/spring-integration/issues/11268 Keep @SuppressWarnings("removal") on remaining RestTemplate-based HTTP outbound APIs until that client is removed. Move HTTP outbound tests onto RestClient instead of suppressing the old client in tests. Signed-off-by: Burak KALAYCI --- .../integration/http/dsl/Http.java | 10 + .../http/dsl/HttpMessageHandlerSpec.java | 5 + .../HttpRequestExecutingMessageHandler.java | 7 + .../http/HttpProxyScenarioTests.java | 131 +++++---- ...boundChannelAdapterParserTests-context.xml | 7 +- ...HttpOutboundChannelAdapterParserTests.java | 27 +- .../HttpOutboundGatewayParserTests.java | 1 + .../HttpOutboundWithinChainTests-context.xml | 11 +- ...tpRequestExecutingMessageHandlerTests.java | 252 ++++++++---------- 9 files changed, 220 insertions(+), 231 deletions(-) diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/dsl/Http.java b/spring-integration-http/src/main/java/org/springframework/integration/http/dsl/Http.java index bac05d8e123..6d74274b3b1 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/dsl/Http.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/dsl/Http.java @@ -37,6 +37,7 @@ * @author Artem Bilan * @author Shiliang Li * @author Arun Sethumadhavan + * @author Burak Kalayci * * @since 5.0 */ @@ -90,6 +91,7 @@ public static HttpMessageHandlerSpec outboundChannelAdapter(Expression uriExpres * @deprecated Since 7.1 in favor of {@link RestClient}-based configuration. */ @Deprecated(since = "7.1", forRemoval = true) + @SuppressWarnings("removal") public static HttpMessageHandlerSpec outboundChannelAdapter(URI uri, @Nullable RestTemplate restTemplate) { return outboundChannelAdapter(uri, toRestClient(restTemplate)); } @@ -115,6 +117,7 @@ public static HttpMessageHandlerSpec outboundChannelAdapter(URI uri, @Nullable R * @deprecated Since 7.1 in favor of {@link RestClient}-based configuration. */ @Deprecated(since = "7.1", forRemoval = true) + @SuppressWarnings("removal") public static HttpMessageHandlerSpec outboundChannelAdapter(String uri, @Nullable RestTemplate restTemplate) { return outboundChannelAdapter(uri, toRestClient(restTemplate)); } @@ -142,6 +145,7 @@ public static HttpMessageHandlerSpec outboundChannelAdapter(String uri, @Nullabl * @deprecated Since 7.1 in favor of {@link RestClient}-based configuration. */ @Deprecated(since = "7.1", forRemoval = true) + @SuppressWarnings("removal") public static

HttpMessageHandlerSpec outboundChannelAdapter(Function, ?> uriFunction, RestTemplate restTemplate) { @@ -174,6 +178,7 @@ public static

HttpMessageHandlerSpec outboundChannelAdapter(Function HttpMessageHandlerSpec outboundGateway(Function, ?> uriFunction, RestTemplate restTemplate) { @@ -327,6 +335,7 @@ public static

HttpMessageHandlerSpec outboundGateway(Function, ?> * @deprecated Since 7.1 in favor of {@link RestClient}-based configuration. */ @Deprecated(since = "7.1", forRemoval = true) + @SuppressWarnings("removal") public static HttpMessageHandlerSpec outboundGateway(Expression uriExpression, @Nullable RestTemplate restTemplate) { @@ -360,6 +369,7 @@ private static HttpMessageHandlerSpec outboundGatewaySpec(Expression uriExpressi return new HttpMessageHandlerSpec(uriExpression, restClient); } + @SuppressWarnings("removal") private static @Nullable RestClient toRestClient(@Nullable RestTemplate restTemplate) { return restTemplate != null ? RestClient.create(restTemplate) : null; } diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/dsl/HttpMessageHandlerSpec.java b/spring-integration-http/src/main/java/org/springframework/integration/http/dsl/HttpMessageHandlerSpec.java index 66280cc7926..ecd9c52ac1a 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/dsl/HttpMessageHandlerSpec.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/dsl/HttpMessageHandlerSpec.java @@ -42,6 +42,7 @@ * @author Oleksii Komlyk * @author Arun Sethumadhavan * @author Glenn Renfro + * @author Burak Kalayci * * @since 5.0 * @@ -56,6 +57,7 @@ public class HttpMessageHandlerSpec * @deprecated Since 7.1 in favor of {@link RestClient}-based configuration. */ @Deprecated(since = "7.1", forRemoval = true) + @SuppressWarnings("removal") protected HttpMessageHandlerSpec(URI uri, @Nullable RestTemplate restTemplate) { this(new ValueExpression<>(uri), restTemplate != null ? RestClient.create(restTemplate) : null); } @@ -64,6 +66,7 @@ protected HttpMessageHandlerSpec(URI uri, @Nullable RestTemplate restTemplate) { * @deprecated Since 7.1 in favor of {@link RestClient}-based configuration. */ @Deprecated(since = "7.1", forRemoval = true) + @SuppressWarnings("removal") protected HttpMessageHandlerSpec(String uri, @Nullable RestTemplate restTemplate) { this(new LiteralExpression(uri), restTemplate != null ? RestClient.create(restTemplate) : null); } @@ -72,6 +75,7 @@ protected HttpMessageHandlerSpec(String uri, @Nullable RestTemplate restTemplate * @deprecated Since 7.1 in favor of {@link RestClient}-based configuration. */ @Deprecated(since = "7.1", forRemoval = true) + @SuppressWarnings("removal") protected HttpMessageHandlerSpec(Expression uriExpression, @Nullable RestTemplate restTemplate) { this(uriExpression, restTemplate != null ? RestClient.create(restTemplate) : null); } @@ -109,6 +113,7 @@ public HttpMessageHandlerSpec requestFactory(ClientHttpRequestFactory requestFac * @deprecated Since 7.2 in favor of {@link RestClient.ResponseSpec.ErrorHandler}. */ @Deprecated(since = "7.2", forRemoval = true) + @SuppressWarnings("removal") public HttpMessageHandlerSpec errorHandler(ResponseErrorHandler errorHandler) { Assert.isTrue(!isClientSet(), "the 'errorHandler' must be specified on the provided client"); this.target.setErrorHandler(errorHandler); diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java b/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java index daf3536887b..af0d9384df8 100755 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java @@ -67,11 +67,13 @@ * @author Shiliang Li * @author Arun Sethumadhavan * @author Glenn Renfro + * @author Burak Kalayci * * @since 2.0 */ public class HttpRequestExecutingMessageHandler extends AbstractHttpRequestExecutingMessageHandler { + @SuppressWarnings("removal") private final @Nullable RestTemplate restTemplate; private volatile @Nullable RestClient restClient; @@ -113,6 +115,7 @@ public HttpRequestExecutingMessageHandler(Expression uriExpression) { * @deprecated Since 7.1 in favor of {@link RestClient}-based configuration. */ @Deprecated(since = "7.1", forRemoval = true) + @SuppressWarnings("removal") public HttpRequestExecutingMessageHandler(String uri, @Nullable RestTemplate restTemplate) { this(new LiteralExpression(uri), restTemplate); /* @@ -131,6 +134,7 @@ public HttpRequestExecutingMessageHandler(String uri, @Nullable RestTemplate res * @deprecated Since 7.1 in favor of {@link RestClient}-based configuration. */ @Deprecated(since = "7.1", forRemoval = true) + @SuppressWarnings("removal") public HttpRequestExecutingMessageHandler(Expression uriExpression, @Nullable RestTemplate restTemplate) { this(uriExpression, restTemplate, null); } @@ -162,6 +166,7 @@ public HttpRequestExecutingMessageHandler(Expression uriExpression, @Nullable Re this(uriExpression, null, restClient); } + @SuppressWarnings("removal") private HttpRequestExecutingMessageHandler(Expression uriExpression, @Nullable RestTemplate restTemplate, @Nullable RestClient restClient) { @@ -226,6 +231,7 @@ protected void doInit() { * @see RestTemplate#setErrorHandler(ResponseErrorHandler) */ @Deprecated(since = "7.2", forRemoval = true) + @SuppressWarnings("removal") public void setErrorHandler(ResponseErrorHandler errorHandler) { assertLocalClient("errorHandler"); RestClient.Builder localRestClientBuilder = this.localRestClientBuilder; @@ -325,6 +331,7 @@ public void setEncodingMode(DefaultUriBuilderFactory.EncodingMode encodingMode) } } + @SuppressWarnings("removal") private ResponseEntity exchangeWithRestTemplate(Object uri, HttpMethod httpMethod, HttpEntity httpRequest, Object expectedResponseType, Map uriVariables) { diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpProxyScenarioTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/HttpProxyScenarioTests.java index a6f95a7a729..6b7a88afdaa 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpProxyScenarioTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/HttpProxyScenarioTests.java @@ -16,23 +16,24 @@ package org.springframework.integration.http; +import java.net.URI; import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.Calendar; import java.util.Locale; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.function.Function; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; import org.springframework.beans.DirectFieldAccessor; -import org.springframework.beans.PropertyAccessor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler; @@ -45,7 +46,7 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestClient; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; @@ -54,11 +55,17 @@ import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * @author Artem Bilan * @author Gary Russell * @author Arun Sethumadhavan + * @author Burak Kalayci * * @since 3.0 */ @@ -115,31 +122,19 @@ public void testHttpProxyScenario() throws Exception { MockHttpServletResponse response = new MockHttpServletResponse(); - RestTemplate template = Mockito.spy(new RestTemplate()); - final String contentDispositionValue = "attachment; filename=\"test.txt\""; - Mockito.doAnswer(invocation -> { - String uri = invocation.getArgument(0); - assertThat(uri).isEqualTo("http://testServer/test?foo=bar&FOO=BAR"); - HttpEntity httpEntity = (HttpEntity) invocation.getArguments()[2]; - HttpHeaders httpHeaders = httpEntity.getHeaders(); - assertThat(httpHeaders.getIfModifiedSince()).isEqualTo(ifModifiedSince); - assertThat(httpHeaders.getFirst("If-Unmodified-Since")).isEqualTo(ifUnmodifiedSinceValue); - assertThat(httpHeaders.getFirst("Connection")).isEqualTo("Keep-Alive"); - - HttpHeaders responseHeaders = HttpHeaders.copyOf(httpHeaders); - responseHeaders.set("Connection", "close"); - responseHeaders.set("Content-Disposition", contentDispositionValue); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - }).when(template) - .exchange(Mockito.anyString(), Mockito.any(HttpMethod.class), - Mockito.any(HttpEntity.class), Mockito.>any(), Mockito.anyMap()); - - PropertyAccessor dfa = new DirectFieldAccessor(this.handler); - dfa.setPropertyValue("localRestClientBuilder", null); - dfa.setPropertyValue("restClient", null); - dfa.setPropertyValue("restTemplate", template); + injectRestClient(this.handler, httpEntity -> { + HttpHeaders httpHeaders = httpEntity.getHeaders(); + assertThat(httpHeaders.getIfModifiedSince()).isEqualTo(ifModifiedSince); + assertThat(httpHeaders.getFirst("If-Unmodified-Since")).isEqualTo(ifUnmodifiedSinceValue); + assertThat(httpHeaders.getFirst("Connection")).isEqualTo("Keep-Alive"); + + HttpHeaders responseHeaders = HttpHeaders.copyOf(httpHeaders); + responseHeaders.set("Connection", "close"); + responseHeaders.set("Content-Disposition", contentDispositionValue); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + }, uri -> assertThat(uri).isEqualTo("http://testServer/test?foo=bar&FOO=BAR")); RequestAttributes attributes = new ServletRequestAttributes(request); RequestContextHolder.setRequestAttributes(attributes); @@ -176,33 +171,21 @@ public void testHttpMultipartProxyScenario() throws Exception { MockHttpServletResponse response = new MockHttpServletResponse(); - RestTemplate template = Mockito.spy(new RestTemplate()); - Mockito.doAnswer(invocation -> { - String uri = invocation.getArgument(0); - assertThat(uri).isEqualTo("http://testServer/testmp"); - HttpEntity httpEntity = (HttpEntity) invocation.getArguments()[2]; - HttpHeaders httpHeaders = httpEntity.getHeaders(); - assertThat(httpHeaders.getFirst("Connection")).isEqualTo("Keep-Alive"); - assertThat(httpHeaders.getContentType().toString()) - .isEqualTo("multipart/form-data;boundary=----WebKitFormBoundarywABD2xqC1FLBijlQ"); - - HttpEntity entity = (HttpEntity) invocation.getArguments()[2]; - assertThat(entity.getBody()).isInstanceOf(MultiValueMap.class); - assertThat(((MultiValueMap) entity.getBody()).getFirst("foo")) - .isEqualTo("foo".getBytes()); - - HttpHeaders responseHeaders = HttpHeaders.copyOf(httpHeaders); - responseHeaders.set("Connection", "close"); - responseHeaders.set("Content-Type", "text/plain"); - return new ResponseEntity<>(responseHeaders, HttpStatus.OK); - }).when(template) - .exchange(Mockito.anyString(), Mockito.any(HttpMethod.class), - Mockito.any(HttpEntity.class), Mockito.>any(), Mockito.anyMap()); - - PropertyAccessor dfa = new DirectFieldAccessor(this.handlermp); - dfa.setPropertyValue("localRestClientBuilder", null); - dfa.setPropertyValue("restClient", null); - dfa.setPropertyValue("restTemplate", template); + injectRestClient(this.handlermp, httpEntity -> { + HttpHeaders httpHeaders = httpEntity.getHeaders(); + assertThat(httpHeaders.getFirst("Connection")).isEqualTo("Keep-Alive"); + assertThat(httpHeaders.getContentType().toString()) + .isEqualTo("multipart/form-data;boundary=----WebKitFormBoundarywABD2xqC1FLBijlQ"); + + assertThat(httpEntity.getBody()).isInstanceOf(MultiValueMap.class); + assertThat(((MultiValueMap) httpEntity.getBody()).getFirst("foo")) + .isEqualTo("foo".getBytes()); + + HttpHeaders responseHeaders = HttpHeaders.copyOf(httpHeaders); + responseHeaders.set("Connection", "close"); + responseHeaders.set("Content-Type", "text/plain"); + return new ResponseEntity<>(responseHeaders, HttpStatus.OK); + }, uri -> assertThat(uri).isEqualTo("http://testServer/testmp")); RequestAttributes attributes = new ServletRequestAttributes(request); RequestContextHolder.setRequestAttributes(attributes); @@ -215,4 +198,44 @@ public void testHttpMultipartProxyScenario() throws Exception { RequestContextHolder.resetRequestAttributes(); } + @SuppressWarnings("unchecked") + private static void injectRestClient(HttpRequestExecutingMessageHandler handler, + Function, ResponseEntity> exchange, + Consumer uriAsserter) { + + RestClient restClient = mock(RestClient.class); + RestClient.RequestBodyUriSpec spec = mock(RestClient.RequestBodyUriSpec.class); + RestClient.ResponseSpec responseSpec = mock(RestClient.ResponseSpec.class); + HttpHeaders headers = new HttpHeaders(); + AtomicReference body = new AtomicReference<>(); + AtomicReference> response = new AtomicReference<>(); + + when(restClient.method(any())).thenReturn(spec); + when(spec.uri(any(URI.class))).thenAnswer(invocation -> { + uriAsserter.accept(invocation.getArgument(0).toString()); + return spec; + }); + when(spec.uri(anyString(), anyMap())).thenAnswer(invocation -> { + uriAsserter.accept(invocation.getArgument(0)); + return spec; + }); + when(spec.headers(any())).thenAnswer(invocation -> { + Consumer headerConsumer = invocation.getArgument(0); + headerConsumer.accept(headers); + return spec; + }); + when(spec.body(any(Object.class))).thenAnswer(invocation -> { + body.set(invocation.getArgument(0)); + return spec; + }); + when(spec.retrieve()).thenAnswer(invocation -> { + response.set(exchange.apply(new HttpEntity<>(body.get(), headers))); + return responseSpec; + }); + when(responseSpec.toEntity(any(Class.class))).thenAnswer(invocation -> response.get()); + when(responseSpec.toBodilessEntity()).thenAnswer(invocation -> response.get()); + + new DirectFieldAccessor(handler).setPropertyValue("restClient", restClient); + } + } diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests-context.xml b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests-context.xml index 4556bfe5dda..1b4a57101c2 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests-context.xml +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests-context.xml @@ -14,11 +14,6 @@ - - - - @@ -50,7 +45,7 @@ + rest-client="customRestClient"/> diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java index bdbe0c80fc6..960aa7489f0 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java @@ -34,7 +34,6 @@ import org.springframework.http.HttpMethod; 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; @@ -48,7 +47,6 @@ import org.springframework.util.ObjectUtils; import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.RestClient; -import org.springframework.web.client.RestTemplate; import org.springframework.web.util.DefaultUriBuilderFactory; import static org.assertj.core.api.Assertions.assertThat; @@ -63,6 +61,7 @@ * @author Shiliang Li * @author Glenn Renfro * @author Arun Sethumadhavan + * @author Burak Kalayci */ @SpringJUnitConfig @DirtiesContext @@ -76,14 +75,6 @@ public class HttpOutboundChannelAdapterParserTests { @Qualifier("fullConfig") private AbstractEndpoint fullConfig; - @Autowired - @Qualifier("restTemplateConfig") - private AbstractEndpoint restTemplateConfig; - - @Autowired - @Qualifier("customRestTemplate") - private RestTemplate customRestTemplate; - @Autowired @Qualifier("restClientConfig") private AbstractEndpoint restClientConfig; @@ -182,13 +173,6 @@ public void fullConfig() { .isEqualTo(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY); } - @Test - public void restTemplateConfig() { - RestTemplate restTemplate = - TestUtils.getPropertyValue(this.restTemplateConfig, "handler.restTemplate"); - assertThat(restTemplate).isEqualTo(customRestTemplate); - } - @Test public void restClientConfig() { RestClient restClient = TestUtils.getPropertyValue(this.restClientConfig, "handler.restClient"); @@ -215,8 +199,8 @@ public void failWithRestTemplateAndRestClientAttributes() { @Test public void withUrlAndTemplate() { DirectFieldAccessor endpointAccessor = new DirectFieldAccessor(this.withUrlAndTemplate); - RestTemplate restTemplate = TestUtils.getPropertyValue(this.withUrlAndTemplate, "handler.restTemplate"); - assertThat(restTemplate).isSameAs(customRestTemplate); + RestClient restClient = TestUtils.getPropertyValue(this.withUrlAndTemplate, "handler.restClient"); + assertThat(restClient).isSameAs(this.customRestClient); HttpRequestExecutingMessageHandler handler = (HttpRequestExecutingMessageHandler) endpointAccessor .getPropertyValue("handler"); DirectFieldAccessor handlerAccessor = new DirectFieldAccessor(handler); @@ -224,11 +208,6 @@ public void withUrlAndTemplate() { assertThat(endpointAccessor.getPropertyValue("inputChannel")) .isEqualTo(this.applicationContext.getBean("requests")); assertThat(handlerAccessor.getPropertyValue("outputChannel")).isNull(); - DirectFieldAccessor templateAccessor = - new DirectFieldAccessor(handlerAccessor.getPropertyValue("restTemplate")); - ClientHttpRequestFactory requestFactory = (ClientHttpRequestFactory) - templateAccessor.getPropertyValue("requestFactory"); - assertThat(requestFactory instanceof SimpleClientHttpRequestFactory).isTrue(); Expression uriExpression = (Expression) handlerAccessor.getPropertyValue("uriExpression"); assertThat(uriExpression.getValue()).isEqualTo("http://localhost/test1"); assertThat(TestUtils.getPropertyValue(handler, "httpMethodExpression").getExpressionString()) diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java index 1c517c2b9ad..e932b0e30c9 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java @@ -60,6 +60,7 @@ * @author Biju Kunjummen * @author Glenn Renfro * @author Arun Sethumadhavan + * @author Burak Kalayci */ @SpringJUnitConfig @DirtiesContext diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpOutboundWithinChainTests-context.xml b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpOutboundWithinChainTests-context.xml index 01911c1df41..a42a7eedf4e 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpOutboundWithinChainTests-context.xml +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpOutboundWithinChainTests-context.xml @@ -9,16 +9,17 @@ http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> - + - + diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java index f281acdebac..acaf5146cd9 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java @@ -28,6 +28,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; import javax.xml.transform.Source; @@ -37,7 +38,6 @@ import reactor.core.publisher.Sinks; import reactor.test.StepVerifier; -import org.springframework.beans.DirectFieldAccessor; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.ParameterizedTypeReference; @@ -68,12 +68,8 @@ import org.springframework.mock.http.client.MockClientHttpRequest; import org.springframework.mock.http.client.MockClientHttpResponse; import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RequestCallback; -import org.springframework.web.client.ResourceAccessException; -import org.springframework.web.client.ResponseExtractor; import org.springframework.web.client.RestClient; import org.springframework.web.client.RestClientException; -import org.springframework.web.client.RestTemplate; import org.springframework.web.util.DefaultUriBuilderFactory; import static org.assertj.core.api.Assertions.assertThat; @@ -81,6 +77,8 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -93,6 +91,7 @@ * @author Florian Schöffl * @author Glenn Renfro * @author Arun Sethumadhavan + * @author Burak Kalayci */ public class HttpRequestExecutingMessageHandlerTests implements TestApplicationContextAware { @@ -113,10 +112,9 @@ void setUp() { @Test public void simpleStringKeyStringValueFormData() { + CapturingRestClient capturing = new CapturingRestClient(); HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler( - "https://www.springsource.org/spring-integration"); - MockRestTemplate template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); + "https://www.springsource.org/spring-integration", capturing.client()); handler.setHttpMethod(HttpMethod.POST); setBeanFactory(handler); handler.afterPropertiesSet(); @@ -136,7 +134,7 @@ public void simpleStringKeyStringValueFormData() { .isThrownBy(() -> handler.handleMessage(message)) .withStackTraceContaining("intentional"); - HttpEntity request = template.lastRequestEntity.get(); + HttpEntity request = capturing.lastRequestEntity(); Object body = request.getBody(); assertThat(request.getHeaders().getContentType()).isNotNull(); assertThat(body).isInstanceOf(MultiValueMap.class); @@ -151,10 +149,9 @@ public void simpleStringKeyStringValueFormData() { @Test public void simpleStringKeyObjectValueFormData() { + CapturingRestClient capturing = new CapturingRestClient(); HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler( - "https://www.springsource.org/spring-integration"); - MockRestTemplate template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); + "https://www.springsource.org/spring-integration", capturing.client()); handler.setHttpMethod(HttpMethod.POST); setBeanFactory(handler); handler.afterPropertiesSet(); @@ -170,7 +167,7 @@ public void simpleStringKeyObjectValueFormData() { .isThrownBy(() -> handler.handleMessage(message)) .withStackTraceContaining("intentional"); - HttpEntity request = template.lastRequestEntity.get(); + HttpEntity request = capturing.lastRequestEntity(); Object body = request.getBody(); assertThat(body instanceof MultiValueMap).isTrue(); MultiValueMap map = (MultiValueMap) body; @@ -182,10 +179,9 @@ public void simpleStringKeyObjectValueFormData() { @Test public void simpleObjectKeyObjectValueFormData() { + CapturingRestClient capturing = new CapturingRestClient(); HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler( - "https://www.springsource.org/spring-integration"); - MockRestTemplate template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); + "https://www.springsource.org/spring-integration", capturing.client()); handler.setHttpMethod(HttpMethod.POST); setBeanFactory(handler); handler.afterPropertiesSet(); @@ -201,7 +197,7 @@ public void simpleObjectKeyObjectValueFormData() { .isThrownBy(() -> handler.handleMessage(message)) .withStackTraceContaining("intentional"); - HttpEntity request = template.lastRequestEntity.get(); + HttpEntity request = capturing.lastRequestEntity(); Object body = request.getBody(); assertThat(body instanceof Map).isTrue(); Map map = (Map) body; @@ -213,10 +209,9 @@ public void simpleObjectKeyObjectValueFormData() { @Test public void stringKeyStringArrayValueFormData() { + CapturingRestClient capturing = new CapturingRestClient(); HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler( - "https://www.springsource.org/spring-integration"); - MockRestTemplate template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); + "https://www.springsource.org/spring-integration", capturing.client()); handler.setHttpMethod(HttpMethod.POST); setBeanFactory(handler); handler.afterPropertiesSet(); @@ -231,7 +226,7 @@ public void stringKeyStringArrayValueFormData() { .isThrownBy(() -> handler.handleMessage(message)) .withStackTraceContaining("intentional"); - HttpEntity request = template.lastRequestEntity.get(); + HttpEntity request = capturing.lastRequestEntity(); Object body = request.getBody(); assertThat(body instanceof MultiValueMap).isTrue(); MultiValueMap map = (MultiValueMap) body; @@ -258,10 +253,9 @@ public void stringKeyStringArrayValueFormData() { @Test public void stringKeyPrimitiveArrayValueMixedFormData() { + CapturingRestClient capturing = new CapturingRestClient(); HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler( - "https://www.springsource.org/spring-integration"); - MockRestTemplate template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); + "https://www.springsource.org/spring-integration", capturing.client()); handler.setHttpMethod(HttpMethod.POST); setBeanFactory(handler); handler.afterPropertiesSet(); @@ -276,7 +270,7 @@ public void stringKeyPrimitiveArrayValueMixedFormData() { .isThrownBy(() -> handler.handleMessage(message)) .withStackTraceContaining("intentional"); - HttpEntity request = template.lastRequestEntity.get(); + HttpEntity request = capturing.lastRequestEntity(); Object body = request.getBody(); assertThat(body instanceof MultiValueMap).isTrue(); MultiValueMap map = (MultiValueMap) body; @@ -306,10 +300,9 @@ public void stringKeyPrimitiveArrayValueMixedFormData() { @Test public void stringKeyNullArrayValueMixedFormData() { + CapturingRestClient capturing = new CapturingRestClient(); HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler( - "https://www.springsource.org/spring-integration"); - MockRestTemplate template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); + "https://www.springsource.org/spring-integration", capturing.client()); handler.setHttpMethod(HttpMethod.POST); setBeanFactory(handler); handler.afterPropertiesSet(); @@ -322,7 +315,7 @@ public void stringKeyNullArrayValueMixedFormData() { .isThrownBy(() -> handler.handleMessage(message)) .withStackTraceContaining("intentional"); - HttpEntity request = template.lastRequestEntity.get(); + HttpEntity request = capturing.lastRequestEntity(); Object body = request.getBody(); assertThat(body instanceof MultiValueMap).isTrue(); MultiValueMap map = (MultiValueMap) body; @@ -347,10 +340,9 @@ public void stringKeyNullArrayValueMixedFormData() { */ @Test public void stringKeyNullCollectionValueMixedFormDataString() { + CapturingRestClient capturing = new CapturingRestClient(); HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler( - "https://www.springsource.org/spring-integration"); - MockRestTemplate template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); + "https://www.springsource.org/spring-integration", capturing.client()); handler.setHttpMethod(HttpMethod.POST); setBeanFactory(handler); handler.afterPropertiesSet(); @@ -367,7 +359,7 @@ public void stringKeyNullCollectionValueMixedFormDataString() { .isThrownBy(() -> handler.handleMessage(message)) .withStackTraceContaining("intentional"); - HttpEntity request = template.lastRequestEntity.get(); + HttpEntity request = capturing.lastRequestEntity(); Object body = request.getBody(); assertThat(body instanceof MultiValueMap).isTrue(); MultiValueMap map = (MultiValueMap) body; @@ -391,10 +383,9 @@ public void stringKeyNullCollectionValueMixedFormDataString() { */ @Test public void stringKeyNullCollectionValueMixedFormDataObject() { + CapturingRestClient capturing = new CapturingRestClient(); HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler( - "https://www.springsource.org/spring-integration"); - MockRestTemplate template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); + "https://www.springsource.org/spring-integration", capturing.client()); handler.setHttpMethod(HttpMethod.POST); setBeanFactory(handler); handler.afterPropertiesSet(); @@ -411,7 +402,7 @@ public void stringKeyNullCollectionValueMixedFormDataObject() { .isThrownBy(() -> handler.handleMessage(message)) .withStackTraceContaining("intentional"); - HttpEntity request = template.lastRequestEntity.get(); + HttpEntity request = capturing.lastRequestEntity(); Object body = request.getBody(); assertThat(body instanceof MultiValueMap).isTrue(); MultiValueMap map = (MultiValueMap) body; @@ -431,10 +422,9 @@ public void stringKeyNullCollectionValueMixedFormDataObject() { @Test public void stringKeyStringCollectionValueFormData() { + CapturingRestClient capturing = new CapturingRestClient(); HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler( - "https://www.springsource.org/spring-integration"); - MockRestTemplate template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); + "https://www.springsource.org/spring-integration", capturing.client()); handler.setHttpMethod(HttpMethod.POST); setBeanFactory(handler); handler.afterPropertiesSet(); @@ -451,7 +441,7 @@ public void stringKeyStringCollectionValueFormData() { .isThrownBy(() -> handler.handleMessage(message)) .withStackTraceContaining("intentional"); - HttpEntity request = template.lastRequestEntity.get(); + HttpEntity request = capturing.lastRequestEntity(); Object body = request.getBody(); assertThat(body instanceof MultiValueMap).isTrue(); MultiValueMap map = (MultiValueMap) body; @@ -473,10 +463,9 @@ public void stringKeyStringCollectionValueFormData() { @Test public void stringKeyObjectCollectionValueFormData() { + CapturingRestClient capturing = new CapturingRestClient(); HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler( - "https://www.springsource.org/spring-integration"); - MockRestTemplate template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); + "https://www.springsource.org/spring-integration", capturing.client()); handler.setHttpMethod(HttpMethod.POST); setBeanFactory(handler); handler.afterPropertiesSet(); @@ -493,7 +482,7 @@ public void stringKeyObjectCollectionValueFormData() { .isThrownBy(() -> handler.handleMessage(message)) .withStackTraceContaining("intentional"); - HttpEntity request = template.lastRequestEntity.get(); + HttpEntity request = capturing.lastRequestEntity(); Object body = request.getBody(); assertThat(body instanceof MultiValueMap).isTrue(); MultiValueMap map = (MultiValueMap) body; @@ -515,10 +504,9 @@ public void stringKeyObjectCollectionValueFormData() { @Test public void nameOnlyWithNullValues() { + CapturingRestClient capturing = new CapturingRestClient(); HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler( - "https://www.springsource.org/spring-integration"); - MockRestTemplate template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); + "https://www.springsource.org/spring-integration", capturing.client()); handler.setHttpMethod(HttpMethod.POST); setBeanFactory(handler); handler.afterPropertiesSet(); @@ -532,7 +520,7 @@ public void nameOnlyWithNullValues() { .isThrownBy(() -> handler.handleMessage(message)) .withStackTraceContaining("intentional"); - HttpEntity request = template.lastRequestEntity.get(); + HttpEntity request = capturing.lastRequestEntity(); Object body = request.getBody(); assertThat(body instanceof MultiValueMap).isTrue(); MultiValueMap map = (MultiValueMap) body; @@ -549,10 +537,9 @@ public void nameOnlyWithNullValues() { @Test public void contentAsByteArray() { + CapturingRestClient capturing = new CapturingRestClient(); HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler( - "https://www.springsource.org/spring-integration"); - MockRestTemplate template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); + "https://www.springsource.org/spring-integration", capturing.client()); handler.setHttpMethod(HttpMethod.POST); setBeanFactory(handler); handler.afterPropertiesSet(); @@ -564,7 +551,7 @@ public void contentAsByteArray() { .isThrownBy(() -> handler.handleMessage(message)) .withStackTraceContaining("intentional"); - HttpEntity request = template.lastRequestEntity.get(); + HttpEntity request = capturing.lastRequestEntity(); Object body = request.getBody(); assertThat(body).asInstanceOf(InstanceOfAssertFactories.BYTE_ARRAY).isEqualTo(bytes); assertThat(request.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_OCTET_STREAM); @@ -572,10 +559,9 @@ public void contentAsByteArray() { @Test public void contentAsXmlSource() { + CapturingRestClient capturing = new CapturingRestClient(); HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler( - "https://www.springsource.org/spring-integration"); - MockRestTemplate template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); + "https://www.springsource.org/spring-integration", capturing.client()); handler.setHttpMethod(HttpMethod.POST); setBeanFactory(handler); handler.afterPropertiesSet(); @@ -586,7 +572,7 @@ public void contentAsXmlSource() { .isThrownBy(() -> handler.handleMessage(message)) .withStackTraceContaining("intentional"); - HttpEntity request = template.lastRequestEntity.get(); + HttpEntity request = capturing.lastRequestEntity(); Object body = request.getBody(); assertThat(body).isInstanceOf(Source.class); assertThat(request.getHeaders().getContentType()).isEqualTo(MediaType.TEXT_XML); @@ -598,8 +584,6 @@ public void testWarnMessageForNonPostPutAndExtractPayload() { HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler( "https://www.springsource.org/spring-integration"); - MockRestTemplate template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); handler.setHttpMethod(HttpMethod.GET); handler.setExtractPayload(true); setBeanFactory(handler); @@ -608,8 +592,6 @@ public void testWarnMessageForNonPostPutAndExtractPayload() { // should not see a warn message since 'setExtractPayload' is not set explicitly handler = new HttpRequestExecutingMessageHandler("https://www.springsource.org/spring-integration"); - template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); handler.setHttpMethod(HttpMethod.GET); setBeanFactory(handler); handler.afterPropertiesSet(); @@ -617,8 +599,6 @@ public void testWarnMessageForNonPostPutAndExtractPayload() { // should not see a warn message since HTTP method is not GET handler = new HttpRequestExecutingMessageHandler("https://www.springsource.org/spring-integration"); - template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); handler.setHttpMethod(HttpMethod.POST); handler.setExtractPayload(true); setBeanFactory(handler); @@ -628,10 +608,10 @@ public void testWarnMessageForNonPostPutAndExtractPayload() { @Test public void contentTypeIsNotSetForGetAndHeadRequest() { // GET + CapturingRestClient capturing = new CapturingRestClient(); HttpRequestExecutingMessageHandler handler = - new HttpRequestExecutingMessageHandler("https://www.springsource.org/spring-integration"); - MockRestTemplate template = new MockRestTemplate(); - setRestTemplateForTesting(handler, template); + new HttpRequestExecutingMessageHandler("https://www.springsource.org/spring-integration", + capturing.client()); handler.setHttpMethod(HttpMethod.GET); setBeanFactory(handler); handler.afterPropertiesSet(); @@ -640,7 +620,7 @@ public void contentTypeIsNotSetForGetAndHeadRequest() { .isThrownBy(() -> handler.handleMessage(MessageBuilder.withPayload(mock(Source.class)).build())) .withStackTraceContaining("intentional"); - assertThat(template.lastRequestEntity.get().getHeaders().getContentType()).isNull(); + assertThat(capturing.lastRequestEntity().getHeaders().getContentType()).isNull(); //HEAD handler.setHttpMethod(HttpMethod.HEAD); @@ -649,7 +629,7 @@ public void contentTypeIsNotSetForGetAndHeadRequest() { .isThrownBy(() -> handler.handleMessage(MessageBuilder.withPayload(mock(Source.class)).build())) .withStackTraceContaining("intentional"); - assertThat(template.lastRequestEntity.get().getHeaders().getContentType()).isNull(); + assertThat(capturing.lastRequestEntity().getHeaders().getContentType()).isNull(); //DELETE handler.setHttpMethod(HttpMethod.DELETE); @@ -658,7 +638,7 @@ public void contentTypeIsNotSetForGetAndHeadRequest() { .isThrownBy(() -> handler.handleMessage(MessageBuilder.withPayload(mock(Source.class)).build())) .withStackTraceContaining("intentional"); - assertThat(template.lastRequestEntity.get().getHeaders().getContentType()).isEqualTo(MediaType.TEXT_XML); + assertThat(capturing.lastRequestEntity().getHeaders().getContentType()).isEqualTo(MediaType.TEXT_XML); //TRACE handler.setHttpMethod(HttpMethod.TRACE); @@ -667,7 +647,7 @@ public void contentTypeIsNotSetForGetAndHeadRequest() { .isThrownBy(() -> handler.handleMessage(MessageBuilder.withPayload(mock(Source.class)).build())) .withStackTraceContaining("intentional"); - assertThat(template.lastRequestEntity.get().getHeaders().getContentType()).isNull(); + assertThat(capturing.lastRequestEntity().getHeaders().getContentType()).isNull(); } @Test @@ -762,10 +742,10 @@ public void testOutboundChannelAdapterWithinChain() { ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext( "HttpOutboundWithinChainTests-context.xml", this.getClass()); MessageChannel channel = ctx.getBean("httpOutboundChannelAdapterWithinChain", MessageChannel.class); - MockRestTemplate2 restTemplate = ctx.getBean("restTemplate", MockRestTemplate2.class); + CapturingRequestFactory requestFactory = ctx.getBean("requestFactory", CapturingRequestFactory.class); channel.send(MessageBuilder.withPayload("test").build()); - assertThat(restTemplate.actualUrl.get()).isEqualTo("http://localhost/test1/%2f"); + assertThat(requestFactory.actualUrl.get()).hasToString("http://localhost/test1/%2f"); HttpRequestExecutingMessageHandler handler = ctx.getBean("chain$child.adapter.handler", HttpRequestExecutingMessageHandler.class); @@ -779,25 +759,28 @@ public void testHttpOutboundGatewayWithinChain() { ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext( "HttpOutboundWithinChainTests-context.xml", this.getClass()); MessageChannel channel = ctx.getBean("httpOutboundGatewayWithinChain", MessageChannel.class); - MockRestTemplate2 restTemplate = ctx.getBean("restTemplate", MockRestTemplate2.class); + CapturingRequestFactory requestFactory = ctx.getBean("requestFactory", CapturingRequestFactory.class); channel.send(MessageBuilder.withPayload("test").build()); PollableChannel output = ctx.getBean("replyChannel", PollableChannel.class); Message receive = output.receive(); assertThat(((ResponseEntity) receive.getPayload()).getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(restTemplate.actualUrl.get()) - .isEqualTo("http://localhost:51235/%2f/testApps?param=http+Outbound+Gateway+Within+Chain"); + assertThat(requestFactory.actualUrl.get()) + .hasToString("http://localhost:51235/%2f/testApps?param=http+Outbound+Gateway+Within+Chain"); ctx.close(); } @Test - @SuppressWarnings("removal") public void testUriExpression() { - MockRestTemplate restTemplate = new MockRestTemplate(); + AtomicReference actualUri = new AtomicReference<>(); HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler( - new SpelExpressionParser().parseExpression("headers['foo']"), restTemplate); + new SpelExpressionParser().parseExpression("headers['foo']")); + handler.setRequestFactory((uri, httpMethod) -> { + actualUri.set(uri); + throw new RuntimeException("intentional"); + }); setBeanFactory(handler); handler.afterPropertiesSet(); String theURL = "https://bar/baz?foo#bar"; @@ -806,7 +789,7 @@ public void testUriExpression() { assertThatException() .isThrownBy(() -> handler.handleMessage(message)); - assertThat(restTemplate.actualUrl.get()).isEqualTo(theURL); + assertThat(actualUri.get()).hasToString(theURL); } @Test @@ -923,31 +906,21 @@ public void acceptHeaderForSerializableResponseMessageExchange() throws IOExcept } @Test - @SuppressWarnings("removal") public void testNoContentTypeAndSmartConverter() { Sinks.One httpHeadersSink = Sinks.one(); - RestTemplate testRestTemplate = new RestTemplate() { - - protected T doExecute(URI url, String uriTemplate, HttpMethod method, - RequestCallback requestCallback, ResponseExtractor responseExtractor) - throws RestClientException { - - try { - ClientHttpRequest request = createRequest(url, method); - requestCallback.doWithRequest(request); - httpHeadersSink.tryEmitValue(request.getHeaders()); - } - catch (IOException e) { - throw new RestClientException("Not possible", e); - } - throw new RuntimeException("intentional"); - } - - }; HttpRequestExecutingMessageHandler handler = - new HttpRequestExecutingMessageHandler("https://www.springsource.org/spring-integration", - testRestTemplate); + new HttpRequestExecutingMessageHandler("https://www.springsource.org/spring-integration"); + handler.setRequestFactory((uri, httpMethod) -> + new MockClientHttpRequest(httpMethod, uri) { + + @Override + protected ClientHttpResponse executeInternal() { + httpHeadersSink.tryEmitValue(getHeaders()); + throw new RuntimeException("intentional"); + } + + }); setBeanFactory(handler); handler.afterPropertiesSet(); @@ -966,15 +939,6 @@ private static void setBeanFactory(HttpRequestExecutingMessageHandler handler) { handler.setBeanFactory(TEST_INTEGRATION_CONTEXT); } - private static void setRestTemplateForTesting(HttpRequestExecutingMessageHandler handler, - RestTemplate restTemplate) { - - DirectFieldAccessor accessor = new DirectFieldAccessor(handler); - accessor.setPropertyValue("localRestClientBuilder", null); - accessor.setPropertyValue("restClient", null); - accessor.setPropertyValue("restTemplate", restTemplate); - } - private static HttpHeaders setUpMocksToCaptureSentHeaders(HttpRequestExecutingMessageHandler handler) throws IOException { @@ -1010,46 +974,50 @@ public String toString() { } - private static class MockRestTemplate extends RestTemplate { - - private final AtomicReference> lastRequestEntity = new AtomicReference<>(); - - private final AtomicReference actualUrl = new AtomicReference<>(); - - protected T doExecute(URI url, String uriTemplate, HttpMethod method, - RequestCallback requestCallback, ResponseExtractor responseExtractor) - throws RestClientException { + private static final class CapturingRestClient { + + private final HttpHeaders headers = new HttpHeaders(); + + private final AtomicReference body = new AtomicReference<>(); + + private RestClient client() { + RestClient restClient = mock(RestClient.class); + RestClient.RequestBodyUriSpec spec = mock(RestClient.RequestBodyUriSpec.class); + + when(restClient.method(any())).thenReturn(spec); + when(spec.uri(any(URI.class))).thenReturn(spec); + when(spec.uri(anyString(), anyMap())).thenReturn(spec); + when(spec.headers(any())).thenAnswer(invocation -> { + this.headers.clear(); + this.body.set(null); + Consumer headerConsumer = invocation.getArgument(0); + headerConsumer.accept(this.headers); + return spec; + }); + when(spec.body(any(Object.class))).thenAnswer(invocation -> { + this.body.set(invocation.getArgument(0)); + return spec; + }); + when(spec.retrieve()).thenThrow(new RuntimeException("intentional")); + return restClient; + } - this.actualUrl.set(url.toString()); - this.lastRequestEntity.set(TestUtils.getPropertyValue(requestCallback, "requestEntity")); - throw new RuntimeException("intentional"); + private HttpEntity lastRequestEntity() { + return new HttpEntity<>(this.body.get(), this.headers); } } - @SuppressWarnings("unused") - private static class MockRestTemplate2 extends RestTemplate { - - private final AtomicReference actualUrl = new AtomicReference<>(); + public static final class CapturingRequestFactory implements ClientHttpRequestFactory { - MockRestTemplate2() { - DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(); - uriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE); - setUriTemplateHandler(uriBuilderFactory); - } + public final AtomicReference actualUrl = new AtomicReference<>(); - protected T doExecute(URI url, String uriTemplate, HttpMethod method, - RequestCallback requestCallback, ResponseExtractor responseExtractor) - throws RestClientException { - - this.actualUrl.set(url.toString()); - try { - return responseExtractor.extractData(new MockClientHttpResponse(new byte[0], HttpStatus.OK)); - } - catch (IOException ex) { - throw new ResourceAccessException("I/O error on " + method.name() + - " request for \"" + url + "\": " + ex.getMessage(), ex); - } + @Override + public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) { + this.actualUrl.set(uri); + MockClientHttpRequest request = new MockClientHttpRequest(httpMethod, uri); + request.setResponse(new MockClientHttpResponse(new byte[0], HttpStatus.OK)); + return request; } } From aac674b6b86a8e3bdc217eceda7f0f092d28069c Mon Sep 17 00:00:00 2001 From: Burak KALAYCI Date: Mon, 24 Aug 2026 20:53:48 +0300 Subject: [PATCH 2/6] GH-11268: Use FQCN for deprecated RestTemplate Avoid the IDE warning on the RestTemplate import. Use mock() without args in proxy tests and restore the parser test that only added an author tag. Signed-off-by: Burak KALAYCI --- .../integration/http/dsl/Http.java | 56 ++++++++++--------- .../http/HttpProxyScenarioTests.java | 6 +- .../HttpOutboundGatewayParserTests.java | 1 - 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/dsl/Http.java b/spring-integration-http/src/main/java/org/springframework/integration/http/dsl/Http.java index 6d74274b3b1..96e47412aa0 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/dsl/Http.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/dsl/Http.java @@ -29,7 +29,6 @@ import org.springframework.messaging.Message; import org.springframework.util.Assert; import org.springframework.web.client.RestClient; -import org.springframework.web.client.RestTemplate; /** * The HTTP components Factory. @@ -84,15 +83,16 @@ public static HttpMessageHandlerSpec outboundChannelAdapter(Expression uriExpres /** * Create an {@link HttpMessageHandlerSpec} builder for one-way adapter - * based on provided {@link URI} and {@link RestTemplate}. + * based on provided {@link URI} and {@link org.springframework.web.client.RestTemplate}. * @param uri the {@link URI} to send requests. - * @param restTemplate {@link RestTemplate} to use. + * @param restTemplate {@link org.springframework.web.client.RestTemplate} to use. * @return the HttpMessageHandlerSpec instance * @deprecated Since 7.1 in favor of {@link RestClient}-based configuration. */ @Deprecated(since = "7.1", forRemoval = true) @SuppressWarnings("removal") - public static HttpMessageHandlerSpec outboundChannelAdapter(URI uri, @Nullable RestTemplate restTemplate) { + public static HttpMessageHandlerSpec outboundChannelAdapter(URI uri, + org.springframework.web.client.@Nullable RestTemplate restTemplate) { return outboundChannelAdapter(uri, toRestClient(restTemplate)); } @@ -110,15 +110,16 @@ public static HttpMessageHandlerSpec outboundChannelAdapter(URI uri, @Nullable R /** * Create an {@link HttpMessageHandlerSpec} builder for one-way adapter - * based on provided {@code uri} and {@link RestTemplate}. + * based on provided {@code uri} and {@link org.springframework.web.client.RestTemplate}. * @param uri the {@code uri} to send requests. - * @param restTemplate {@link RestTemplate} to use. + * @param restTemplate {@link org.springframework.web.client.RestTemplate} to use. * @return the HttpMessageHandlerSpec instance * @deprecated Since 7.1 in favor of {@link RestClient}-based configuration. */ @Deprecated(since = "7.1", forRemoval = true) @SuppressWarnings("removal") - public static HttpMessageHandlerSpec outboundChannelAdapter(String uri, @Nullable RestTemplate restTemplate) { + public static HttpMessageHandlerSpec outboundChannelAdapter(String uri, + org.springframework.web.client.@Nullable RestTemplate restTemplate) { return outboundChannelAdapter(uri, toRestClient(restTemplate)); } @@ -137,9 +138,9 @@ public static HttpMessageHandlerSpec outboundChannelAdapter(String uri, @Nullabl /** * Create an {@link HttpMessageHandlerSpec} builder for one-way adapter * based on provided {@code Function} to evaluate target {@code uri} against request message - * and {@link RestTemplate} for HTTP exchanges. + * and {@link org.springframework.web.client.RestTemplate} for HTTP exchanges. * @param uriFunction the {@code Function} to evaluate {@code uri} at runtime. - * @param restTemplate {@link RestTemplate} to use. + * @param restTemplate {@link org.springframework.web.client.RestTemplate} to use. * @param

the expected payload type. * @return the HttpMessageHandlerSpec instance * @deprecated Since 7.1 in favor of {@link RestClient}-based configuration. @@ -147,7 +148,7 @@ public static HttpMessageHandlerSpec outboundChannelAdapter(String uri, @Nullabl @Deprecated(since = "7.1", forRemoval = true) @SuppressWarnings("removal") public static

HttpMessageHandlerSpec outboundChannelAdapter(Function, ?> uriFunction, - RestTemplate restTemplate) { + org.springframework.web.client.RestTemplate restTemplate) { return outboundChannelAdapter(new FunctionExpression<>(uriFunction), toRestClient(restTemplate)); } @@ -171,16 +172,16 @@ public static

HttpMessageHandlerSpec outboundChannelAdapter(Function the expected payload type. * @return the HttpMessageHandlerSpec instance * @deprecated Since 7.1 in favor of {@link RestClient}-based configuration. @@ -304,7 +307,7 @@ public static HttpMessageHandlerSpec outboundGateway(String uri, @Nullable RestC @Deprecated(since = "7.1", forRemoval = true) @SuppressWarnings("removal") public static

HttpMessageHandlerSpec outboundGateway(Function, ?> uriFunction, - RestTemplate restTemplate) { + org.springframework.web.client.RestTemplate restTemplate) { return outboundGateway(new FunctionExpression<>(uriFunction), toRestClient(restTemplate)); } @@ -328,16 +331,16 @@ public static

HttpMessageHandlerSpec outboundGateway(Function, ?> /** * Create an {@link HttpMessageHandlerSpec} builder for request-reply gateway * based on provided SpEL {@link Expression} to evaluate target {@code uri} - * against request message and {@link RestTemplate} for HTTP exchanges. + * against request message and {@link org.springframework.web.client.RestTemplate} for HTTP exchanges. * @param uriExpression the SpEL {@link Expression} to evaluate {@code uri} at runtime. - * @param restTemplate {@link RestTemplate} to use. + * @param restTemplate {@link org.springframework.web.client.RestTemplate} to use. * @return the HttpMessageHandlerSpec instance * @deprecated Since 7.1 in favor of {@link RestClient}-based configuration. */ @Deprecated(since = "7.1", forRemoval = true) @SuppressWarnings("removal") public static HttpMessageHandlerSpec outboundGateway(Expression uriExpression, - @Nullable RestTemplate restTemplate) { + org.springframework.web.client.@Nullable RestTemplate restTemplate) { return outboundGateway(uriExpression, toRestClient(restTemplate)); } @@ -370,7 +373,8 @@ private static HttpMessageHandlerSpec outboundGatewaySpec(Expression uriExpressi } @SuppressWarnings("removal") - private static @Nullable RestClient toRestClient(@Nullable RestTemplate restTemplate) { + private static @Nullable RestClient toRestClient( + org.springframework.web.client.@Nullable RestTemplate restTemplate) { return restTemplate != null ? RestClient.create(restTemplate) : null; } diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpProxyScenarioTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/HttpProxyScenarioTests.java index 6b7a88afdaa..359c9e259b6 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpProxyScenarioTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/HttpProxyScenarioTests.java @@ -203,9 +203,9 @@ private static void injectRestClient(HttpRequestExecutingMessageHandler handler, Function, ResponseEntity> exchange, Consumer uriAsserter) { - RestClient restClient = mock(RestClient.class); - RestClient.RequestBodyUriSpec spec = mock(RestClient.RequestBodyUriSpec.class); - RestClient.ResponseSpec responseSpec = mock(RestClient.ResponseSpec.class); + RestClient restClient = mock(); + RestClient.RequestBodyUriSpec spec = mock(); + RestClient.ResponseSpec responseSpec = mock(); HttpHeaders headers = new HttpHeaders(); AtomicReference body = new AtomicReference<>(); AtomicReference> response = new AtomicReference<>(); diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java index e932b0e30c9..1c517c2b9ad 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java @@ -60,7 +60,6 @@ * @author Biju Kunjummen * @author Glenn Renfro * @author Arun Sethumadhavan - * @author Burak Kalayci */ @SpringJUnitConfig @DirtiesContext From 2c8f9c7239533d1ccfbc66ff8d727dd58bf93ae5 Mon Sep 17 00:00:00 2001 From: Burak KALAYCI Date: Mon, 24 Aug 2026 21:38:08 +0300 Subject: [PATCH 3/6] GH-11268: Use FQCN on HttpMessageHandlerSpec too Drop RestTemplate and ResponseErrorHandler imports so the IDE does not flag those deprecated types. Signed-off-by: Burak KALAYCI --- .../http/dsl/HttpMessageHandlerSpec.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/dsl/HttpMessageHandlerSpec.java b/spring-integration-http/src/main/java/org/springframework/integration/http/dsl/HttpMessageHandlerSpec.java index ecd9c52ac1a..a8d652bed49 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/dsl/HttpMessageHandlerSpec.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/dsl/HttpMessageHandlerSpec.java @@ -30,9 +30,7 @@ import org.springframework.integration.expression.ValueExpression; import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler; import org.springframework.util.Assert; -import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.RestClient; -import org.springframework.web.client.RestTemplate; /** * The {@link BaseHttpMessageHandlerSpec} implementation for the {@link HttpRequestExecutingMessageHandler}. @@ -58,7 +56,7 @@ public class HttpMessageHandlerSpec */ @Deprecated(since = "7.1", forRemoval = true) @SuppressWarnings("removal") - protected HttpMessageHandlerSpec(URI uri, @Nullable RestTemplate restTemplate) { + protected HttpMessageHandlerSpec(URI uri, org.springframework.web.client.@Nullable RestTemplate restTemplate) { this(new ValueExpression<>(uri), restTemplate != null ? RestClient.create(restTemplate) : null); } @@ -67,7 +65,7 @@ protected HttpMessageHandlerSpec(URI uri, @Nullable RestTemplate restTemplate) { */ @Deprecated(since = "7.1", forRemoval = true) @SuppressWarnings("removal") - protected HttpMessageHandlerSpec(String uri, @Nullable RestTemplate restTemplate) { + protected HttpMessageHandlerSpec(String uri, org.springframework.web.client.@Nullable RestTemplate restTemplate) { this(new LiteralExpression(uri), restTemplate != null ? RestClient.create(restTemplate) : null); } @@ -76,7 +74,8 @@ protected HttpMessageHandlerSpec(String uri, @Nullable RestTemplate restTemplate */ @Deprecated(since = "7.1", forRemoval = true) @SuppressWarnings("removal") - protected HttpMessageHandlerSpec(Expression uriExpression, @Nullable RestTemplate restTemplate) { + protected HttpMessageHandlerSpec(Expression uriExpression, + org.springframework.web.client.@Nullable RestTemplate restTemplate) { this(uriExpression, restTemplate != null ? RestClient.create(restTemplate) : null); } @@ -94,7 +93,8 @@ protected HttpMessageHandlerSpec(Expression uriExpression, @Nullable RestClient } /** - * Set the {@link ClientHttpRequestFactory} for the underlying {@link RestTemplate}. + * Set the {@link ClientHttpRequestFactory} for the underlying + * {@link org.springframework.web.client.RestTemplate}. * @param requestFactory The request factory. * @return the spec * @deprecated Since 7.2 in favor of {@link RestClient}-based configuration. @@ -107,14 +107,16 @@ public HttpMessageHandlerSpec requestFactory(ClientHttpRequestFactory requestFac } /** - * Set the {@link ResponseErrorHandler} for the underlying {@link RestTemplate}. + * Set the {@link org.springframework.web.client.ResponseErrorHandler} for the underlying + * {@link org.springframework.web.client.RestTemplate}. * @param errorHandler The error handler. * @return the spec * @deprecated Since 7.2 in favor of {@link RestClient.ResponseSpec.ErrorHandler}. */ @Deprecated(since = "7.2", forRemoval = true) @SuppressWarnings("removal") - public HttpMessageHandlerSpec errorHandler(ResponseErrorHandler errorHandler) { + public HttpMessageHandlerSpec errorHandler( + org.springframework.web.client.ResponseErrorHandler errorHandler) { Assert.isTrue(!isClientSet(), "the 'errorHandler' must be specified on the provided client"); this.target.setErrorHandler(errorHandler); return _this(); From b198c2a8977cc3793d8e8121a210c1431d7a6884 Mon Sep 17 00:00:00 2001 From: Burak KALAYCI Date: Mon, 24 Aug 2026 22:55:00 +0300 Subject: [PATCH 4/6] GH-11268: Use FQCN on HttpRequestExecutingMessageHandler Drop RestTemplate and ResponseErrorHandler imports so the IDE does not flag those deprecated types. Signed-off-by: Burak KALAYCI --- .../HttpRequestExecutingMessageHandler.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java b/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java index af0d9384df8..bc4dfac7616 100755 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java @@ -37,16 +37,14 @@ import org.springframework.messaging.Message; import org.springframework.messaging.MessageHandlingException; import org.springframework.util.Assert; -import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.RestClient; import org.springframework.web.client.RestClientException; -import org.springframework.web.client.RestTemplate; import org.springframework.web.util.DefaultUriBuilderFactory; /** * A {@link org.springframework.messaging.MessageHandler} * implementation that executes HTTP requests by delegating - * to a {@link RestClient} or {@link RestTemplate} instance. + * to a {@link RestClient} or {@link org.springframework.web.client.RestTemplate} instance. * If the 'expectReply' flag is set to true (the default) * then a reply Message will be generated from the HTTP response. If that response contains * a body, it will be used as the reply Message's payload. Otherwise the reply Message's @@ -74,7 +72,7 @@ public class HttpRequestExecutingMessageHandler extends AbstractHttpRequestExecutingMessageHandler { @SuppressWarnings("removal") - private final @Nullable RestTemplate restTemplate; + private final org.springframework.web.client.@Nullable RestTemplate restTemplate; private volatile @Nullable RestClient restClient; @@ -116,7 +114,8 @@ public HttpRequestExecutingMessageHandler(Expression uriExpression) { */ @Deprecated(since = "7.1", forRemoval = true) @SuppressWarnings("removal") - public HttpRequestExecutingMessageHandler(String uri, @Nullable RestTemplate restTemplate) { + public HttpRequestExecutingMessageHandler(String uri, + org.springframework.web.client.@Nullable RestTemplate restTemplate) { this(new LiteralExpression(uri), restTemplate); /* * We'd prefer to do this assertion first, but the compiler doesn't allow it. However, @@ -135,7 +134,8 @@ public HttpRequestExecutingMessageHandler(String uri, @Nullable RestTemplate res */ @Deprecated(since = "7.1", forRemoval = true) @SuppressWarnings("removal") - public HttpRequestExecutingMessageHandler(Expression uriExpression, @Nullable RestTemplate restTemplate) { + public HttpRequestExecutingMessageHandler(Expression uriExpression, + org.springframework.web.client.@Nullable RestTemplate restTemplate) { this(uriExpression, restTemplate, null); } @@ -168,7 +168,7 @@ public HttpRequestExecutingMessageHandler(Expression uriExpression, @Nullable Re @SuppressWarnings("removal") private HttpRequestExecutingMessageHandler(Expression uriExpression, - @Nullable RestTemplate restTemplate, @Nullable RestClient restClient) { + org.springframework.web.client.@Nullable RestTemplate restTemplate, @Nullable RestClient restClient) { super(uriExpression); Assert.isTrue(restTemplate == null || restClient == null, @@ -224,15 +224,16 @@ protected void doInit() { } /** - * Set the {@link ResponseErrorHandler} for the underlying {@link RestTemplate}. + * Set the {@link org.springframework.web.client.ResponseErrorHandler} for the underlying + * {@link org.springframework.web.client.RestTemplate}. * @param errorHandler The error handler. * @deprecated Use {@link #setDefaultStatusHandler(RestClient.ResponseSpec.ErrorHandler)} * or {@link #defaultStatusHandler(Predicate, RestClient.ResponseSpec.ErrorHandler)} - * @see RestTemplate#setErrorHandler(ResponseErrorHandler) + * @see org.springframework.web.client.RestTemplate#setErrorHandler(org.springframework.web.client.ResponseErrorHandler) */ @Deprecated(since = "7.2", forRemoval = true) @SuppressWarnings("removal") - public void setErrorHandler(ResponseErrorHandler errorHandler) { + public void setErrorHandler(org.springframework.web.client.ResponseErrorHandler errorHandler) { assertLocalClient("errorHandler"); RestClient.Builder localRestClientBuilder = this.localRestClientBuilder; Assert.state(localRestClientBuilder != null, "'localRestClientBuilder' must not be null"); @@ -335,7 +336,7 @@ public void setEncodingMode(DefaultUriBuilderFactory.EncodingMode encodingMode) private ResponseEntity exchangeWithRestTemplate(Object uri, HttpMethod httpMethod, HttpEntity httpRequest, Object expectedResponseType, Map uriVariables) { - RestTemplate restTemplate = this.restTemplate; + org.springframework.web.client.RestTemplate restTemplate = this.restTemplate; Assert.state(restTemplate != null, "'restTemplate' must not be null"); if (uri instanceof URI uriToUse) { From b9483012114bbbe99a10d20c4de7a17e1df5f6bf Mon Sep 17 00:00:00 2001 From: Burak KALAYCI Date: Mon, 24 Aug 2026 23:36:34 +0300 Subject: [PATCH 5/6] GH-11268: Use RestClient ErrorHandler in XML parser tests Wire error-handler to defaultStatusHandler and drop the deprecated ResponseErrorHandler types from the parser tests. Signed-off-by: Burak KALAYCI --- .../http/config/HttpAdapterParsingUtils.java | 14 ++++++++++++++ .../config/HttpOutboundChannelAdapterParser.java | 5 +---- .../http/config/HttpOutboundGatewayParser.java | 5 +---- .../http/config/spring-integration-http.xsd | 4 ++-- .../HttpOutboundChannelAdapterParserTests.java | 12 +++--------- .../config/HttpOutboundGatewayParserTests.java | 3 +-- 6 files changed, 22 insertions(+), 21 deletions(-) diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpAdapterParsingUtils.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpAdapterParsingUtils.java index b4bb1b6cf09..f8b2a753f41 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpAdapterParsingUtils.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpAdapterParsingUtils.java @@ -26,6 +26,7 @@ import org.springframework.beans.factory.xml.ParserContext; import org.springframework.expression.common.LiteralExpression; import org.springframework.integration.config.ExpressionFactoryBean; +import org.springframework.integration.config.xml.IntegrationNamespaceUtils; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; @@ -52,6 +53,19 @@ final class HttpAdapterParsingUtils { private static final LocalClientKind REST_CLIENT_KIND = new LocalClientKind("rest-client", "the provided client", "RestClient.Builder.uriBuilderFactory"); + static void configureLocalClientAttributes(BeanDefinitionBuilder builder, Element element) { + for (String referenceAttributeName : LOCAL_CLIENT_REFERENCE_ATTRIBUTES) { + if ("error-handler".equals(referenceAttributeName)) { + IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, referenceAttributeName, + "defaultStatusHandler"); + } + else { + IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, referenceAttributeName); + } + } + IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "encoding-mode"); + } + static void verifyNoRestTemplateAttributes(Element element, ParserContext parserContext) { verifyNoLocalClientAttributes(element, parserContext, REST_TEMPLATE_KIND); } diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java index affaf7ca7fc..07565dac113 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java @@ -100,10 +100,7 @@ else if (StringUtils.hasText(restClientRef)) { .addIndexedArgumentValue(1, new RuntimeBeanReference(restClientRef)); } else { - for (String referenceAttributeName : HttpAdapterParsingUtils.LOCAL_CLIENT_REFERENCE_ATTRIBUTES) { - IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, referenceAttributeName); - } - IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "encoding-mode"); + HttpAdapterParsingUtils.configureLocalClientAttributes(builder, element); } return builder; } diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java index 8913f57f686..38ba0f931c4 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java @@ -113,10 +113,7 @@ else if (StringUtils.hasText(restClientRef)) { .addIndexedArgumentValue(1, new RuntimeBeanReference(restClientRef)); } else { - for (String referenceAttributeName : HttpAdapterParsingUtils.LOCAL_CLIENT_REFERENCE_ATTRIBUTES) { - IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, referenceAttributeName); - } - IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "encoding-mode"); + HttpAdapterParsingUtils.configureLocalClientAttributes(builder, element); } return builder; } diff --git a/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http.xsd b/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http.xsd index 5c75987c32f..43616dc97a7 100644 --- a/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http.xsd +++ b/spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http.xsd @@ -832,11 +832,11 @@ - Reference to a ResponseErrorHandler to be used by the underlying RestTemplate. + Reference to a RestClient.ResponseSpec.ErrorHandler to be used by the underlying RestClient. - + diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java index 960aa7489f0..21221c2fc04 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java @@ -16,7 +16,6 @@ package org.springframework.integration.http.config; -import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; @@ -32,6 +31,7 @@ import org.springframework.expression.Expression; import org.springframework.expression.spel.standard.SpelExpression; import org.springframework.http.HttpMethod; +import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpResponse; import org.springframework.integration.endpoint.AbstractEndpoint; @@ -45,7 +45,6 @@ import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.util.ObjectUtils; -import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.RestClient; import org.springframework.web.util.DefaultUriBuilderFactory; @@ -267,15 +266,10 @@ public void failWithUrlAndExpression() { getClass())); } - public static class StubErrorHandler implements ResponseErrorHandler { + public static class StubErrorHandler implements RestClient.ResponseSpec.ErrorHandler { @Override - public boolean hasError(ClientHttpResponse response) { - return false; - } - - @Override - public void handleError(URI url, HttpMethod method, ClientHttpResponse response) { + public void handle(HttpRequest request, ClientHttpResponse response) { } } diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java index 1c517c2b9ad..653276ed0c8 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java @@ -45,7 +45,6 @@ import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.util.ObjectUtils; -import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.RestClient; import static org.assertj.core.api.Assertions.assertThat; @@ -65,7 +64,7 @@ @DirtiesContext public class HttpOutboundGatewayParserTests { - public static final ResponseErrorHandler mockResponseErrorHandler = mock(); + public static final RestClient.ResponseSpec.ErrorHandler mockResponseErrorHandler = mock(); @Autowired @Qualifier("minimalConfig") From 002bd0d7d46e7fcdbbfc6f0677e8aab27d9f394d Mon Sep 17 00:00:00 2001 From: Burak KALAYCI Date: Tue, 25 Aug 2026 17:33:02 +0300 Subject: [PATCH 6/6] GH-11268: Add author to improved HTTP parser classes Signed-off-by: Burak KALAYCI --- .../integration/http/config/HttpAdapterParsingUtils.java | 1 + .../http/config/HttpOutboundChannelAdapterParser.java | 1 + .../integration/http/config/HttpOutboundGatewayParser.java | 1 + 3 files changed, 3 insertions(+) diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpAdapterParsingUtils.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpAdapterParsingUtils.java index f8b2a753f41..61758ef493c 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpAdapterParsingUtils.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpAdapterParsingUtils.java @@ -38,6 +38,7 @@ * @author Artem Bilan * @author Shiliang Li * @author Arun Sethumadhavan + * @author Burak Kalayci * * @since 2.0.2 */ diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java index 07565dac113..b1633fceead 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java @@ -37,6 +37,7 @@ * @author Artem Bilan * @author Shiliang Li * @author Arun Sethumadhavan + * @author Burak Kalayci * * @since 2.0 */ diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java index 38ba0f931c4..872c5cfbbb7 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java @@ -35,6 +35,7 @@ * @author Artem Bilan * @author Shiliang Li * @author Arun Sethumadhavan + * @author Burak Kalayci */ public class HttpOutboundGatewayParser extends AbstractConsumerEndpointParser {