Affects: \6.1.3


If RestClient Builder is created from a RestTemplate an attempt to set a the baseUrl would leads to the java.lang.IllegalArgumentException: URI is not absolute exception.

To reproduce:

@Test
public void test2() {
  String baseUrl = "https://dog.ceo";
  RestTemplate restTemplate = new RestTemplate();
  var restClient = RestClient.builder(restTemplate).baseUrl(baseUrl).build();
 String res = restClient.get().uri("/api/breeds/list/all").retrieve().body(String.class);
 assertThat(res).isNotNull();
}

would throw:

java.lang.IllegalArgumentException: URI is not absolute
 at java.base/java.net.URL.fromURI([URL.java:721](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at java.base/java.net.URI.toURL([URI.java:1139](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at org.springframework.http.client.SimpleClientHttpRequestFactory.createRequest([SimpleClientHttpRequestFactory.java:154](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.createRequest([DefaultRestClient.java:528](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))

Note: If you set the restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(baseUrl)); before creating the builder it won't fail.

Comment From: Akaame

@poutsma I reproduced this and what happens is clear:

private UriBuilderFactory initUriBuilderFactory() {
if (this.uriBuilderFactory != null) {
    return this.uriBuilderFactory;
}
DefaultUriBuilderFactory factory = (this.baseUrl != null ?
        new DefaultUriBuilderFactory(this.baseUrl) : new DefaultUriBuilderFactory());
factory.setDefaultUriVariables(this.defaultUriVariables);
return factory;
}

The condition here is not respected because of the DefaultUriBuilderFactory. This is what I am seeing:

Spring Unable to use baseUrl on builders created from RestTemplate

Therefore the baseUrl is never respected. The code works when the setUriTemplateHandler is called with a UriBuilderFactory explicitly because it creates instances with baseUrl already. I have not contributed Spring enough to suggest the best solution here. Maybe it is advisable to ensure either the existence of this.uriBuilderFactory.baseUrl or the this.baseUrl itself.

Comment From: jhoeller

@poutsma I'm replacing hasRestTemplateDefaults() with hasBaseUri() in DefaultUriBuilderFactory since this allows for keeping the actual RestTemplate-style settings check in DefaultRestClientBuilder itself where it conceptually fits better.

Not least of it all, RestClient and RestTemplate live in the web.client package whereas DefaultUriBuilderFactory lives in web.util where it shouldn't logically depend on RestTemplate and its default settings, in particular not in a public method name.