Closed poutsma closed 1 year ago
After team discussion, it has been decided that the 6.1 timeline will be too early for us to fully implement a Loom-ready WebClient. There are simply too may unknowns: underlying ClientHttpRequestFactory implementations that yet have to reveal their plans for Loom support, it is unclear what structured concurrency will look like in a Loom environment, and so on.
Implementing a new, Loom-ready WebClient in 6.1 could mean that we end up with something that is not ready for the future. Therefore, we have decided to do experimental work on this issue in parallel to the 6.1 release, but not make the issue part of this release. Further progress will be provided through this issue.
Note that we are still considering other areas for Loom compatibility for 6.1, including the existing (reactive) WebClient and RestTemplate.
This is amazing, but please, keep the package server(arch)-agnostic this time (reactive/servlet)
Spring 6.1 M2 will see the introduction of RestClient
, a synchronous HTTP client that offers an API similar to WebClient
, using the same infrastructure (i.e. request factory, error handler, interceptors, etc) as RestTemplate
.
Out of curiosity, why use "Rest" as part of the name if it can be used for anything HTTP-related, such as GraphQL? I admit it's tough to come up with a good, descriptive name that also rolls easily off the tongue, though, especially since "HttpClient" is already taken.
The prefix Rest
reflects that this new client conceptually sits in between RestTemplate
and WebClient
. Initially we considered having two WebClient
classes: a reactive and non-reactive one. But that would cause confusion, so we went for RestClient
.
In retrospect, I would not have have given RestTemplate
that prefix when it was introduced in Spring 3, because it has little to do with REST. But here we are, and like you said: HttpClient
is already taken by Apache, OkHttp, Jetty, and the JDK.
The RestTemplate will be deprecated in a future version and will not have major new features added going forward. https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html
with RestClient in place, will RestTemplate get deprecated in 6.1 timeframe?
The RestTemplate will be deprecated in a future version and will not have major new features added going forward.
@anbusampath Please read that page you linked to again, as it does not contain the text you quoted.
with RestClient in place, will RestTemplate get deprecated in 6.1 timeframe?
RestTemplate
will not be deprecated; it is in maintenance mode, meaning that it will not have new features.
@anbusampath Please read that page you linked to again, as it does not contain the text you quoted.
sorry my bad, I was reading old doc - https://docs.spring.io/spring-framework/docs/5.2.1.RELEASE/javadoc-api/index.html?org/springframework/web/client/RestTemplate.html and attached latest doc link. Latest version does not contain the text.
RestTemplate
will not be deprecated; it is in maintenance mode, meaning that it will not have new features.
Thanks for the clarification.
RestTemplate
will not be deprecated; it is in maintenance mode, meaning that it will not have new features.
@poutsma Could you review this PR https://github.com/spring-projects/spring-framework/pull/27188? It's not new feature, I think it's a fix or improvement.
Will this new RestClient
support the HttpServiceProxyFactory
class along with the @HttpExchange
annotated interfaces?
Will this new
RestClient
support theHttpServiceProxyFactory
class along with the@HttpExchange
annotated interfaces?
watch this issue - https://github.com/spring-projects/spring-framework/issues/30117
Thanks for making this happen @poutsma (and the team). With RestTemplate
being in the maintenance mode, something like this was much needed for all of us that aren't (for whatever the reason) keen on using WebClient
.
I'm curious whether the team considered making the new client a part of separate module, rather then having it again (as with RestTemplate
) packaged in spring-web
that's mostly focused on server-side components? I know that something along these lines was previously discussed (https://github.com/spring-projects/spring-framework/issues/21301 comes to mind), but I'm in the camp with those that firmly believe that I shouldn't get server-side components if client is all I'm interested in. Besides the fact it has become quite common for frameworks that react on presence of things on classpath, I would say that the likelihood of setups that need just the client in on the rise - Spring Batch comes to mind as it recommends job per JVM approach these days, if I'm not mistaken.
Regarding naming, did you consider going with HttpOperations
(implemented by HttpTemplate
)? This is more aligned with other places in Spring where we have ...Operations
/...Template
combination, and avoids using the term REST where it really shouldn't be used. Additionally, it feels to me that RestClient
itself isn't really the client itself but rather the convenience layer that abstracts the underlying HTTP client, similar like other ...Operations
/...Template
combinations do.
I'm curious whether the team considered making the new client a part of separate module, rather then having it again (as with
RestTemplate
) packaged inspring-web
that's mostly focused on server-side components?
This was not considered. RestClient
is closely aligned to RestTemplate
, as it uses the same underlying infrastructure and throws the same exceptions. Putting RestClient
in a separate module would therefore mean either moving RestTemplate
and related types out of the spring-web module—breaking backward compatibility from 6.0, or putting RestClient
in a new module all by itself, which is equally unappealing.
Regarding naming, did you consider going with
HttpOperations
(implemented byHttpTemplate
)? This is more aligned with other places in Spring where we have...Operations
/...Template
combination, and avoids using the term REST where it really shouldn't be used.
A HttpClient based the Operations
/Template
design is what we created in RestTemplate 14 years ago, and it quickly became apparent that the API-style that Templates offer is not suitable for HTTP clients, because exposing every capability of HTTP in a Template results in too many overloaded (see RestTemplate
). As for the Rest
prefix, see my comment above.
Additionally, it feels to me that
RestClient
itself isn't really the client itself but rather the convenience layer that abstracts the underlying HTTP client, similar like other...Operations
/...Template
combinations do.
I am not sure what gave you that feeling, because the WebClient
was introduced in 5.0 and "abstract the underlying HTTP clients" in pretty much the same way as RestClient
does.
This was not considered. RestClient is closely aligned to RestTemplate, as it uses the same underlying infrastructure and throws the same exceptions. Putting RestClient in a separate module would therefore mean either moving RestTemplate and related types out of the spring-web module—breaking backward compatibility from 6.0, or putting RestClient in a new module all by itself, which is equally unappealing.
I understand that this would be a significant undertaking, and one that wouldn't be fully possible without breaking changes and therefore a new major release. However, IMO RestClient
in a new module sounds quite nice, assuming other clients are moved there as well with time (if RestTemplate
won't eventually get deprecated and removed).
With the introduction of a modern HTTP client to the JDK itself, it's even more difficult to swallow the extra components you need to put to your classpath in order to use the new RestClient
, if you don't need server-side support. Quite honestly, I'd prefer to use the thinnest possible convenience layer around java.net.http.HttpClient
(be it from Spring or someone else) simply because I can have the same experience on every type of project while also having minimal impact on the classpath.
I am not sure what gave you that feeling, because the WebClient was introduced in 5.0 and "abstract the underlying HTTP clients" in pretty much the same way as RestClient does.
The same concerns from my end apply to WebClient
as well, I'm just not focusing on it as I generally try to avoid reactive, but I think it should've been named (reactive-)HTTP-something. Naming truly is hard, but I would've definitely preferred something that has HTTP in its name and expresses well that it's an abstraction of the underlying client, regardless of the legacy and how others name their clients.
Anyhow, this is (to me) a less important concern to how things are laid out across Spring modules.
Naming is hard, and it's not always about picking the most logical name. The choice has to be made in a specific context, and in the given context the chosen name is good. The RestTemplate
, even if imperfectly named, has been used for so long and widely that it carries very deep associations. RestClient
is good as a layer around the same infrastructure and in the same package.
The Spring Framework has many clients, two HTTP clients, two WebSocket clients, SockJsClient, TCP client, STOMP client, RSocket client, DatabaseClient, and not even counting the various templates for JDBC, JMS. Across Spring projects there are many more. There would be many new jars down this road, tempting as it might look for one case, I'm not sure the overall end result is a better place.
Many of those clients support different underlying libraries. It's not clear if you actually want this split even further, e.g. one HTTP client jar for the JDK client, another for Jetty, another for Apache HTTP Components, and so on, but clearly that would be even more jars, or otherwise you still have a jar with some optional dependencies at least. Our view is that we try to structure modules but any optional dependencies within should not have impact you in any way as long as the classes are not used.
Many of those clients support different underlying libraries. It's not clear if you actually want this split even further, e.g. one HTTP client jar for the JDK client, another for Jetty, another for Apache HTTP Components, and so on, but clearly that would be even more jars, or otherwise you still have a jar with some optional dependencies at least. Our view is that we try to structure modules but any optional dependencies within should not have impact you in any way as long as the classes are not used.
My preference would be to have a single Spring module that carries all the HTTP-client related code, with supported underlying libraries being expressed through optional dependencies.
On projects I work on I'm really picky about what I put on the classpath and really like to avoid having anything that's not really necessary. So I'm never thrilled to see server- and client-side components mixed together.
My own preferences aside, there are numerous benefits of keeping the two apart:
Does RestClient
have a variant for use in testing like RestTemplate
had with TestRestTemplate
?
Is the alternative using the WebTestClient
here?
EDIT: issue tracking this https://github.com/spring-projects/spring-framework/issues/31275
@wimdetroyer, TestRestTemplate
is part of the Spring Boot test support. It's a simple helper to configure a RestTemplate
for integration testing against your server. It's up to the Boot team to consider what similar support for RestClient
looks like.
In the mean time, you can bridge TestRestTemplate
to RestClient
:
@Test
void exampleTest(@Autowired TestRestTemplate restTemplate) {
RestClient restClient = RestClient.create(restTemplate.getRestTemplate());
// ...
}
Does RestClient have a retry mechanism support? How we can configure the client to retry requests when specific exception is thrown?
Does RestClient have a retry mechanism support? How we can configure the client to retry requests when specific exception is thrown?
Use spring retry
RestClient
can use the same interface as RestTemplate
for inserting retry processes, which is the ClientHttpRequestInterceptor
. For an example of a ClientHttpRequestInterceptor
with retry logic, you can refer to this GitHub repository: https://github.com/making/retryable-client-http-request-interceptor
In Spring Framework 5.0, we introduced the
WebClient
: a new, reactive HTTP client. Compared toRestTemplate
, the previous generation,WebClient
improved HTTP access on two fronts:With the advent of Project Loom, asynchrony can be obtained through standard, synchronous APIs. We should therefore introduce a version of
WebClient
that offers the same improved APIs as the current reactive version, but exposes them in a synchronous manner.