5

Getting Below error , while calling JPA method, frequently in Hibernate 6

org.springframework.dao.InvalidDataAccessApiUsageException: Illegal pop() with non-matching JdbcValuesSourceProcessingState at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:368)

ozkanpakdil
  • 3,199
  • 31
  • 48
Jana
  • 239
  • 2
  • 11
  • Let's continue that discussion on Zulip: https://hibernate.zulipchat.com/#narrow/stream/132094-hibernate-orm-dev/topic/Illegal.20pop.28.29.20error – Christian Beikov Feb 06 '23 at 11:47

3 Answers3

3

For everyone who has this problem and uses Quarkus 3 with Vertx bare Api.

I fix this error by forcing the JDBC Call to the Vertx Eventbus thread by wrapping it in a EvenBus Consuming function as described in the official documentation, and fiddling around with @WithTransaction, @WithSession, @WithSessionOnDemand or Panache.withTransaction{}.

This results in code which I'm sure gives me cancer in the long run, as the revenge of karma and the coding gods. But hey, it's temporary code as I migrate my vertx code to mainly quarkus with sparkles of vertx.


    fun createToken(userId: String): Future<String> {
        val promise = Promise.promise<String>()
        eventBus.request<String>("createTokenMsg", userId)
            .onSuccess { msg -> promise.complete(msg.body()) }
            .onFailure(promise::fail)
        return promise.future()
    }

    @ConsumeEvent("createTokenMsg")
    fun createTokenMsgConsume(msg: Message<String>) {
        val userId = msg.body()

        createToken(userId).subscribe().with(
            { msg.reply(it.token) },
            { error: Throwable ->
                val txt = "Fail to create token for user id $userId"
                logger.log(Level.SEVERE, txt, error)
                msg.fail(500, txt)
            }
        )
    }

    @WithSession
    fun createToken(userId: String): Uni<TokenIdEntity> {
        return Panache
            .withTransaction { repository.findByUserId(userId) }
            .chain { found: TokenIdEntity? ->
            val token = found ?: TokenIdEntity(userId = userId)
            token.regenrateToken()

            Panache.withTransaction { repository.persistAndFlush(token) }
        }
    }

You can use it with Objects to, you hate to use the JsonObject

Not an ideal solution because:

  • You misuse the eventbus for something which should be a function call (which introduce a lot of overhead)
  • If your code runs in a vertx cluster, it may be consumed by another instance
  • You loose your stacktrace at this point, you can log the .onFailure method of the eventbus.request-Future but the trace is lost at this point. (which sucks big time for debugging)

Disclaimer

I am not a very experienced user of Hibernate-Reactive, Panache and Quarkus so maybe this solution is shooting a sparrow with a shotgun , where you miss all of your 7 rounds and the bird dies of old age, but it works for me at a point where the other answers , were not descriptive enough or does not work.

The @Transactional solution does not work for me because quarkus takes an issue to call JTA transactions from an io Thread

io.quarkus.runtime.BlockingOperationNotAllowedException: Cannot start a JTA transaction from the IO thread.

But I'm curious about better solutions and hope that my solution maybe leads in a direction for a better solution.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
user9959059
  • 31
  • 1
  • 2
1

We stumbled upon the same problem in our project where we were passing entity with OneToMany and ManyToOne relations with lazy loading to a method returning CompletableFuture. As a workaround we prepared DTO used for further operations outside of the method, passed it instead of the entity object and it worked like a charm

Bartek
  • 11
  • 1
0

In my system Spring Boot and Hibernate manage the database. To still get access to the entity manager I have to use

@PersistenceContext(type = PersistenceContextType.TRANSACTION)
private final EntityManager entityManager;

The important part here is PersistenceContextType.TRANSACTION, when I used PersistenceContextType.EXTENDED I got that error. Especially in connection with other transactions.

So I added @Transactional(propagation = Propagation.REQUIRES_NEW) to my methods to be safe.

Now I'm completely error free.

Jan
  • 1,032
  • 11
  • 26