How to implement async in spring boot for getting response over asynchronous call? - spring-boot

How can i call 3 different GET rest apis asynchronously in Spring Boot? Currently its taking alot of time to execute this apis sequentially. Let me know how to do this asynchronously?

You can use async-http-client as given in the following url : https://www.baeldung.com/async-http-client
2.You can use AsyncRestTemplate. In AsyncRestTemplate object you need to send the following three parameters.
* endpoint uri,
* request entity with headers,
*and response object.
Catch all those in to a ListenableFuture object where implement the override methods of callback in the case of failure and success.
For both of these approach, you have to create request objects and call the services. And the call backmethod will capture the result in the response objects. You can merge responses together and then do your business.

You can use #EnableAsync annotation at the configuration level to enable async processing and #Async at the method level which needs to be invoked asynchronously.
For further details please refer to the below link
https://www.baeldung.com/spring-async

Related

At what point does the subscription take place? (spring webflux)

At what point does the spring webflux do the subscription? Everywhere I have read that there must be a subscription otherwise no change happens. In my short time with Spring Webflux, I have never seen a subscribe() neither in the controller or services.
My doubt is also when using flatMap(), map(),... etc.. at what point does the subscription take place?
What I have read does not really resolve my doubts.
public Flux method(){
....
myFlux.flatMap(data -> {
....
}).flatMap(e -> { .... });
}
I know this is an asynchronous issue, but each flatMap runs at the same time?...and so sometimes some data I have noticed is null.
It's the framework (spring-webflux) that subscribes to the returned Mono or Flux. For example if you use Netty (that's the default), then subscription happens here based on my debugging:
https://github.com/reactor/reactor-netty/blob/db27625064fc78f8374c1ef0af3160ec3ae979f4/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpServer.java#L962
Also, this article might be of help to understand what happens when:
https://spring.io/blog/2019/03/06/flight-of-the-flux-1-assembly-vs-subscription
You need to call a .subscribe() or block() function after your flatmap. Here's an example.
Assuming that myFlux is of type Flux, the following will execute the subscription based on the example above
myFlux.subscribe(System.out::println);
Here's an explanation on a separate StackOverflow thread.
But in your method function, you are returning a Flux object - so it's up to the consumer of the method() function how it wants to subscribe to the Flux. You shouldn't be trying to subscribe to the Flux from within
The answer is: it depends.
For example, if this is a Spring Controller method, then it is the framework itself that subscribes to the Mono or Flux.
If it is a method that is triggered from time to time by a Scheduler, then you must explicitly subscribe to the Mono or Flux, otherwise, no processing will take place.
This means that if your application only exposes a REST API and no processing need to be triggered in any other way, then it is very likely that you will never need to explicitly subscribe to a Mono or Flux because Spring will take care of that by you.

Is filter the right place to handle service calls based on header values in Spring?

Looking to make a service call based on a header value.
I can see two options:
1) Do it from the controller which is mainly used for a different service.
2) Add a filter which will do this by reading the request context.
Want to know what's the best way to handle this in a Spring application.
I guess it depends on your requirements.
Controller:
If you have to make service calls for preparing the response of a specific controller. For example, you have a controller say:
/employee
fand or preparing the response of this endpoint you need to call say staff service.
In this case, it's better to handle such calls in controllers.
Filter:
If you want to intercept each request and perform some operation on the request before sending it to the controller or before sending the response to the client.
A use case here can be checking the roles of the user by intercepting all requests.
As we know by using the filter, we can perform two operations at two instances −
Before sending the request to the controller
Before sending a response to the client.
In this case, OncePerRequestFilter is quite useful from the spring web module.
Quoting the documentation :
Filter base class that aims to guarantee a single execution per request dispatch, on any servlet container.

what is the difference between ResponseEntity<Mono> and Mono<ResponseEntity> as a return type of a rest controller

In Spring Webflux, what's the difference between ResponseEntity<Mono> versus Mono<ResponseEntity> as a return type of a rest controller?
When is the most appropriate to what?
Following up on this question, let's say I need to return a list, or let's say several elements of Foo, there are many examples of returning Flux.
Would it make sense to return ResponseEntity<Flux> or Flux<ResponseEntity>?
When I'm looking for this question, I found the same question posted here: https://github.com/spring-projects/spring-framework/issues/22614, but no answer, I searched spring docs, but find no info.
Thanks for the help.
Here are the various options you can make with a ResponseEntity return value:
ResponseEntity<Mono<T>> or ResponseEntity<Flux<T>> -- this makes the response status and headers known immediately while the body is provided asynchronously at a later point. Whether the body is Mono or Flux depends on how many values the response has.
Mono<ResponseEntity<T>> -- this provides all three -- response status, headers, and body, asynchronously at a later point. IT allows the response status and headers to vary depending on the outcome of asynchronous request handling.
Mono<ResponseEntity<Mono<T>>> or Mono<ResponseEntity<Flux<T>>> are also possible but less common. They provide the response status and headers asynchronously first and then the response body, also asynchronously at a second point later.
https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-ann-responseentity
WebFlux supports using a single value reactive type to produce the
ResponseEntity asynchronously, and/or single and multi-value reactive
types for the body.
So the return type on an annotated controller would actually be a Reactive Publisher like Flux or Mono that emits an object representing the data to return.
Example
Flux<AccountDto>
Or also:
Flux<ResponseEntity<AccountDto>>
I think you can even just set a raw DTO type as the return type and Webflux will automagically wrap it in a publisher for you.
Valid Return Types
https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-ann-return-types
Example: https://github.com/oktadeveloper/okta-spring-webflux-react-example/blob/react-app/reactive-web/src/main/java/com/example/demo/ProfileRestController.java
Non-blocking Reactive Paradigm
When doing Reactive Programming you want to every layer to communicate via Flux/Mono. So you would get back a Flux from your ReactiveRepository and the service layer would also return a Flux to the Controller. Basically, in reactive programming everything is a Flux/Mono.
Internals
While SpringMVC and Spring Webflux annotated controllers look similar, they are vastly different internally. For instance, Webflux uses Jetty while SpringMVC uses Tomcat by default. Internally, Webflux is more like a non-blocking event-loop architecture while SpringMVC traditionally leverages a threadpool with 1 thread per request blocking for I/O.
Check out this article for more details on Spring WebFlux

why does spring cloud stream's #InboundChannelAdapter accept no parameters?

I'm trying to use spring cloud stream to send and receive messages on kafka. The examples for this use a simple example of using time stamps as the messages. I'm trying to go just one step further into a real world application when I ran into this blocker on the InboundChannelAdapter docs:
"A method annotated with #InboundChannelAdapter can't accept any parameters"
I was trying to use it like so:
#InboundChannelAdapter(value = ChannelManager.OUTPUT)
public EventCreated createCustomerEvent(String customerId, String thingId) {
return new EventCreated(customerId, thingId);
}
What usage am I missing? I imagine that when you want to create an event, you have some data that you want to use for that event, and so you would normally pass that data in via parameters. But "A method annotated with #InboundChannelAdapter can't accept any parameters". So how are you supposed to use this?
I understand that #InboundChannelAdapter comes from spring-integration, which spring-cloud-stream extends, and so spring-integration may have a different context in which this makes sense. But it seems un-intuitive to me (as does using an _INBOUND_ChannelAdapter for an output/producer/source)
Well, first of all the #InboundChannelAdapter is defined exactly in Spring Integration and Spring Cloud Stream doesn't extend it. That's false. Not sure where you have picked up that info...
This annotation builds something like SourcePollingChannelAdapter which provides a poller based on the scheduler and calls periodically a MessageSource.receive(). Since there is no any context and end-user can't effect that poller's behavior with his own arguments, the requirement for empty method parameters is obvious.
This #InboundChannelAdapter is a beginning of the flow and it is active. It does its logic on background without your events.
If you would like to call some method with parameters and trigger with that some flow, you should consider to use #MessagingGateway: http://docs.spring.io/spring-integration/reference/html/messaging-endpoints-chapter.html#messaging-gateway-annotation
How are you expecting to call that method? I think there was a miscommunication with your statement "stream extends integration" and Artem probably understood that we extend #InboundChannelAdatper
So, if you are actively calling this method, as it appears since you do have arguments that are passed to it, why not just using your source channel to send the data?
Usually sources do not require arguments as they are either push like the twitter stream that taps on twitter, listen for events and pushes them to the source channel, or they are polled, in which case, they are invoked on an interval defined via a poller.
As Artem pointed, if your intention is to call this method from your business flow, and deal with the return while triggering a message flow, then check his link from the docs.

Blocking message pending 10000 for BLOCKING..using spring websockets

I am facing the following error while using spring websockets:
Use case: On our server side code we have a fucntionality to search values in data base..if the values are not present in database..it will hit a servlet and get the data..The second part i.e., hitting servlet and getting the data is asynchronous call.
So for one request there are multiple things we have to search for in data base..
Example: In request we got a some parameter channel: 1
This channel is mapped to multiple ids say 1 is mapped to 1,2,3,4,5
In websocket once the request comes to server i will extract the channel and get all the id's mapped and run a loop over id's as follows:
for(int i=0;i<ids.length;i++)
{
SomeObject databaseRespObj=callToDatabase(i); //SomeObject contains two fields value exists and string values
if(!databaseRespObj.valuesExists)
{
AsynchronouscallToServelt(i);
//once response received it will send message immediately using session
}
}
While execution of above server side code,some times only i am facing the below error.
java.lang.IllegalStateException: Blocking message pending 10000 for BLOCKING
at org.eclipse.jetty.websocket.common.WebSocketRemoteEndpoint.lockMsg(WebSocketRemoteEndpoint.java:130) ~[websocket-common-9.3.8.v20160314.jar:9.3.8.v20160314]
at org.eclipse.jetty.websocket.common.WebSocketRemoteEndpoint.sendString(WebSocketRemoteEndpoint.java:379) ~[websocket-common-9.3.8.v20160314.jar:9.3.8.v20160314]
at org.springframework.web.socket.adapter.jetty.JettyWebSocketSession.sendTextMessage(JettyWebSocketSession.java:188) ~[spring-websocket-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.socket.adapter.AbstractWebSocketSession.sendMessage(AbstractWebSocketSession.java:105) ~[spring-websocket-4.2.4.RELEASE.jar:4.2.4.RELEASE]
Sorry if the above framing of the question is not clear.Will spring support sending asynchronous messages like normal javax websocket does Session.getAsyncRemote().sendText(String text)
What is the configuration made in spring to send asynchronous messages using websocket session
From what I understand, you have multiple threads sending messages on the same RemoteEndpoint when the asynchronous technique kicks in.
Seems very similar to this :
WebSocket async send can result in blocked send once queue filled
I don't thing you necessarily have to use Futures or mechanisms described in the above post.
What I don't really get is : why doing asynchronous call to servlets ? Ofcourse several could send messages on the same RemoteEndPoint..
But can't you simply make synchronous calls to the relevant classes and keep the same request-response flow that you use when records are found in your database ? :)
UPDATE
Since you added in comments the fact that you need to focus on speed, and since it seems that your current solution is not applicable, let's maybe have a look at the problem from a different angle.
I'm not a websocket expert but as far as I understand what you try to achieve with the asynch servlet calls is not possible.
However, if you change the design/config of your project, this should be achievable.
Personally I use Websockets to be able to send a message to an arbitrary user that did not necessarily made a request - as long as he is connected, he must get the message.
To do this, I simply use the SimpMessagingTemplate class offered by Spring in their websocket support. To send a message to ANY USER THAT I WANT, I do this :
#Autowired
SimpMessagingTemplate smt;
(.......)
smt.convertAndSendToUser(recipient.getUsername(), "/queue/notify", payload);
So in your case, you could, in your loop :
make class instance method calls (instead of a servlet, no network transit, you cannot be faster ! Just a call to your biz-logic / service / whatever)
every time a method returns data, use the SimpMessagingTemplate like in the snippet here above :)
you can still do it asynchronously if you want ! :)
By doing this, you reduce latency (calling servlets adds alot), and have a reliable technique.
You can easily and quickly send thousands of messages to one user or to several users, at your own discretion, without stumbling upon the "10000 for BLOCKING" problem, which probably comes from more than 1 servlet "answering the same question" ;)
To obtain a SimpMessagingTemplate from Spring, you will need to use the <websocket:message-broker> tag or the equivalent non-xml-java-config.
I suggest to check this doc which has more info :
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html
and the following post I created on SO where I am using it (I've got another problem in the post, related to spring configuration and context hierarchies, but at least you have some template code to look at, the code is working) :
Spring Websocket : receiving nothing from SimpMessagingTemplate
Spring : how to expose SimpMessagingTemplate bean to root context ?

Resources