micronaut-projects / micronaut-data

Ahead of Time Data Repositories
Apache License 2.0
459 stars 195 forks source link

TransactionalEventListener fails over upgrade Micronaut-data #2826

Open bweefting opened 4 months ago

bweefting commented 4 months ago

Expected Behavior

In our codebase we use the micronaut TransactionalEventListener to perform logic just before completion of a transaction. Expected this code to work after upgrading.

Actual Behaviour

That code stopped working after an upgrade of micronaut, specifically micronaut-data. (from 4.3.0 to anything higher)

Steps To Reproduce

Reproduced in separate module with just 2 beans:

@Singleton
public class TxLead {

    @Inject
    private ApplicationEventPublisher<String> eventPublisher;

    @Transactional
    public void lead() throws SQLException {
        System.out.println("Before publish");
        eventPublisher.publishEvent("something");
        System.out.println("After publish");
    }
}

and

@Singleton
public class TxFollow {
    @TransactionalEventListener(TransactionalEventListener.TransactionPhase.BEFORE_COMMIT)
    public void becauseOfEvent(final String event) {
        System.out.println("Listener to event " + event);
    }
}

This setup works correctly with the following versions:

4.3.3 4.3.0 After upgrading micronaut data to 4.3.1 (or any newer up to 462) the listener does not act/print anymore. ### Environment Information - On Windows 11 - openjdk 17.0.9 ### Example Application _No response_ ### Version 4.3.3
temofey1989 commented 3 months ago

I have faced to the similar problem working with Micronaut (4.3.7) with Data R2DBC and Kotlin. I my code

@Singleton
open class BookLoggingListener {

    @TransactionalEventListener
    open fun onCreated(event: BookCreated) {
        ...
    }
}

Every time I see this message:

16:38:50.521 [reactor-tcp-nio-1] DEBUG i.m.t.a.TransactionalEventListener - No active transaction, skipping event ...

After some investigation I have found some weird thing...

In TransactionalEventInterceptor there is such a code:

@Singleton
@Internal
public class TransactionalEventInterceptor implements MethodInterceptor<Object, Object> {
    ...
    @Override
    public Object intercept(MethodInvocationContext<Object, Object> context) {
        ...
        transactionEventInvocation.transactionManager
            .findTransactionStatus()
            .ifPresentOrElse(transactionStatus -> {
        ...
    ...
}

If you go to the implementation of the .findTransactionStatus() it will lead you to the SynchronousTransactionOperationsFromReactiveTransactionOperations class. And in this class you'll see this:

@Internal
public final class SynchronousTransactionOperationsFromReactiveTransactionOperations<T> implements TransactionOperations<T> {
    ...
    @Override
    public Optional<? extends TransactionStatus<?>> findTransactionStatus() {
        return Optional.empty();
    }
    ...
}

So this feature appears to be disabled... 😄

dstepanov commented 3 months ago

@temofey1989 This feature is not supported for the reactive transactions

dstepanov commented 3 months ago

@bweefting Are you using reactive TX manger? Can you please create a sample app?

temofey1989 commented 3 months ago

@dstepanov Thanks for the quick feedback. Can I ask you if you have a plan to support this feature in future for Reactive Transactions? Maybe this question also related to #2826. Thanks.

dstepanov commented 3 months ago

Not sure it can be possible. You can get ReactiveConnectionStatus you can add a callback yourself.

strmik commented 2 months ago

@temofey1989 This feature is not supported for the reactive transactions

@dstepanov Could this be perhaps documented in the annotation's javadoc please? Just spent some time on this problem until I found this ticket/comment. Maybe I missed this in docs/guides, I am not sure.

Thanks.

sdelamo commented 2 months ago

@temofey1989 This feature is not supported for the reactive transactions

@dstepanov Could this be perhaps documented in the annotation's javadoc please? Just spent some time on this problem until I found this ticket/comment. Maybe I missed this in docs/guides, I am not sure.

Thanks.

@wetted please, documenta that Transactional Events are not supported for reactive transactions