diff --git a/spring-integration-core/src/main/java/org/springframework/integration/annotation/Publisher.java b/spring-integration-core/src/main/java/org/springframework/integration/annotation/Publisher.java
index b494cc10b3..c6453c3560 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/annotation/Publisher.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/annotation/Publisher.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-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.
@@ -21,16 +21,16 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import org.springframework.core.annotation.AliasFor;
+
/**
- * Annotation to indicate that a method, or all public methods if applied at
- * class-level, should publish Messages.
+ * Annotation to indicate that a method, or all public methods if applied at class-level,
+ * should publish Messages.
*
* By default, the Message will be constructed from the return value of the method
- * invocation
- * and sent to a channel specified by the {@link #channel()} attribute.
- * However, a combination of both @Payload and @Header annotations
- * can be used to further manage the message structure. See the reference manual for
- * examples.
+ * invocation and sent to a channel specified by the {@link #channel()} attribute.
+ * However, a combination of both @Payload and @Header annotations can be used to further
+ * manage the message structure. See the reference manual for examples.
*
* Note: unlike @Gateway, this annotation is used to generate an AOP Advice for an
* existing service and its method implementation. The message sending is a side effect
@@ -40,17 +40,28 @@ import java.lang.annotation.Target;
* The XML equivalent is {@code }
*
* @author Mark Fisher
+ * @author Jeff Maxwell
*
* @since 2.0
+ *
* @see org.springframework.integration.aop.MessagePublishingInterceptor
*/
-@Target({ElementType.METHOD, ElementType.TYPE})
+@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface Publisher {
+ /**
+ * Alias for the {@link #channel()} attribute.
+ * @return The name of the Message Channel to which Messages will be published.
+ * @since 5.0.4
+ */
+ @AliasFor("channel")
+ String value() default "";
+
/**
* @return The name of the Message Channel to which Messages will be published.
*/
+ @AliasFor("value")
String channel() default "";
}
diff --git a/spring-integration-core/src/test/java/org/springframework/integration/aop/PublisherAnnotationAdvisorTests.java b/spring-integration-core/src/test/java/org/springframework/integration/aop/PublisherAnnotationAdvisorTests.java
index 0e06f96a6d..87af422207 100644
--- a/spring-integration-core/src/test/java/org/springframework/integration/aop/PublisherAnnotationAdvisorTests.java
+++ b/spring-integration-core/src/test/java/org/springframework/integration/aop/PublisherAnnotationAdvisorTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-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.
@@ -29,27 +29,27 @@ import org.junit.Test;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.context.support.StaticApplicationContext;
-import org.springframework.messaging.Message;
-import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.integration.annotation.Publisher;
import org.springframework.integration.channel.QueueChannel;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.handler.annotation.Payload;
/**
* @author Mark Fisher
+ * @author Jeff Maxwell
+ *
* @since 2.0
*/
public class PublisherAnnotationAdvisorTests {
private final StaticApplicationContext context = new StaticApplicationContext();
-
@Before
public void setup() {
context.registerSingleton("testChannel", QueueChannel.class);
context.registerSingleton("testMetaChannel", QueueChannel.class);
}
-
@Test
public void annotationAtMethodLevelOnVoidReturnWithParamAnnotation() {
PublisherAnnotationAdvisor advisor = new PublisherAnnotationAdvisor();
@@ -120,6 +120,75 @@ public class PublisherAnnotationAdvisorTests {
assertEquals("foo", message.getPayload());
}
+ @Test
+ public void annotationViaValueAtMethodLevelOnVoidReturnWithParamAnnotation() {
+ PublisherAnnotationAdvisor advisor = new PublisherAnnotationAdvisor();
+ advisor.setBeanFactory(context);
+ QueueChannel testChannel = context.getBean("testChannel", QueueChannel.class);
+ ProxyFactory pf = new ProxyFactory(new AnnotationViaValueAtMethodLevelTestBeanImpl());
+ pf.addAdvisor(advisor);
+ TestVoidBean proxy = (TestVoidBean) pf.getProxy();
+ proxy.testVoidMethod("foo");
+ Message> message = testChannel.receive(0);
+ assertNotNull(message);
+ assertEquals("foo", message.getPayload());
+ }
+
+ @Test
+ public void annotationViaValueAtMethodLevel() {
+ PublisherAnnotationAdvisor advisor = new PublisherAnnotationAdvisor();
+ advisor.setBeanFactory(context);
+ QueueChannel testChannel = context.getBean("testChannel", QueueChannel.class);
+ ProxyFactory pf = new ProxyFactory(new AnnotationViaValueAtMethodLevelTestBeanImpl());
+ pf.addAdvisor(advisor);
+ TestBean proxy = (TestBean) pf.getProxy();
+ proxy.test();
+ Message> message = testChannel.receive(0);
+ assertNotNull(message);
+ assertEquals("foo", message.getPayload());
+ }
+
+ @Test
+ public void annotationViaValueAtClassLevel() {
+ PublisherAnnotationAdvisor advisor = new PublisherAnnotationAdvisor();
+ advisor.setBeanFactory(context);
+ QueueChannel testChannel = context.getBean("testChannel", QueueChannel.class);
+ ProxyFactory pf = new ProxyFactory(new AnnotationViaValueAtClassLevelTestBeanImpl());
+ pf.addAdvisor(advisor);
+ TestBean proxy = (TestBean) pf.getProxy();
+ proxy.test();
+ Message> message = testChannel.receive(0);
+ assertNotNull(message);
+ assertEquals("foo", message.getPayload());
+ }
+
+ @Test
+ public void metaAnnotationViaValueAtMethodLevel() {
+ PublisherAnnotationAdvisor advisor = new PublisherAnnotationAdvisor();
+ advisor.setBeanFactory(context);
+ QueueChannel testMetaChannel = context.getBean("testMetaChannel", QueueChannel.class);
+ ProxyFactory pf = new ProxyFactory(new MetaAnnotationViaValueAtMethodLevelTestBeanImpl());
+ pf.addAdvisor(advisor);
+ TestBean proxy = (TestBean) pf.getProxy();
+ proxy.test();
+ Message> message = testMetaChannel.receive(0);
+ assertNotNull(message);
+ assertEquals("foo", message.getPayload());
+ }
+
+ @Test
+ public void metaAnnotationViaValueAtClassLevel() {
+ PublisherAnnotationAdvisor advisor = new PublisherAnnotationAdvisor();
+ advisor.setBeanFactory(context);
+ QueueChannel testMetaChannel = context.getBean("testMetaChannel", QueueChannel.class);
+ ProxyFactory pf = new ProxyFactory(new MetaAnnotationViaValueAtClassLevelTestBeanImpl());
+ pf.addAdvisor(advisor);
+ TestBean proxy = (TestBean) pf.getProxy();
+ proxy.test();
+ Message> message = testMetaChannel.receive(0);
+ assertNotNull(message);
+ assertEquals("foo", message.getPayload());
+ }
interface TestBean {
@@ -127,58 +196,114 @@ public class PublisherAnnotationAdvisorTests {
}
-
interface TestVoidBean {
void testVoidMethod(String s);
}
-
static class AnnotationAtMethodLevelTestBeanImpl implements TestBean, TestVoidBean {
+ @Override
@Publisher(channel = "testChannel")
public String test() {
return "foo";
}
+ @Override
@Publisher(channel = "testChannel")
- public void testVoidMethod(@Payload String s) { }
- }
+ public void testVoidMethod(@Payload String s) {
+ }
+ }
@Publisher(channel = "testChannel")
static class AnnotationAtClassLevelTestBeanImpl implements TestBean {
+ @Override
public String test() {
return "foo";
}
}
-
- @Target({ElementType.METHOD, ElementType.TYPE})
+ @Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Publisher(channel = "testMetaChannel")
public @interface TestMetaPublisher {
- }
+ }
static class MetaAnnotationAtMethodLevelTestBeanImpl implements TestBean {
+ @Override
@TestMetaPublisher
public String test() {
return "foo";
}
- }
+ }
@TestMetaPublisher
static class MetaAnnotationAtClassLevelTestBeanImpl implements TestBean {
+ @Override
public String test() {
return "foo";
}
+
+ }
+
+ static class AnnotationViaValueAtMethodLevelTestBeanImpl implements TestBean, TestVoidBean {
+
+ @Override
+ @Publisher("testChannel")
+ public String test() {
+ return "foo";
+ }
+
+ @Override
+ @Publisher("testChannel")
+ public void testVoidMethod(@Payload String s) {
+ }
+
+ }
+
+ @Publisher("testChannel")
+ static class AnnotationViaValueAtClassLevelTestBeanImpl implements TestBean {
+
+ @Override
+ public String test() {
+ return "foo";
+ }
+
+ }
+
+ @Target({ ElementType.METHOD, ElementType.TYPE })
+ @Retention(RetentionPolicy.RUNTIME)
+ @Publisher("testMetaChannel")
+ public @interface TestMetaPublisherViaValue {
+
+ }
+
+ static class MetaAnnotationViaValueAtMethodLevelTestBeanImpl implements TestBean {
+
+ @Override
+ @TestMetaPublisherViaValue
+ public String test() {
+ return "foo";
+ }
+
+ }
+
+ @TestMetaPublisherViaValue
+ static class MetaAnnotationViaValueAtClassLevelTestBeanImpl implements TestBean {
+
+ @Override
+ public String test() {
+ return "foo";
+ }
+
}
}