What is the proper way to make an api call via springs `WebClient`, but ignore the result? - spring

What is the proper way to make an api call via springs WebClient, but ignore the result? The ClientResponse object specifically calls out that I have to do something with the result...
Docs:
NOTE: When given access to a ClientResponse, through the WebClient exchange() method, you must always use one of the body or toEntity methods to ensure resources are released and avoid potential issues with HTTP connection pooling. You can use bodyToMono(Void.class) if no response content is expected. However keep in mind that if the response does have content, the connection will be closed and will not be placed back in the pool.
Can I make a WebClient call and ignore the results? or is there a generic catch all "body or toEntity method" that I can use and then ignore?

Prior to Spring Framework 5.2, using the WebClient#exchange() method and dealing directly with the Mono<ClientResponse> could be quite complex or lead to potential memory leaks.
As of Spring Framework 5.2, this has been made much easier for developers and the exchange() method has been deprecated.
Mono<ResponseEntity<Void>> response = webClient.put()
.uri("https://example.org/book/123")
.retrieve()
.toBodilessEntity();
Spring will read the response body (if present) and release the data buffers, and then return the connection to the pool. It's making sure that there's no memory leak, including when additional Reactor operators are used.

Related

Spring Boot WebFlux Save request and response as json

I've used spring webflux as it was suggested to be used for httpClient. now I'm forced to save the request and response (JSON) in DB so I could track the history of service usage. and I don't want to block the response and reduce the performance.
some people have written about actuator, and others suggest using a filter. but until now I have not found a straight answer. Is it good to do something like this at all? and in my case what would be the best way to still keep the non-blocking system running ?
any recommendations ?

Calling Multiple apis synchronously, spring boot webflux

In my project we are using spring boot webflux, and I have this scenario where i have to call multiple api's from within a particular microservice synchronously.
e.g.
for(String api:apiNames){
//call api's
}
As per my understanding, webClient works asynchronously, until and unless someone subscribe to it it wont release the response.
in my current scenario i have to make use of webclient and I have to call each api only after successfull execution of previous api.
Note:- api response can be anything success/failure
Please help me in implementing this synchronous call
You can use the #block() method to make it synchronous.
Example on a mono (https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html#block--)
For example on the (asynchronous) webflux webclient:
return webClient.get()
.uri(uri)
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(String.class)
.block();
The above example will wait with executing any next line of code untill it has received a response.
After which you can just make another call to another api in the same way.
Edit: As pointed out in the comments I would like to add a warning that using #block() is not efficient and you should try and chain more reactive calls and try to avoid making your application non reactive.
A nice post with more details can be found here: https://stackoverflow.com/a/57365926/1326867
Although, the question uses the word "synchronously", the description rather seems to suggest that sequentiality is what is needed, meaning executing each request one after the other.
If that's the requirement, it can be implemented the following way with Reactor:
Flux.fromIterable(apiNames)
.concatMap(apiName -> webClient...) // concatMap ensures sequential execution
However, if the application is a blocking Spring application, then Nick Hol's answer is also a correct one.

How to use Apollo Server DataSource to call a GraphQL API

In our GraphQL api (Apollo-Server) we would like to add a new dataSource which accesses GitHub's GraphQL api. We are looking to consume this data. It appears that using apollo-datasource-rest` is a good approach to do this. It's an established, still maintained module which provides caching, access to context and other dataSource benefits. It's also managed by the Apollo team. We want to verify that this is a good approach for making requests to other GraphQL APIs.
Other options are:
Roll your own datasource, which doesn't seem necessary or with apparent benefits
Build out a datasource using #apollo/client
There is a module, apollo-datasource-graphql, which appears fits this perfectly, though it has not been updated in two years and appears it may be unfinished with tests and request caching not complete.
Is using apollo-datasource-rest a good practice for accessing other GraphQL APIs as a dataSource in a GraphQL server service?
Is there a better, more established approach for doing this?
We are having the same concern since our backend needs to consume, as a client, a graphql api. The REST interface approach is expecting http GET queries to be cacheable, but not verbs like POST, PUT, DELETE... My understanding of GraphQL is that if you are only using http POST as a communication pattern this is going to prevent apollo-datasource-rest to handle caching for your queries and then it may not be the appropriate lib.
Other approaches to consider:
apollo-datasource-http
Apollo server (and the GraphQL specification) also supports GET queries so it may solve apollo-datasource-rest caching issues
usage of graphql-code-generator to generate the consumer of the target GraphQL api (and then use the client directly inside a service, or define a custom datasource to wrap the client)

Connection pooling in spring WebClient

I want to use Spring WebClient in a project to consume some external web service.
Can WebClient object be singleton or shared among all threads (requests)?
If my application is going to get millions of requests per second, then do I need to pool WebClient Objects? If yes, I am unable to find any documentation or examples.
Does mono.block() internally work similar to future.get() or latch.await()?
The WebClient is a non-blocking implementation of a REST client built on the Reactive Stack, so I guess the only issue you should focus on is to complete a non-blocking call.
Can WebClient object be a singleton or shared among all threads (requests)?
A standard way I have seen everywhere is to inject WebClient as a bean. I find no reason to do any different.
#Autowired
WebClient webClient;
If my application is going to get millions of requests per second, then do I need to pool WebClient Objects?
That's a lot! This should definitely need to be solved with service replication, load-balancers, bulkhead, etc. In terms of the client itself, see the following performance of reactive client using newer versions of Spring: WebFlux Reactive Programming Performance Test. Moreover, that is the expected maximal throughput?
Does mono.block() internally work similar to future.get() or latch.await()?
Yes, it does.

WebClient vs RestTemplate

As per spring 5:
WebClient is an interface representing the main entry point for performing web requests.
It has been created as a part of the Spring Web Reactive module and will be replacing the classic RestTemplate in these scenarios. The new client is a reactive, non-blocking solution that works over the HTTP/1.1 protocol
Does that mean, we need to recode for the old applications using RestTemplate if we want to upgrade to Spring 5?
Or there is some workaround to work with RestTemplate in Spring 5?
No, RestTemplate will continue to exist (at least for now). You don't have to replace it with WebClient.
One of the main differences is RestTemplate is synchronous and blocking i.e. when you do a rest call you need to wait till the response comes back to proceed further.
But WebClient is complete opposite of this. The caller need not wait till response comes back. Instead he will be notified when there is a response.
If you need such a functionality, then yes you need to replace your Resttemplate with WebClient.
You can in fact achieve Rest template like synchronous processing in webclient using .block(). But the other way is not possible.
EDIT:
RestTemplate will be deprecated in a future version(> 5.0) and will not have major new features added going forward
According to the Java Doc the RestTemplate will be in maintenance mode. Spring team advise to use the WebClient if possible:
NOTE: As of 5.0, the non-blocking, reactive
org.springframework.web.reactive.client.WebClient offers a modern
alternative to the RestTemplate with efficient support for both sync
and async, as well as streaming scenarios. The RestTemplate will be
deprecated in a future version and will not have major new features
added going forward.
RestTemplate is not really deprecated. But it will not be evolved in the future. So sticking to RestTemplate is perfectly valid if it does what you need.
Another way to put that is that if you need specific usage patterns like streaming, scatter/gatter, or custom timeouts, this won't be covered by RestTemplate and you need to use WebClient instead.
Now using WebClient in a blocking application is fine too. Using block() shouldn't hurt there and Spring MVC controller does partially support reactive return types.
WebClient is Non-Blocking Client, RestTemplate is Blocking Client.
For a long time, spring serves as a web customer. Under the hood, RestTemplate uses the Java API API, which is based on the subject model.This means that the matter will be blocked until the client receives a response. The problem with the blockage code is due to the existence of any string of memory and cpu cycles. Let us consider a lot of applications that are waiting for low services that are needed to produce the result.Sooner or later, requests for the results are collected. As a result, the program creates many issues, which result in depletion of a pool of thread or occupying all of the available memory. We can also experience performance performance due to the cpu switching.
Spring WebClient vs. RestTemplate
WebClient supports asynchronous as well as synchronous calls.
RestTemplate supports only synchronous calls.
No changes are required in old code even if the RestTemplate is depracated(as long as you don't need asynchronous behaviour)

Resources