I’m trying to use non-blocking action. Following the documentation I’m able to use the first example. I need that the action returns more than one data, so I created a class for that.
Just a note that in the code provided, calculateResponse is a blocking method, and the use of CompletableFuture isn’t providing any benefit. If projectRepository.findAll is doing I/O, then it should be returning a CompletionStage itself, and must be implemented to perform any blocking I/O in an appropriate execution context.
If the whole method is intended to block, then it’s simpler to have it return ListProjectsData directly, rather than wrapping it in a CompletionStage.
Correct. I guess probably the particular method call is part of a larger chain of calls not mentioned above and this method has been wrapped into a CompletableFuture so as to not break the chaining of futures.
So, if I understand I have benefit only on methods that does I/O operations. In this case projectRepository.findAll is the method that does the mongo query.
For the other problem, the code compilation error is the same as IntelliJ: play.sbt.PlayExceptions$CompilationException: Compilation error[cannot find symbol
symbol: method getProjects()
Thanks, very very interesting. Actually I’m using Spring Data MongoDB, so to use reactive access to Mongo I’ve to rewrite all the queries. Could be an interesting challenge.
In the slides there are a lot of techniques example, which of them is better to learn and use?
I had find that Spring Data MongoDB has @Async decorator to create asynchronous query. I don’t know if this is sufficient to create asynchronous query under Play. This matter is too complicated for me :-)
The best options are the ones that use the async MongoDB driver, such as example 6 in that slide deck.
You could also use the reactive streams API, which can be integrated easily with Akka Streams. This might be better if you are expecting a large number of results from the query, as you could handle them in a streaming fashion without loading all results into memory at the same time.
Spring Data now offers a reactive Mongo repository implementation as well, though it uses Spring’s custom API, and would need to be adapted to CompletionStage or Akka Streams.
Since planningRepository.findByDataContains is now returning a CompletionStage, it’s possible that this is using a non-blocking query, but projectRepository.findAll and userRepository.countByProjectsEquals still appear to be blocking.
It is not safe to modify userProjects (a mutable HashMap) from multiple threads, as this code does.
There is a race condition, because listProject can render the view before the asynchronous processing of the results of planningRepository.findByDataContains complete.
The definition of dataProject isn’t included here, but is likely to also be unsafe to modify in this way.
To correct this, you’ll need to use async repositories for all of your queries, and change your logic around to avoid updating mutable collections from asynchronous actions.
Working with CompletionStage can take a little practice to wrap your head around, so it might be worth searching for some online tutorials to help get a hang of it.