Skip to content

Commit 35ce947

Browse files
committed
Revise @poller usage to single entry in Messaging Annotations.
Fixes spring-projects#3506
1 parent fdc4768 commit 35ce947

File tree

15 files changed

+100
-62
lines changed

15 files changed

+100
-62
lines changed

spring-integration-core/src/main/java/org/springframework/integration/annotation/Aggregator.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -105,10 +105,9 @@
105105
/**
106106
* @return the {@link Poller} options for a polled endpoint
107107
* ({@link org.springframework.integration.scheduling.PollerMetadata}).
108-
* This attribute is an {@code array} just to allow an empty default (no poller).
109108
* Mutually exclusive with {@link #reactive()}.
110109
*/
111-
Poller[] poller() default { };
110+
Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
112111

113112
/**
114113
* @return the {@link Reactive} marker for a consumer endpoint.

spring-integration-core/src/main/java/org/springframework/integration/annotation/BridgeFrom.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2021 the original author or authors.
2+
* Copyright 2014-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -70,10 +70,9 @@
7070
/**
7171
* @return the {@link Poller} options for a polled endpoint
7272
* ({@link org.springframework.integration.scheduling.PollerMetadata}).
73-
* This attribute is an {@code array} just to allow an empty default (no poller).
7473
* Mutually exclusive with {@link #reactive()}.
7574
*/
76-
Poller[] poller() default { };
75+
Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
7776

7877
/**
7978
* @return the {@link Reactive} marker for a consumer endpoint.

spring-integration-core/src/main/java/org/springframework/integration/annotation/BridgeTo.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2021 the original author or authors.
2+
* Copyright 2014-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -77,10 +77,9 @@
7777
/**
7878
* @return the {@link Poller} options for a polled endpoint
7979
* ({@link org.springframework.integration.scheduling.PollerMetadata}).
80-
* This attribute is an {@code array} just to allow an empty default (no poller).
8180
* Mutually exclusive with {@link #reactive()}.
8281
*/
83-
Poller[] poller() default { };
82+
Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
8483

8584
/**
8685
* @return the {@link Reactive} marker for a consumer endpoint.

spring-integration-core/src/main/java/org/springframework/integration/annotation/Filter.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -128,10 +128,9 @@
128128
/**
129129
* @return the {@link Poller} options for a polled endpoint
130130
* ({@link org.springframework.integration.scheduling.PollerMetadata}).
131-
* This attribute is an {@code array} just to allow an empty default (no poller).
132131
* Mutually exclusive with {@link #reactive()}.
133132
*/
134-
Poller[] poller() default { };
133+
Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
135134

136135
/**
137136
* @return the {@link Reactive} marker for a consumer endpoint.

spring-integration-core/src/main/java/org/springframework/integration/annotation/InboundChannelAdapter.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2019 the original author or authors.
2+
* Copyright 2014-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
2323
import java.lang.annotation.Target;
2424

2525
import org.springframework.core.annotation.AliasFor;
26+
import org.springframework.messaging.handler.annotation.ValueConstants;
2627

2728
/**
2829
* Indicates that a method is capable of producing a {@link org.springframework.messaging.Message}
@@ -86,10 +87,8 @@
8687
/**
8788
* @return the {@link org.springframework.integration.annotation.Poller} options for a polled endpoint
8889
* ({@link org.springframework.integration.scheduling.PollerMetadata}).
89-
* This attribute is an {@code array} just to allow an empty default (no poller).
90-
* Only one {@link org.springframework.integration.annotation.Poller} element is allowed.
9190
* NOTE: a {@link Poller} here has {@link Poller#maxMessagesPerPoll()} set to 1 by default.
9291
*/
93-
Poller[] poller() default { };
92+
Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
9493

9594
}

spring-integration-core/src/main/java/org/springframework/integration/annotation/Router.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -151,10 +151,9 @@
151151
/**
152152
* @return the {@link Poller} options for a polled endpoint
153153
* ({@link org.springframework.integration.scheduling.PollerMetadata}).
154-
* This attribute is an {@code array} just to allow an empty default (no poller).
155154
* Mutually exclusive with {@link #reactive()}.
156155
*/
157-
Poller[] poller() default { };
156+
Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
158157

159158
/**
160159
* @return the {@link Reactive} marker for a consumer endpoint.

spring-integration-core/src/main/java/org/springframework/integration/annotation/ServiceActivator.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -121,11 +121,9 @@
121121
/**
122122
* @return the {@link Poller} options for a polled endpoint
123123
* ({@link org.springframework.integration.scheduling.PollerMetadata}).
124-
* This attribute is an {@code array} just to allow an empty default (no poller).
125-
* Only one {@link Poller} element is allowed.
126124
* Mutually exclusive with {@link #reactive()}.
127125
*/
128-
Poller[] poller() default { };
126+
Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
129127

130128
/**
131129
* @return the {@link Reactive} marker for a consumer endpoint.

spring-integration-core/src/main/java/org/springframework/integration/annotation/Splitter.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -116,10 +116,9 @@
116116
/**
117117
* @return the {@link Poller} options for a polled endpoint
118118
* ({@link org.springframework.integration.scheduling.PollerMetadata}).
119-
* This attribute is an {@code array} just to allow an empty default (no poller).
120119
* Mutually exclusive with {@link #reactive()}.
121120
*/
122-
Poller[] poller() default { };
121+
Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
123122

124123
/**
125124
* @return the {@link Reactive} marker for a consumer endpoint.

spring-integration-core/src/main/java/org/springframework/integration/annotation/Transformer.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -92,10 +92,9 @@
9292
/**
9393
* @return the {@link Poller} options for a polled endpoint
9494
* ({@link org.springframework.integration.scheduling.PollerMetadata}).
95-
* This attribute is an {@code array} just to allow an empty default (no poller).
9695
* Mutually exclusive with {@link #reactive()}.
9796
*/
98-
Poller[] poller() default { };
97+
Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
9998

10099
/**
101100
* @return the {@link Reactive} marker for a consumer endpoint.

spring-integration-core/src/main/java/org/springframework/integration/config/annotation/AbstractMethodAnnotationPostProcessor.java

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -363,24 +363,26 @@ protected AbstractEndpoint createEndpoint(MessageHandler handler, @SuppressWarni
363363
protected AbstractEndpoint doCreateEndpoint(MessageHandler handler, MessageChannel inputChannel,
364364
List<Annotation> annotations) {
365365

366-
Poller[] pollers = MessagingAnnotationUtils.resolveAttribute(annotations, "poller", Poller[].class);
366+
Poller poller = MessagingAnnotationUtils.resolveAttribute(annotations, "poller", Poller.class);
367+
boolean pollerProvided = poller != null && !ValueConstants.DEFAULT_NONE.equals(poller.value());
368+
367369
Reactive reactive = MessagingAnnotationUtils.resolveAttribute(annotations, "reactive", Reactive.class);
368370
boolean reactiveProvided = reactive != null && !ValueConstants.DEFAULT_NONE.equals(reactive.value());
369371

370-
Assert.state(!reactiveProvided || ObjectUtils.isEmpty(pollers),
372+
Assert.state(!reactiveProvided || !pollerProvided,
371373
"The 'poller' and 'reactive' are mutually exclusive.");
372374

373375
if (inputChannel instanceof Publisher || handler instanceof ReactiveMessageHandlerAdapter || reactiveProvided) {
374376
return reactiveStreamsConsumer(inputChannel, handler, reactiveProvided ? reactive : null);
375377
}
376378
else if (inputChannel instanceof SubscribableChannel) {
377-
Assert.state(ObjectUtils.isEmpty(pollers), () ->
379+
Assert.state(!pollerProvided, () ->
378380
"A '@Poller' should not be specified for Annotation-based " +
379381
"endpoint, since '" + inputChannel + "' is a SubscribableChannel (not pollable).");
380382
return new EventDrivenConsumer((SubscribableChannel) inputChannel, handler);
381383
}
382384
else if (inputChannel instanceof PollableChannel) {
383-
return pollingConsumer(inputChannel, handler, pollers);
385+
return pollingConsumer(inputChannel, handler, poller);
384386
}
385387
else {
386388
throw new IllegalArgumentException("Unsupported 'inputChannel' type: '"
@@ -414,19 +416,15 @@ private ReactiveStreamsConsumer reactiveStreamsConsumer(MessageChannel channel,
414416
return reactiveStreamsConsumer;
415417
}
416418

417-
private PollingConsumer pollingConsumer(MessageChannel inputChannel, MessageHandler handler, Poller[] pollers) {
419+
private PollingConsumer pollingConsumer(MessageChannel inputChannel, MessageHandler handler, Poller poller) {
418420
PollingConsumer pollingConsumer = new PollingConsumer((PollableChannel) inputChannel, handler);
419-
configurePollingEndpoint(pollingConsumer, pollers);
421+
configurePollingEndpoint(pollingConsumer, poller);
420422
return pollingConsumer;
421423
}
422424

423-
protected void configurePollingEndpoint(AbstractPollingEndpoint pollingEndpoint, Poller[] pollers) {
425+
protected void configurePollingEndpoint(AbstractPollingEndpoint pollingEndpoint, Poller poller) {
424426
PollerMetadata pollerMetadata;
425-
if (!ObjectUtils.isEmpty(pollers)) {
426-
Assert.state(pollers.length == 1,
427-
"The 'poller' for an Annotation-based endpoint can have only one '@Poller'.");
428-
Poller poller = pollers[0];
429-
427+
if (poller != null && !ValueConstants.DEFAULT_NONE.equals(poller.value())) {
430428
String ref = poller.value();
431429
String triggerRef = poller.trigger();
432430
String executorRef = poller.taskExecutor();

spring-integration-core/src/main/java/org/springframework/integration/config/annotation/InboundChannelAdapterAnnotationPostProcessor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2021 the original author or authors.
2+
* Copyright 2014-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -82,8 +82,8 @@ public Object postProcess(Object bean, String beanName, Method method, List<Anno
8282
SourcePollingChannelAdapter adapter = new SourcePollingChannelAdapter();
8383
adapter.setOutputChannelName(channelName);
8484
adapter.setSource(messageSource);
85-
Poller[] pollers = MessagingAnnotationUtils.resolveAttribute(annotations, "poller", Poller[].class);
86-
configurePollingEndpoint(adapter, pollers);
85+
Poller poller = MessagingAnnotationUtils.resolveAttribute(annotations, "poller", Poller.class);
86+
configurePollingEndpoint(adapter, poller);
8787

8888
return adapter;
8989
}

spring-integration-core/src/main/java/org/springframework/integration/util/MessagingAnnotationUtils.java

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2021 the original author or authors.
2+
* Copyright 2014-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,12 +26,14 @@
2626
import org.springframework.core.annotation.AnnotationUtils;
2727
import org.springframework.integration.annotation.EndpointId;
2828
import org.springframework.integration.annotation.Payloads;
29+
import org.springframework.integration.annotation.Poller;
2930
import org.springframework.messaging.MessagingException;
3031
import org.springframework.messaging.handler.annotation.Header;
3132
import org.springframework.messaging.handler.annotation.Headers;
3233
import org.springframework.messaging.handler.annotation.Payload;
34+
import org.springframework.messaging.handler.annotation.ValueConstants;
35+
import org.springframework.util.ObjectUtils;
3336
import org.springframework.util.ReflectionUtils;
34-
import org.springframework.util.StringUtils;
3537

3638
/**
3739
* Utility methods to support annotation processing.
@@ -41,17 +43,16 @@
4143
* @author Gunnar Hillert
4244
* @author Soby Chacko
4345
* @author Artem Bilan
46+
* @author Chris Bono
4447
*
4548
* @since 4.0
4649
*/
4750
public final class MessagingAnnotationUtils {
4851

4952
/**
50-
* Get the attribute value from the annotation hierarchy, returning the first non-empty
51-
* value closest to the annotated method. While traversing up the hierarchy, for string-valued
52-
* attributes, an empty string is ignored. For array-valued attributes, an empty
53-
* array is ignored.
54-
* The overridden attribute must be the same type.
53+
* Get the attribute value from the annotation hierarchy, returning the first
54+
* {@link MessagingAnnotationUtils#hasValue non-empty}) value closest to the annotated method.
55+
*
5556
* @param annotations The meta-annotations in order (closest first).
5657
* @param name The attribute name.
5758
* @param requiredType The expected type.
@@ -69,9 +70,31 @@ public static <T> T resolveAttribute(List<Annotation> annotations, String name,
6970
return null;
7071
}
7172

72-
public static boolean hasValue(Object value) {
73-
return value != null && (!(value instanceof String) || (StringUtils.hasText((String) value))) // NOSONAR
74-
&& (!value.getClass().isArray() || ((Object[]) value).length > 0);
73+
/**
74+
* Determines if the value of a named attribute from an annotation instance contains an actual value.
75+
* <p>It is considered to NOT contain a value if it is null, an empty string, an empty array, or a {@link Poller}
76+
* whose 'value' field is set to {@link ValueConstants#DEFAULT_NONE}.
77+
*
78+
* @param annotationValue the value of the annotation attribute
79+
* @return whether {@code annotationValue} is set to a non-empty value
80+
*/
81+
public static boolean hasValue(Object annotationValue) {
82+
if (annotationValue == null) {
83+
return false;
84+
}
85+
// Empty array
86+
if (ObjectUtils.isArray(annotationValue) && ObjectUtils.isEmpty(annotationValue)) {
87+
return false;
88+
}
89+
// Empty string
90+
if ((annotationValue instanceof String) && ObjectUtils.isEmpty(annotationValue)) {
91+
return false;
92+
}
93+
// Poller with special 'none' value
94+
if ((annotationValue instanceof Poller) && ValueConstants.DEFAULT_NONE.equals(((Poller) annotationValue).value())) {
95+
return false;
96+
}
97+
return true;
7598
}
7699

77100
public static Method findAnnotatedMethod(Object target, final Class<? extends Annotation> annotationType) {

spring-integration-core/src/test/java/org/springframework/integration/configuration/EnableIntegrationTests.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2021 the original author or authors.
2+
* Copyright 2014-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -127,6 +127,7 @@
127127
import org.springframework.messaging.MessageHandler;
128128
import org.springframework.messaging.PollableChannel;
129129
import org.springframework.messaging.handler.annotation.Payload;
130+
import org.springframework.messaging.handler.annotation.ValueConstants;
130131
import org.springframework.messaging.support.ChannelInterceptor;
131132
import org.springframework.messaging.support.GenericMessage;
132133
import org.springframework.scheduling.Trigger;
@@ -1506,7 +1507,7 @@ public interface TestGateway2 {
15061507

15071508
String phase() default "";
15081509

1509-
Poller[] poller() default { };
1510+
Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
15101511

15111512
}
15121513

@@ -1525,7 +1526,7 @@ public interface TestGateway2 {
15251526

15261527
String phase() default "";
15271528

1528-
Poller[] poller() default { };
1529+
Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
15291530

15301531
}
15311532

@@ -1631,7 +1632,7 @@ public interface TestGateway2 {
16311632

16321633
String phase() default "";
16331634

1634-
Poller[] poller() default { };
1635+
Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
16351636

16361637
}
16371638

@@ -1664,7 +1665,7 @@ public interface TestGateway2 {
16641665

16651666
String phase() default "";
16661667

1667-
Poller[] poller() default { };
1668+
Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
16681669

16691670
}
16701671

0 commit comments

Comments
 (0)