Search code examples
spring-integration

spring integration adviceChain on ServiceActivator is not executing the beforeReceive of an advice


I defined my poller with a service activator with adviceChain like this:

   @ServiceActivator(inputChannel = EVENT_CHANNEL,
            adviceChain = {"globalLockAdvice"},
            poller = @Poller(
                    maxMessagesPerPoll = "${event.poller.maxMessagesPerPoll:1}",
                    fixedDelay = "${event.poller.fixedDelay:1000}",
                    receiveTimeout = "${event.poller.receiveTimeout:1000}"))
    public void handleEventMessage(Message<String> message) throws MessagingException {
...
}

@Component
public class GlobalLockAdvice implements ReceiveMessageAdvice {

    private final LockConfiguration lockConfiguration;

    public GlobalLockAdvice(LockConfiguration lockConfiguration) {
        this.lockConfiguration = lockConfiguration;
    }

    @Override
    public boolean beforeReceive(Object source) {
        return lockConfiguration.isLeader();
    }

    @Override
    public Message<?> afterReceive(Message<?> result, Object source) {
        return result;
    }

}

But beforeReceive is not called. When debugging I see 'target' is a ServiceActivator class, resulting in skipping calling the beforeReceive:

@FunctionalInterface
public interface ReceiveMessageAdvice extends MethodInterceptor {

    @Override
    @Nullable
    default Object invoke(MethodInvocation invocation) throws Throwable {
        Object target = invocation.getThis();
        if (!(target instanceof MessageSource) && !(target instanceof PollableChannel)) {
            return invocation.proceed();
        }
...

What am I doing wrong?


Solution

  • The advice chain on the service activator advises the message handler, not the channel polled by the poller.

    To add an advice chain to the poller, you must define the poller as a PollerMetadata bean instead of using the @Poller annotation attributes. @Poller("metadata").

    See the javadocs for @Poller.

    /**
     * Provides the {@link org.springframework.integration.scheduling.PollerMetadata} options
     * for the Messaging annotations for polled endpoints. It is an analogue of the XML
     * {@code <poller/>} element, but provides only simple attributes. If the
     * {@link org.springframework.integration.scheduling.PollerMetadata} requires more options
     * (e.g. Transactional and other Advices) or {@code initialDelay} etc, the
     * {@link org.springframework.integration.scheduling.PollerMetadata} should be configured
     * as a generic bean and its bean name can be specified as the {@code value} attribute of
     * this annotation. In that case, the other attributes are not allowed.
     * <p>
     * Non-reference attributes support Property Placeholder resolutions.