Check whether a JTA transaction is successfully co

2019-08-25 08:57发布

问题:

Is there a way to check if the current transaction is committed or not in JPA entity listeners something like the following?

@ApplicationScoped
public class EntityListener {

    @Inject
    private Event<EntityEvent> event;
    @Inject
    private EntityManager entityManager;
    @Resource
    private UserTransaction userTransaction;

    @PostPersist
    @PostUpdate
    @PostRemove
    public void onChange(Entity entity) {

        // This is only a piece of pseudo code.
        if (userTransaction.isComitted()) {
            // Do something.
        }
    }
}

Entity listeners in JPA 2.1 are treated as CDI beans that depend upon CDI injection(s) and a transaction context along with CDI is available in entity listeners. Those injections are therefore possible in the entity listener (with or without the annotation @ApplicationScoped). The JPA 2.1 specification states,

The persistence provider is only required to support CDI injection into entity listeners in Java EE container environments. If the CDI is not enabled, the persistence provider must not invoke entity listeners that depend upon CDI injection.

When invoked from within a Java EE environment, the callback listeners for an entity share the enterprise naming context of the invoking component, and the entity callback methods are invoked in the transaction and security contexts of the calling component at the time at which the callback method is invoked.

For example, if a transaction commit occurs as a result of the normal termination of a session bean business method with transaction attribute RequiresNew, the PostPersist and PostRemove callbacks are executed in the naming context, the transaction context, and the security context of that component.

Does there exist a way to know whether a transaction is successfully committed or not in JPA entity listener so that a different action or no action at all could be taken accordingly?

I expect a transaction does not get finished in its entirely as soon as a commit occurs and hence, there should exist a way to see, if a commit occurs or not especially, I am looking for a way to simulate a transaction-wide event i.e. an event triggering at the end of a transaction giving the status of the transaction whether the transaction is committed or rolled back.

Using GlassFish Server 4.1 / Java EE 7 having EclipseLink 2.6.0 (JPA 2.1).

回答1:

Please refer the CDI specification docs.

10.4.5. Transactional observer methods

Transactional observer methods are observer methods which receive event notifications during the before or after completion phase of the transaction in which the event was fired. If no transaction is in progress when the event is fired, they are notified at the same time as other observers.

  • A before completion observer method is called during the before completion phase of the transaction.
  • An after completion observer method is called during the after completion phase of the transaction.
  • An after success observer method is called during the after completion phase of the transaction, only when the transaction
    completes successfully.
  • An after failure observer method is called during the after completion phase of the transaction, only when the transaction fails.

The enumeration javax.enterprise.event.TransactionPhase identifies the kind of transactional observer method:

public enum TransactionPhase {
    IN_PROGRESS,
    BEFORE_COMPLETION,
    AFTER_COMPLETION,
    AFTER_FAILURE,
    AFTER_SUCCESS
}

A transactional observer method may be declared by specifying any value other than IN_PROGRESS for during:

void onDocumentUpdate(@Observes(during=AFTER_SUCCESS) @Updated Document doc) { ... }