Search code examples
javajpajava-ee-6openjpa

OPenJPA: : How to commit entities when an exception is thrown


In an EJB project, for a specific exception, I want to still persist the entity which is currently rolledback. Creating and flushing the entity in the exception block does not help. The transaction is still rolled back. I tried to detach the entity from the current transaction and persist it in a new transaction. But that results in an "entity managed by another transaction " error. How can I achieve this?

The project is built on JEE6 with EJB 3.1. Persistence is with OpenJPA.


Solution

  • The EJB 3.1 spec describes how you can accomplish this in section 14.2.1:

    The Bean Provider defines application exceptions. Application exceptions that are checked exceptions may be defined as such by being listed in the throws clauses of the methods of the bean’s business interface, no-interface view, home interface, component interface, and web service endpoint. An application exception that is an unchecked exception is defined as an application exception by annotating it with the ApplicationException metadata annotation, or denoting it in the deployment descriptor with the application-exception element

    and

    An application exception does not automatically result in marking the transaction for rollback unless the ApplicationException annotation is applied to the exception class and is specified with the rollback element value true or the application-exception deployment descriptor element for the exception specifies the rollback element as true. [...]

    The Bean Provider must do one of the following to ensure data integrity before throwing an application exception from an enterprise bean instance:

    • Ensure that the instance is in a state such that a client’s attempt to continue and/or commit the transaction does not result in loss of data integrity. For example, the instance throws an application exception indicating that the value of an input parameter was invalid before the instance performed any database updates.
    • If the application exception is not specified to cause transaction rollback, mark the transaction for rollback using the EJBContext.setRollbackOnly method before throwing the application exception. Marking the transaction for rollback will ensure that the transaction can never commit.

    That is, if you want the transaction to commit when an exception is thrown, you must designate that exception as application exception.

    Or you could start a separate transaction, but as JEE does not support nested transactions, this is only possible once the previous transaction has completed.