Search code examples
javapostgresqlvert.xjooq

Getting ERROR Connection not open CLOSED when composing Futures using vertx-jooq-classic-reactive: 5.0.1


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).


Solution

  • 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.