Make RestTemplateBuilder more compatible with RestClient.Builder

When Spring Framework builds a `RestClient` from a `RestTemplate`, it
will use any `UriTemplateHandler` that has been set on the
`RestTemplate` if the provided `UriTemplateHandler` is also a
`UriBuilderFactory`. Prior to this commit, Spring Boot's
`RestTemplateBuilder#rootUri` set a `UriTemplateHandler` on the created
`RestTemplate`, but it was not a `UriBuilderFactory` so `RestClient`
would not consider it.

With this commit, `RestTemplateBuilder#rootUri` sets a
`UriTemplateHandler` that is also a `UriBuilderFactory` so that any
root URI that is set on the `RestTemplateBuilder` will be applied to a
`RestClient` also.

Fixes gh-39317
This commit is contained in:
Scott Frederick
2024-02-13 13:10:55 -06:00
parent a0cb2bdeaf
commit 720e9cef16
9 changed files with 271 additions and 15 deletions

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2012-2024 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
*
* https://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.boot.test.autoconfigure.web.client;
import org.junit.jupiter.api.Test;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.RestClient;
import org.springframework.web.client.RestClient.Builder;
import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
/**
* Tests for building a {@link RestClient} from a {@link RestTemplateBuilder}.
*
* @author Scott Frederick
*/
class RestClientWithRestTemplateBuilderTests {
@Test
void buildUsingRestTemplateBuilderRootUri() {
RestTemplate restTemplate = new RestTemplateBuilder().rootUri("https://resttemplate.example.com").build();
RestClient.Builder builder = RestClient.builder(restTemplate);
RestClient client = buildMockedClient(builder, "https://resttemplate.example.com/test");
assertThat(client.get().uri("/test").retrieve().toBodilessEntity().getStatusCode().is2xxSuccessful()).isTrue();
}
@Test
void buildUsingRestClientBuilderBaseUrl() {
RestTemplate restTemplate = new RestTemplateBuilder().build();
RestClient.Builder builder = RestClient.builder(restTemplate).baseUrl("https://restclient.example.com");
RestClient client = buildMockedClient(builder, "https://restclient.example.com/test");
assertThat(client.get().uri("/test").retrieve().toBodilessEntity().getStatusCode().is2xxSuccessful()).isTrue();
}
@Test
void buildRestTemplateBuilderRootUriAndRestClientBuilderBaseUrl() {
RestTemplate restTemplate = new RestTemplateBuilder().rootUri("https://resttemplate.example.com").build();
RestClient.Builder builder = RestClient.builder(restTemplate).baseUrl("https://restclient.example.com");
RestClient client = buildMockedClient(builder, "https://resttemplate.example.com/test");
assertThat(client.get().uri("/test").retrieve().toBodilessEntity().getStatusCode().is2xxSuccessful()).isTrue();
}
private RestClient buildMockedClient(Builder builder, String url) {
MockRestServiceServer server = MockRestServiceServer.bindTo(builder).build();
server.expect(requestTo(url)).andRespond(withSuccess());
return builder.build();
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright 2012-2024 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
*
* https://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.boot.test.autoconfigure.web.client;
import org.junit.jupiter.api.Test;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.RestClient;
import org.springframework.web.client.RestClient.Builder;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.DefaultUriBuilderFactory;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
/**
* Tests for building a {@link RestClient} from a {@link RestTemplate}.
*
* @author Scott Frederick
*/
class RestClientWithRestTemplateTests {
@Test
void buildUsingRestTemplateUriTemplateHandler() {
RestTemplate restTemplate = new RestTemplate();
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("https://resttemplate.example.com");
restTemplate.setUriTemplateHandler(uriBuilderFactory);
Builder builder = RestClient.builder(restTemplate);
RestClient client = buildMockedClient(builder, "https://resttemplate.example.com/test");
assertThat(client.get().uri("/test").retrieve().toBodilessEntity().getStatusCode().is2xxSuccessful()).isTrue();
}
@Test
void buildUsingRestClientBuilderBaseUrl() {
RestTemplate restTemplate = new RestTemplate();
Builder builder = RestClient.builder(restTemplate).baseUrl("https://restclient.example.com");
RestClient client = buildMockedClient(builder, "https://restclient.example.com/test");
assertThat(client.get().uri("/test").retrieve().toBodilessEntity().getStatusCode().is2xxSuccessful()).isTrue();
}
@Test
void buildUsingRestTemplateUriTemplateHandlerAndRestClientBuilderBaseUrl() {
RestTemplate restTemplate = new RestTemplate();
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory("https://resttemplate.example.com");
restTemplate.setUriTemplateHandler(uriBuilderFactory);
Builder builder = RestClient.builder(restTemplate).baseUrl("https://restclient.example.com");
RestClient client = buildMockedClient(builder, "https://resttemplate.example.com/test");
assertThat(client.get().uri("/test").retrieve().toBodilessEntity().getStatusCode().is2xxSuccessful()).isTrue();
}
private RestClient buildMockedClient(Builder builder, String url) {
MockRestServiceServer server = MockRestServiceServer.bindTo(builder).build();
server.expect(requestTo(url)).andRespond(withSuccess());
return builder.build();
}
}