I have an issue when multiple Futures are being composed in order to perform update Book table and insert/delete certain rows in intermediate tables _Category_Book_ and _Author_Book_ since Book is connected with Many-To-Many relationship with Author and Category. Error message that I get in console is:
ERROR com.ns.vertx.pg.BookJooqQueries - Error, something failed in deleteCategoryBookFuture.compose(..)! Cause: io.vertx.core.VertxException: Connection not open CLOSED
Also, I am using mixture of DAO instances and execute() method on instance of ReactiveClassicGenericQueryExecutor class. This is repo link to my class where I am getting this error and this is HttpVerticle where routes, DAOs and other configuration is taking place for my RESTful web services.
I don't know if there is a possibility that I've "over-composed" Future instances and that's what's causing this error, but as I understood composition is used when certain operations (Insert/Delete/Update) need to be performed in sequential order and all have to succeeded.
Libraries I am using:
Vert.x version: 3.8.2
vertx-jooq-classic-reactive: 5.0.1
postgresql: 42.2.2 (Postgres DB is version 11.7 on my machine)
NOTE: I have these changes made in my book_CRUD branch, not to be mistaken with master (as I don't want to merge these not fully functional changes).
I've (to be more honest @jklingsporn) managed to find a solution a solution to fix issue. Problem was that (as much as I understood) is to compose not Future instances, but there right-hand side values (that is method invocations). For example, I had my code written like this:
Set<Long> deleteCategoryIdsSet = HashSet();
Future<Integer> insertBCFuture = categoryBookDAO.insert(bookCategories);
Future<Integer> deleteCategoryBookFuture = queryExecutor.execute(dsl -> dsl
.deleteFrom(CATEGORY_BOOK)
.where(CATEGORY_BOOK.BOOK_ID.eq(Long.valueOf(bookId)))
.and(CATEGORY_BOOK.CATEGORY_ID.in(deleteCategoryIdsSet)))
Future<Integer> retVal = insertBCFuture.compose(res -> deleteCategoryBookFuture)
.setHandler(finalResRetVal -> {
// handle 'finalResRetVal'
..});
...and changed it to this as @jklingsporn suggested:
return queryExecutor.execute(dsl -> dsl
.deleteFrom(CATEGORY_BOOK)
.where(CATEGORY_BOOK.BOOK_ID.eq(Long.valueOf(bookId)))
.and(CATEGORY_BOOK.CATEGORY_ID.in(deleteCategoryIdsSet)))
.compose(res -> categoryBookDAO.insert(bookCategories));
In that (solved) way Future code does not get magically delayed and error doesn't show up and deletes and inserts are successfully performed.