As the title says, the org.springframework.boot.web.client.ClientHttpRequestFactories::get(ClientHttpRequestFactorySettings settings) falls back to org.springframework.http.client.SimpleClientHttpRequestFactory when no other optional dependency is present (apache hc5, jetty or okhttp), which uses java.net.HttpURLConnection underneath. However, java.net.HttpURLConnection does not and will never support HTTP Patch method as the original request was marked as "Won't Fix" and they delegate to new JDK11 Client API (which Spring Framework and Boot support).

https://bugs.openjdk.org/browse/JDK-7016595

Now, both RestTemplate and RestClient use the mentioned ClientHttpRequestFactories method and end up with SimpleClientHttpRequestFactory set as their request factory. Calling any HTTP endpoint with HTTP Method PATCH will throw an exception

org.opentest4j.AssertionFailedError: Unexpected exception thrown: org.springframework.web.client.ResourceAccessException: I/O error on PATCH request for "http://localhost:59537": Invalid HTTP method: PATCH

    at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:152)
    at org.junit.jupiter.api.AssertDoesNotThrow.createAssertionFailedError(AssertDoesNotThrow.java:84)
    at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:75)
    at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:58)
    at org.junit.jupiter.api.Assertions.assertDoesNotThrow(Assertions.java:3228)
    at com.github.krezovic.resttemplate_bug.ResttemplateBugApplicationTests.rtTest(ResttemplateBugApplicationTests.java:30)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on PATCH request for "http://localhost:59537": Invalid HTTP method: PATCH
    at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.createResourceAccessException(DefaultRestClient.java:578)
    at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.exchangeInternal(DefaultRestClient.java:501)
    at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.retrieve(DefaultRestClient.java:463)
    at com.github.krezovic.resttemplate_bug.ResttemplateBugApplicationTests.lambda$rtTest$1(ResttemplateBugApplicationTests.java:30)
    at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:71)
    ... 6 more
Caused by: java.net.ProtocolException: Invalid HTTP method: PATCH
    at java.base/java.net.HttpURLConnection.setRequestMethod(HttpURLConnection.java:491)
    at java.base/sun.net.www.protocol.http.HttpURLConnection.setRequestMethod(HttpURLConnection.java:592)
    at org.springframework.http.client.SimpleClientHttpRequestFactory.prepareConnection(SimpleClientHttpRequestFactory.java:200)
    at org.springframework.http.client.SimpleClientHttpRequestFactory.createRequest(SimpleClientHttpRequestFactory.java:155)
    at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.createRequest(DefaultRestClient.java:557)
    at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.exchangeInternal(DefaultRestClient.java:483)

Reproducer located at https://github.com/krezovic/resttemplate-bug, simply run ./mvnw clean verify

The obvious fix would be to switch to JDK11 Client Factory which appears to be preferred by RestClient.Builder in org.springframework.web.client.DefaultRestClientBuilder::initRequestFactory but sadly is overriden by org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration to call the already mentioned method which does not consider JDK11 Client Factory at all.

Comment From: philwebb

Thanks for raising the issue. This is not the first problem we've encountered with SimpleClientHttpRequestFactory, however changing the default is a little more involved that it would first appear. See the discussion in #36118 for more background.

I think we can consider this issue a duplicate of #36266. Until we have the configuration options in place, we can't consider switching to the JDK11 Client Factory since folks won't be able to switch back easily.