Announcement Announcement Module
Collapse
No announcement yet.
Programmatically setting rollbackOnly Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Programmatically setting rollbackOnly

    I need to mark a transaction as rollback only. I've tried:
    Code:
    PlatformTransactionManager transactionManager = getTransactionManager();
    DefaultTransactionStatus tx = (..) transactionManager.getTransaction(null);
    tx.setRollbackOnly();
    But it doesn't seem to have any effect. I tried then:
    Code:
    PlatformTransactionManager transactionManager = getTransactionManager();
    Method setRollbackOnly = transactionManager.getClass().getDeclaredMethod("doSetRollbackOnly", DefaultTransactionStatus.class);
    if (setRollbackOnly != null) {
       setRollbackOnly.setAccessible(true);
       setRollbackOnly.invoke(transactionManager, tx);
    }
    And it does in fact set the rollback only property but the execution fails later with:
    Code:
    org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
      at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:465)
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:732)
    Is it possible to mark the transaction as rollback only and continue the execution flow without getting an exception?

    Regards

  • #2
    Your approach of marking the current transaction for rollback looks a bit strange.
    The reference manual shows a cleaner approach. See the last code example in that section for the programmatic approach.

    Regards,
    Andreas

    Comment


    • #3
      In my last approach I was using:
      Code:
      PlatformTransactionManager transactionManager = getTransactionManager();
      transactionManager.rollback(transactionManager.getTransaction(null));
      Which was somewhat cleaner but resulted in the same exception. I tried the example at the reference documentation to no avail. It always fails with the same exception:
      Code:
      Caused by: javax.persistence.RollbackException: Transaction marked as rollbackOnly
        at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:51)
        at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:456)
      I think it's a bug with the JpaTransactionManager which doesn't check properly for the rollback mark.

      Regards

      Comment


      • #4
        After some more tweaks I'm always getting an exception in some point or other. Maybe I'm just trying something that is not designed to behave as I wish. So, the first question should be: Is it possible to mark for rollback something and don't get an exception at all at any point? Because the setRollbackOnly method won't throw anything (and hence the application continues) but once Spring tries to commit the transaction it will throw one exception or other and the flow will be interrupted.

        Comment


        • #5
          I think that exception is by design in order to inform the invoker about the rollback. After all there is a commit expected upon invocation.
          If you really want to discard that, you might introduce an interceptor which catches that exception and swallows it.
          In order to not pollute your code you might then also consider to throw a specific exception and maybe add a matching rollback clause. That way you don't need to fiddle with transactions inside your application.

          Regards,
          Andreas

          Comment


          • #6
            That's unfortunate because even though I could catch the exception in several ways the fact that there is an exception means the flow is interrupted and the return value of the method lost which was the whole purpose of the programmatic approach (mark for rollback transparently without throwing a runtime exception and be able to process the result).

            Comment


            • #7
              Maybe you could redesign your code so that the client invokes a method on class A which in turn delegates to a transactional method in class B. The method in A could then handle any exception as required and return whatever is appropriate to the client.

              Regards,
              Andreas

              Comment


              • #8
                In the end I created a custom rollback exception that contains the return value and I coded a new DWR converter for that kind of exceptions that unwraps the value and transfers it. Not what I was looking for at all :-)

                Comment

                Working...
                X