Does the following code block the call, if so how do I make it non-blocking? i.e. making the use of Reactive Java Stream useless? How can I paginate without making the call blocking?
Currently I have a webClient calling to a backend service that returns a Flux<Item> and according to specs I need to return a ResponseEntity<ItemListResponse> where I have provide a paginated response
code inside the controller method looks like ->
// getItems method was initially returning a Flux but my method was failing to paginate it so now that method returns a Mono<List<Item>>
// I would really like to see how I can make this work with Flux!
return webClient.getItems(...required params...)
.map(r -> {
// we get offset and limit from query params
var paginatedItems = listPaginator.applyPagination(r, offset, limit)
// assembleItemResponse method maps all values from backend service to new response required by client
List<ItemResponse> itemResponseList = paginatedItems.stream()
.map(this::assembleItemResponse)
.collect(Collectors.toList());
return ResponseEntity.ok()
.body(ItemListResponse.builder()
.itemCount(r.size())
.pagesize(itemResponseList.size())
.listItems(itemResponseList)
.build());
});
Does applying Pagination on response using Spring Webflux make it blocking?
There's nothing inherently blocking about pagination, but the normal Spring Data way to achieve that is by using a PagingAndSortingRepository to query the data layer for only the results you need for that particular page (as oppose to querying the data layer for all possible results then filtering, which could have a huge performance impact depending on the data size.) Unfortunately that approach is blocking. The PagingAndSortingRepository doesn't as of yet have a reactive equivalent.
However, that doesn't appear to be what you're doing here. A complete example here would be helpful, but it looks like r is a list of items, and then you're applying a listPaginator to that entire list to reduce it down. If that's the case then there's no reason why it would necessarily be blocking, so it should be safe. However, it's impossible to say for certain without knowing the specific behaviour of the applyPagination and assembleItemResponse methods. If those methods are blocking then no - you're not safe here, and you need to consider another approach (exactly what approach would require a more complete example.) If those methods are non-blocking (they just deal with the data they have, don't call any further web / db services, etc.) then you're ok.
Separately, you might consider looking at Blockhound which will be able to tell you for certain whether you have any blocking calls where they shouldn't be.
Related
I am having some problems with Spring #Transactional and hope to find a solution here. I have a method in the service labeled as #Transactional which works by calling a method to request data via HTTP protocol (I'm using Apache HttpClient now), parsing the response and writing the result to the database. Since it all works in one method I'm afraid that this may cause transaction cancellation, because my project has a transaction time limit and request from external API may be really long.
Here I would like an answer on how to most correctly separate HTTP request+response parsing and database operations in such a case. As an option it is possible to have two methods one for transaction and the other for the rest of the logic, but I already have an assumption that there is a generally accepted design pattern for such tasks.
Different types of I/O in single #Tranactional method could cause trouble. If the API call responds very slowly for a while, this method would hold the borrowed Connection while waiting for the response.
You must break the single method.
Method1 will make the rest call. Response received with http status code 200 OK. Store it in suitable collection.
Method 2 will process records from method 1. You can explore on TransactionTemplate.
Refer - Sample code for reference, Sample code here
I've got a REST service written in Java using Spring and associated libraries including Reactor, using Mono to wrap expensive operations.
I am refactoring DB related code with the usual CRUD methods. I've come across examples with a return type of Mono<Void>, which to me would make sense for methods where one only cares about success or failure. For my use case things like update or especially delete a database entry.
In actuality I've been hitting all sorts of friction in trying to use Mono<Void> which came to a head for me when I had an area where I had two methods that could be done in parallel, one of which was returning Mono<Void>, and when I went to use Mono.zip to combine the results that didn't work. And I couldn't find any method to combine them, maintain the parallelism, and use Mono<Void>. What does work is mapping the Mono<Void> to something like Mono<Boolean> with a dummy Boolean.TRUE.
So at this point I am wondering what the best practice is when the method doesn't have a real return type, just indicate success or error. Should I be trying to use Mono<Void> with some techniques I am missing or just use a dummy type like Mono<Boolean>?
I have following setup:
HTTP request arrives on REST endpoint and I receive it in my Application Service.
Application service maps request to command C1 and forwards it to aggregate using commandGateway.sendAndWait(new C1(restPostBody));.
Aggregate is loaded from repo, new command is applied and new event is produced an saved to store.
At this point in time, I need to enrich this event and use it as response of REST call.
So far I can see this options:
Use view projector, and project new event to create view model that can be forwarded as response in REST call. I guees here I would need to use queryGateway.subscriptionQuery(... and sqr.updates().blockFirst() for waiting for event to be processed by projector and then create response. Also, I guess this should be synchronous, since projection could get out of sync if system fails between storing event to DB and storing projection to DB?
Use some event enricher after event is published from aggregate and add needed properties to it and add response to REST call. This is similar to Projection, but in this case I would not save it to DB, since only time I need the data is as response to REST endpoint at the time command is issued. This should be definitelly synchronous, since if something fails, I would loose response. In case of async - I would need to have Aggregate handle duplicate events, and still emit events to event enricher but without storing to db. This seems to make things a lot complicated.
Are there any best practices related to this?
UPDATE
what I'm having currently is:
#Autowired
public void configure(EventProcessingConfigurer configurer){
configurer.usingSubscribingEventProcessors();
}
for synchronous Event processing in aggregate and view-model. Then I can query view model using (looks a bit ugly - is there better way?)
try {
sc = queryGateway.query(new MyQuery("123", "123),
ResponseTypes.instanceOf(SomeView.class)).get();
}
catch (InterruptedException e) {
e.printStackTrace();
}
catch (ExecutionException e) {
e.printStackTrace();
}
And I can return this SomeView as response on REST api.
So, #bojanv55, you're trying to spoof your application to be a synchronous set up, whilst the command-event-query approach with Axon Framework enforces you to go the other way.
Ideally, your front-end should be compliant to this situation.
Thus, if you hit an end point which publishes a command, then you'd do a fire and forget. The events updating your query model will be pushed as updates, as they happen, to the front-end. So shortly, embracing the fact it's asynchronous should, in the end, make everything feel more seamless.
However, that's easier said then done; you're asking this question with a reason of course.
I personally like the usage of the subscription query, which you're also pointing towards, to spoof the operation to become synchronous.
This repository by Frans shows how to do this with Axon Framework quite nicely I think.
What he does, is handle the REST operation and first dispatching a subscription query for the thing you know will be updated pretty soon.
Secondly, the command is dispatched to the aggregate, the aggregate makes a decision to publish an event and the event updates the query model.
The query model update then constitutes in an update being emitted towards your subscription query, allowing you to only return the result as soon as the query model has actually be adjusted.
Concluding, I'd always recommend my first suggestion to embrace the asynchronous situation you're in. Secondly though, I think the subscription query solution I've just shared could resolve the problem you're having as well.
Hope this helps you out!
In the context of an Android development using Cloud Firestore database, I am writing the method get(int id) : MyDO of my DAO class. Since, in Firestore, all the operations are asynchronous, the use of the return, a MyDO object, must take account of this asynchronous aspect.
A first solution would be the callback. The method get I'm writting could accepts a callback parameter (as a second parameter) in which I would put the code, in the call to get, that uses the object MyDO. However, I don't want it.
I know a bit about promises, or even await/async. Would these notions be useful in this context?
There are no promises in Java nor await/async, only in Javascript you can find that. More informations here.
In Android, instead of returning a Promise it retruns a Task.
So if you don't want to use a custom callback, you might consider using the following solution:
Firestore - Merging two queries locally
I am fetching data from several different APIs. They are rest and soap web services. I have one id that I pass to each API one by one and get data in return. But each API takes few seconds to return the result and so the final response object that I create takes too much time.
My application is a Spring 4 Rest Service. What is the best way to call all these several APIs in parallel so that my Response time reduces to as less as possible.
Thanks.
You can use #Async annotation. You can find an example here
Daniel's answer is right but I would like to add something more to it. If you want to do something with your results but don't want to block with Future#get then I would suggest you to use CompletableFuture class.
It will let you add various actions which will be triggered on its completion.
There is also a really nice article on how to use CompletableFuture with Spring's #async annotation. Here it the link. Completable futures with Spring async