diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/advice/AbstractHandleMessageAdvice.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/advice/AbstractHandleMessageAdvice.java index bbd6aa8739..810f92d229 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/handler/advice/AbstractHandleMessageAdvice.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/advice/AbstractHandleMessageAdvice.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.integration.context.IntegrationObjectSupport; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHandler; @@ -30,9 +31,11 @@ import org.springframework.messaging.MessageHandler; * for the {@link MessageHandler#handleMessage(Message)}. * * @author Artem Bilan + * @author Gary Russell + * * @since 4.3.1 */ -public abstract class AbstractHandleMessageAdvice implements HandleMessageAdvice { +public abstract class AbstractHandleMessageAdvice extends IntegrationObjectSupport implements HandleMessageAdvice { protected final Log logger = LogFactory.getLog(this.getClass()); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/advice/IdempotentReceiverInterceptor.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/advice/IdempotentReceiverInterceptor.java index 134a345d38..1d15425f7b 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/handler/advice/IdempotentReceiverInterceptor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/advice/IdempotentReceiverInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2017 the original author or authors. + * Copyright 2014-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,16 +19,10 @@ package org.springframework.integration.handler.advice; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.integration.IntegrationMessageHeaderAccessor; import org.springframework.integration.MessageRejectedException; import org.springframework.integration.core.MessageSelector; import org.springframework.integration.core.MessagingTemplate; -import org.springframework.integration.support.DefaultMessageBuilderFactory; -import org.springframework.integration.support.MessageBuilderFactory; -import org.springframework.integration.support.utils.IntegrationUtils; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; @@ -46,30 +40,28 @@ import org.springframework.util.Assert; * {@code requestMessage} isn't accepted by {@link MessageSelector}. *
* The {@code idempotent filtering} logic depends on the provided {@link MessageSelector}. - *
+ *
* This class is designed to be used only for the {@link MessageHandler#handleMessage}, * method. * * @author Artem Bilan + * @author Gary Russell + * * @since 4.1 * @see org.springframework.integration.selector.MetadataStoreSelector * @see org.springframework.integration.config.IdempotentReceiverAutoProxyCreatorInitializer */ -public class IdempotentReceiverInterceptor extends AbstractHandleMessageAdvice implements BeanFactoryAware { +public class IdempotentReceiverInterceptor extends AbstractHandleMessageAdvice { private final MessagingTemplate messagingTemplate = new MessagingTemplate(); private final MessageSelector messageSelector; - private volatile MessageChannel discardChannel; + private MessageChannel discardChannel; - private volatile boolean throwExceptionOnRejection; + private String discardChannelName; - private volatile MessageBuilderFactory messageBuilderFactory = new DefaultMessageBuilderFactory(); - - private volatile boolean messageBuilderFactorySet; - - private BeanFactory beanFactory; + private boolean throwExceptionOnRejection; public IdempotentReceiverInterceptor(MessageSelector messageSelector) { Assert.notNull(messageSelector, "'messageSelector' must not be null"); @@ -120,19 +112,31 @@ public class IdempotentReceiverInterceptor extends AbstractHandleMessageAdvice i this.discardChannel = discardChannel; } - @Override - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = beanFactory; + /** + * Specify a channel name where rejected Messages should be sent. If the discard + * channel is null (the default), duplicate Messages will be enriched with + * {@link IntegrationMessageHeaderAccessor#DUPLICATE_MESSAGE} header + * and returned as normal to the {@code invocation.proceed()}. However, + * the 'throwExceptionOnRejection' flag determines whether rejected Messages + * trigger an exception. That value is evaluated regardless of the presence + * of a discard channel. + *
+ * If there is needed just silently 'drop' rejected messages configure the + * {@link #discardChannel} to the {@code nullChannel}. + *
+ * Only applies if a {@link #setDiscardChannel(MessageChannel) discardChannel} + * is not provided. + * @param discardChannelName The discard channel name. + * @see #setThrowExceptionOnRejection(boolean) + * @since 5.0.1 + */ + public void setDiscardChannelName(String discardChannelName) { + this.discardChannelName = discardChannelName; } - protected MessageBuilderFactory getMessageBuilderFactory() { - if (!this.messageBuilderFactorySet) { - if (this.beanFactory != null) { - this.messageBuilderFactory = IntegrationUtils.getMessageBuilderFactory(this.beanFactory); - } - this.messageBuilderFactorySet = true; - } - return this.messageBuilderFactory; + @Override + public String getComponentType() { + return "idempotent-receiver-interceptor"; } @Override @@ -140,8 +144,9 @@ public class IdempotentReceiverInterceptor extends AbstractHandleMessageAdvice i boolean accept = this.messageSelector.accept(message); if (!accept) { boolean discarded = false; - if (this.discardChannel != null) { - this.messagingTemplate.send(this.discardChannel, message); + MessageChannel theDiscardChannel = obtainDiscardChannel(); + if (theDiscardChannel != null) { + this.messagingTemplate.send(theDiscardChannel, message); discarded = true; } if (this.throwExceptionOnRejection) { @@ -150,8 +155,11 @@ public class IdempotentReceiverInterceptor extends AbstractHandleMessageAdvice i } if (!discarded) { - invocation.getArguments()[0] = getMessageBuilderFactory().fromMessage(message) - .setHeader(IntegrationMessageHeaderAccessor.DUPLICATE_MESSAGE, true).build(); + invocation.getArguments()[0] = + getMessageBuilderFactory() + .fromMessage(message) + .setHeader(IntegrationMessageHeaderAccessor.DUPLICATE_MESSAGE, true) + .build(); } else { return null; @@ -160,4 +168,18 @@ public class IdempotentReceiverInterceptor extends AbstractHandleMessageAdvice i return invocation.proceed(); } + private MessageChannel obtainDiscardChannel() { + if (this.discardChannel == null) { + if (this.discardChannelName != null) { + if (getChannelResolver() == null) { + throw new IllegalStateException("No channel resolver available to resolve the discard channel '" + + this.discardChannelName + "'"); + } + this.discardChannel = getChannelResolver() + .resolveDestination(this.discardChannelName); + } + } + return this.discardChannel; + } + } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/dsl/transformers/TransformerTests.java b/spring-integration-core/src/test/java/org/springframework/integration/dsl/transformers/TransformerTests.java index 4e5838627f..4f4c12a26d 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/dsl/transformers/TransformerTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/dsl/transformers/TransformerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 the original author or authors. + * Copyright 2017-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -323,7 +323,7 @@ public class TransformerTests { public IdempotentReceiverInterceptor idempotentReceiverInterceptor() { IdempotentReceiverInterceptor idempotentReceiverInterceptor = new IdempotentReceiverInterceptor(new MetadataStoreSelector(m -> m.getPayload().toString())); - idempotentReceiverInterceptor.setDiscardChannel(idempotentDiscardChannel()); + idempotentReceiverInterceptor.setDiscardChannelName("idempotentDiscardChannel"); idempotentReceiverInterceptor.setThrowExceptionOnRejection(true); return idempotentReceiverInterceptor; }