Does MongoDB Panache support change streams? - quarkus

Does MongoDB Panache offer support for change streams? I cannot find any information about it online.

There is nothing specific inside MongoDB with Panache for change streams.
You can the underlying collection or database from your Panache entity/repository via the collection() or database() method. Then you can use the standard watch() method to define a change stream.

Related

MongoDB Panache Best Practices for Multi-Document Transactions

Regarding the quote below in the MongoDB Panache documentation [https://quarkus.io/guides/mongodb-panache]
MongoDB offers ACID transactions since version 4.0. MongoDB with Panache doesn’t provide support for them.
As such, is there a recommended approach or a best practice on handling Multi-Document transactions to ensure atomicity?
Consider the example:
public void buyCarTest() {
carRepository.increaseStock(1);
cashRepository.decreaseCash(10000);
}
If we were to do it manually, it would be:
check if the write operation into 2nd repository failed, and
if so, revert changes made in carRepository
This approach seems tenuous at best especially if there are more than 2 repositories I'm writing into.
Thanks.
What you propose is what is called a compensation and it is tricky to implements.
I'd rather use an event based mechanism for this: you send the two events and asynchronously they are processed so a failure of one of the tenant (the stock manager) will not impact the second one.
You can also use MongoDB transaction but for this you will need to use the MongoDB API instead of Panache (so get the collection from your entity and use it).
Transaction support for MongoDB is a work in progress (see https://github.com/quarkusio/quarkus/pull/7222) you can watch this issue to be notified when it'll be implemented.

Using Spring JPA Specification with OData Queries

so i have a spring boot application and my data source is MySQL via JPA. I am trying to introduce Odata queries to my API's and then fetch data based on those odata params. I was wondering if there are any utils or external libraries i can use to parse the odata query then construct the JPA Specification. I have looked into olingo but im not sure if it is exactly what i am looking for. I was thinking of parsing the query text, and constructing the jpa specifications manually(maybe use reflection is necessary), but if anyone has any tips or advice on how to better approach this it would be much appreciated!!
I was thinking of doing something similar to this but with odata instead. Only issue i see is making this dynamic enough to handle every complex odata query coming in.
https://www.baeldung.com/rest-api-search-language-spring-data-specifications

Update specific field in mongodb of a spring-boot app using spring-data feature

Can we update only specific field in mongodb of a spring-boot app using spring-data feature?
Currently, spring-data provides a save method to update as well as save in a document. If two sets of concurrent updates happen in a single document for the different field, we can lose information. I know we can solve the problem using Mongotemplate. Can we solve these problems using spring-data?
Thanks
What about Optimistic Locking feature?
The #Version annotation provides syntax similar to that of JPA in the context of MongoDB and makes sure updates are only applied to documents with a matching version. Therefore, the actual value of the version property is added to the update query in such a way that the update does not have any effect if another operation altered the document in the meantime. In that case, an OptimisticLockingFailureException is thrown.
See Spring Documentation: https://docs.spring.io/spring-data/mongodb/docs/2.0.9.RELEASE/reference/html/#mongo-template.optimistic-locking
With MongoDB 4.0, ACID transactions have arrived in the Document store, enforcing all-or-nothing execution and maintaining data integrity. So, let’s get straight to it by looking at both the synchronous and the reactive execution models.
you could write code like this:
#Transactional
void insertDocuments() {
operations.insert(documentOne);
operations.insert(documentTwo);
}
Complete Spring's documentation:
https://spring.io/blog/2018/06/28/hands-on-mongodb-4-0-transactions-with-spring-data

Database event listener using spring boot

I need to attach a listener to a table in db
which should call a spring boot method, once CRUD operation is performed in the table(pre listeners and post listeners)
the entry can be made from any source
how can i do that in spring boot?
If the entity can be created from any source - e.g. manual insert - this is something which is outside of the scope and context of your running application.
What you're describing is known as the CDC (change data capture) pattern.
To implement CDC in this case you need to use the instrumentation of the underlying database - for example triggers.
As I see this is tagged with MongoDb - triggers are not an option as mongodb doesn't have support for triggers.
If you are using MongoDb v3.6+ you can leverage the new Change Streams feature. This is the official example with Java.
Change streams allow applications to access real-time data changes
without the complexity and risk of tailing the oplog. Applications can
use change streams to subscribe to all data changes on a single
collection, a database, or an entire deployment, and immediately react
to them. Because change streams use the aggregation framework,
applications can also filter for specific changes or transform the
notifications at will.
If you are using earlier versions of MongoDb you can monitor the oplog or use tailable cursors with capped collections.
Another approach would be to look into a 3rd party solution that turns everything happening in the DB as event streams - like for example debezium.
This article explains how to call any program from DB-Trigger.
Therefore, you can just create a Spring Boot java app and make the sys call to your app.
Similar mechanism is also available in Oracle and other DB.

ReactiveCrudRepository to use Hibernate in spring

Is it possible to use Hibernate and RDBMS(Mysql, Postgres etc) with ReactiveCrudRepository instead of CrudRepository? I have tried some samples with Spring Data Jpa and Hibernate, but couldn't get it done. I was only able to find a few samples on ReactiveCrudRepository for MongoDB and cassandra.
Is it possible to use Hibernate and Mysql with ReactiveCrudRepository instead of CrudRepository?
TL;DR:
Not with Hibernate and MySQL, but with R2DBC and Postgres, Microsoft SQL Server or H2.
Take a look at Spring Data R2DBC.
Long Version
Why not JPA?
With Hibernate/JPA included this won't happen in the foreseeable future.
JPA is based on the idea that you load part of your data model into memory, manipulate the resulting object model and let JPA transform these changes.
All this within a single transaction.
This is kind of the opposite how one deals with a reactive store where you try to make atomic changes and try to decouple the loading, processing and storing and all this without blocking.
Why not JDBC?
So we have to look at the technology level below JPA: JDBC.
But JDBC is still blocking: You send a SQL statement to your database and then JDBC will block until you get the result.
And again this goes against the idea of reactive: Never block.
One could wrap this in a thread pool to mitigate this to some extent, but that is more of a workaround than a solution.
Why R2DBC?
There are some suitable drivers for some databases that could be used for reactive repositories.
But they are proprietary and thereby not a good basis for something that really should eventually work across all (relevant) relational databases.
For some time the Spring Data team hoped that ADBA would fill that gap.
But discussions on the mailing list made it clear that ADBA was not aiming for reactive but only for asynchronous.
Again not what we needed for a reactive repository abstraction.
So early in 2018 various people living at the intersection or reactive and relational decided that we need a standard for reactive database access.
R2DBC (Reactive Relational Database Connectivity)
is a proposal for such a standard.
The hope is that it either helps convincing Oracle to move ADBA to a reactive approach or if that doesn't happen it becomes the standard itself.
And with already three implementations available chances for the second option look promising.
R2DBC itself is mainly an SPI, i.e. an API that is to be implemented by database providers.
The SPI is designed in a way that puts minimal requirements on implementers.
But this also makes R2DBC somewhat cumbersome to use.
The idea is that other libraries will step up and build libraries designed for usability on top of that SPI, as it happened with JDBC.
Spring Data R2DBC
Spring Data R2DBC is one such library and it offers what you asked for: Support for ReactiveCrudRepository although it is independent of JPA/Hibernate and there is no support for MySQL yet.
State of the projects
Both R2DBC and Spring Data R2DBC didn't have a production release yet and it will take at least several months to get there.
Spring Data R2DBC just released the first milestone.
See the release article for its current capabilities.
R2DBC is on its 6th milestone. See the release article for details.
See also this answer: Why does Spring not provide reactive (non-blocking) clients for relational databases?
Original answer as a reference for archeologists:
As of now (Jan 2017) it is not possible.
The currently relevant release for the reactive part of Spring Data is Spring Data Kay M1 (You can check if there is a newer version available on the project home page)
And a blog post from the Spring Data team about that release and specifically the reactive parts in it starts with (emphasis mine):
Spring Data Kay M1 is the first release ever that comes with support for reactive data access. Its initial set of supported stores — MongoDB, Apache Cassandra, and Redis — all ship reactive drivers already, which made them very natural candidates for such a prototype.
The reason is that there is no standard non-blocking way to access a relational database. So only those that support this kind of API are supported right now.
One could implement a ReactiveCrudRepository using JPA or JDBC and delegate the work to a thread pool. This would provide an async API on the outside, but would still consume the resources for the Threads and block between independent data accesses, so only a small part of the benefits of the reactive approach would get realized.
Hibernate started a new Hibernate Reactive subproject for reactive streams support which provides Hibernate/JPA similar APIs to access RDBMS. But unfortunately at the moment, Spring Data does not support it. So there is no a ReactiveCrudRepoisoty for Hibernate Reactive.
But you can integrate Hibernate with Spring yourself and get reactive support.
Define a persistence.xml file, note the provider class must be specified as the one in Hibernate Reactive.
Declare a Mutiny.SessionFactory bean.
Then inject it in your repository class.
I have created a complete example demos Hibernate Reactive + Spring.
Update: Till now Spring team has no plan to support it, if you are willing to taste other framework, check Quarkus and Micronaunt, both have seamless Hibernate Reactive support. Check my Quarkus Hibernate Reactive example and Micronaut Hibernate Reactive example.
According to quote from previous answer
One could implement a ReactiveCrudRepository using JPA or JDBC and delegating the work to a thread pool. This would provide an async API on the outside, but would still consume the resources for the Threads and block between independent data accesses, so only a small part of the benefits of the reactive approach would get realized.
James Ward claims it can be non-blocking. I mean I asked him:
yeah ok, but isn't ScalikeJDBC-Async doing exactly the same? just putting query invocation into another thread pool?
and he replied
No because ScalalikeJDBC-Async uses https://github.com/mauricio... which is actually a non-blocking (NIO) JDBCish database driver.
source
So you can be reactive by replacing hibernate + spring data with postgresql-async (should work with mysql).
you could try with quarkus framework and panache mongo hibernate reactive repositories. https://quarkus.io/guides/mongodb-panache .It is easy manage a reactive repository over mongoDB, It is later but hope helps.

Resources