GH-3506: No array for poller messaging anns attr

Fixes https://github.com/spring-projects/spring-integration/issues/3506

Revise the `@Poller` usage in the messaging annotations from an array value
to a single entry with a `ValueConstants.DEFAULT_NONE` for default value

Code review feedback

- Make annotation utils check for NONE more generic
- Move docs to whats-new.adoc
- Polish javadoc

Code review feedback
- simplify docs
- simplify isProvided checks
This commit is contained in:
Chris Bono
2022-03-09 20:54:05 -05:00
committed by Artem Bilan
parent ecb9ac3fc3
commit f3d3694836
15 changed files with 91 additions and 68 deletions

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ import org.springframework.messaging.handler.annotation.ValueConstants;
* @author Marius Bogoevici * @author Marius Bogoevici
* @author Oleg Zhurakousky * @author Oleg Zhurakousky
* @author Artem Bilan * @author Artem Bilan
* @author Chris Bono
*/ */
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE }) @Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@@ -105,10 +106,9 @@ public @interface Aggregator {
/** /**
* @return the {@link Poller} options for a polled endpoint * @return the {@link Poller} options for a polled endpoint
* ({@link org.springframework.integration.scheduling.PollerMetadata}). * ({@link org.springframework.integration.scheduling.PollerMetadata}).
* This attribute is an {@code array} just to allow an empty default (no poller).
* Mutually exclusive with {@link #reactive()}. * Mutually exclusive with {@link #reactive()}.
*/ */
Poller[] poller() default { }; Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
/** /**
* @return the {@link Reactive} marker for a consumer endpoint. * @return the {@link Reactive} marker for a consumer endpoint.

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2014-2021 the original author or authors. * Copyright 2014-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -38,6 +38,7 @@ import org.springframework.messaging.handler.annotation.ValueConstants;
* is used as the {@code outputChannel} of the {@link org.springframework.integration.handler.BridgeHandler}. * is used as the {@code outputChannel} of the {@link org.springframework.integration.handler.BridgeHandler}.
* *
* @author Artem Bilan * @author Artem Bilan
* @author Chris Bono
* *
* @since 4.0 * @since 4.0
*/ */
@@ -70,10 +71,9 @@ public @interface BridgeFrom {
/** /**
* @return the {@link Poller} options for a polled endpoint * @return the {@link Poller} options for a polled endpoint
* ({@link org.springframework.integration.scheduling.PollerMetadata}). * ({@link org.springframework.integration.scheduling.PollerMetadata}).
* This attribute is an {@code array} just to allow an empty default (no poller).
* Mutually exclusive with {@link #reactive()}. * Mutually exclusive with {@link #reactive()}.
*/ */
Poller[] poller() default { }; Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
/** /**
* @return the {@link Reactive} marker for a consumer endpoint. * @return the {@link Reactive} marker for a consumer endpoint.

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2014-2021 the original author or authors. * Copyright 2014-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@ import org.springframework.messaging.handler.annotation.ValueConstants;
* If no output channel is provided and no reply-channel exists, an exception is thrown. * If no output channel is provided and no reply-channel exists, an exception is thrown.
* *
* @author Artem Bilan * @author Artem Bilan
* @author Chris Bono
* *
* @since 4.0 * @since 4.0
*/ */
@@ -77,10 +78,9 @@ public @interface BridgeTo {
/** /**
* @return the {@link Poller} options for a polled endpoint * @return the {@link Poller} options for a polled endpoint
* ({@link org.springframework.integration.scheduling.PollerMetadata}). * ({@link org.springframework.integration.scheduling.PollerMetadata}).
* This attribute is an {@code array} just to allow an empty default (no poller).
* Mutually exclusive with {@link #reactive()}. * Mutually exclusive with {@link #reactive()}.
*/ */
Poller[] poller() default { }; Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
/** /**
* @return the {@link Reactive} marker for a consumer endpoint. * @return the {@link Reactive} marker for a consumer endpoint.

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -40,6 +40,7 @@ import org.springframework.messaging.handler.annotation.ValueConstants;
* @author Mark Fisher * @author Mark Fisher
* @author Gary Russell * @author Gary Russell
* @author Artem Bilan * @author Artem Bilan
* @author Chris Bono
* *
* @since 2.0 * @since 2.0
*/ */
@@ -128,10 +129,9 @@ public @interface Filter {
/** /**
* @return the {@link Poller} options for a polled endpoint * @return the {@link Poller} options for a polled endpoint
* ({@link org.springframework.integration.scheduling.PollerMetadata}). * ({@link org.springframework.integration.scheduling.PollerMetadata}).
* This attribute is an {@code array} just to allow an empty default (no poller).
* Mutually exclusive with {@link #reactive()}. * Mutually exclusive with {@link #reactive()}.
*/ */
Poller[] poller() default { }; Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
/** /**
* @return the {@link Reactive} marker for a consumer endpoint. * @return the {@link Reactive} marker for a consumer endpoint.

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2014-2019 the original author or authors. * Copyright 2014-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor; import org.springframework.core.annotation.AliasFor;
import org.springframework.messaging.handler.annotation.ValueConstants;
/** /**
* Indicates that a method is capable of producing a {@link org.springframework.messaging.Message} * Indicates that a method is capable of producing a {@link org.springframework.messaging.Message}
@@ -45,6 +46,7 @@ import org.springframework.core.annotation.AliasFor;
* *
* @author Artem Bilan * @author Artem Bilan
* @author Gary Russell * @author Gary Russell
* @author Chris Bono
* *
* @since 4.0 * @since 4.0
*/ */
@@ -86,10 +88,8 @@ public @interface InboundChannelAdapter {
/** /**
* @return the {@link org.springframework.integration.annotation.Poller} options for a polled endpoint * @return the {@link org.springframework.integration.annotation.Poller} options for a polled endpoint
* ({@link org.springframework.integration.scheduling.PollerMetadata}). * ({@link org.springframework.integration.scheduling.PollerMetadata}).
* This attribute is an {@code array} just to allow an empty default (no poller).
* Only one {@link org.springframework.integration.annotation.Poller} element is allowed.
* NOTE: a {@link Poller} here has {@link Poller#maxMessagesPerPoll()} set to 1 by default. * NOTE: a {@link Poller} here has {@link Poller#maxMessagesPerPoll()} set to 1 by default.
*/ */
Poller[] poller() default { }; Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -45,6 +45,7 @@ import org.springframework.messaging.handler.annotation.ValueConstants;
* *
* @author Mark Fisher * @author Mark Fisher
* @author Artem Bilan * @author Artem Bilan
* @author Chris Bono
*/ */
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE }) @Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@@ -151,10 +152,9 @@ public @interface Router {
/** /**
* @return the {@link Poller} options for a polled endpoint * @return the {@link Poller} options for a polled endpoint
* ({@link org.springframework.integration.scheduling.PollerMetadata}). * ({@link org.springframework.integration.scheduling.PollerMetadata}).
* This attribute is an {@code array} just to allow an empty default (no poller).
* Mutually exclusive with {@link #reactive()}. * Mutually exclusive with {@link #reactive()}.
*/ */
Poller[] poller() default { }; Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
/** /**
* @return the {@link Reactive} marker for a consumer endpoint. * @return the {@link Reactive} marker for a consumer endpoint.

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@ import org.springframework.messaging.handler.annotation.ValueConstants;
* @author Gary Russell * @author Gary Russell
* @author Artem Bilan * @author Artem Bilan
* @author Yilin Wei * @author Yilin Wei
* @author Chris Bono
*/ */
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE }) @Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@@ -121,11 +122,9 @@ public @interface ServiceActivator {
/** /**
* @return the {@link Poller} options for a polled endpoint * @return the {@link Poller} options for a polled endpoint
* ({@link org.springframework.integration.scheduling.PollerMetadata}). * ({@link org.springframework.integration.scheduling.PollerMetadata}).
* This attribute is an {@code array} just to allow an empty default (no poller).
* Only one {@link Poller} element is allowed.
* Mutually exclusive with {@link #reactive()}. * Mutually exclusive with {@link #reactive()}.
*/ */
Poller[] poller() default { }; Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
/** /**
* @return the {@link Reactive} marker for a consumer endpoint. * @return the {@link Reactive} marker for a consumer endpoint.

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@ import org.springframework.messaging.handler.annotation.ValueConstants;
* @author Mark Fisher * @author Mark Fisher
* @author Gary Russell * @author Gary Russell
* @author Artem Bilan * @author Artem Bilan
* @author Chris Bono
*/ */
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE }) @Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@@ -116,10 +117,9 @@ public @interface Splitter {
/** /**
* @return the {@link Poller} options for a polled endpoint * @return the {@link Poller} options for a polled endpoint
* ({@link org.springframework.integration.scheduling.PollerMetadata}). * ({@link org.springframework.integration.scheduling.PollerMetadata}).
* This attribute is an {@code array} just to allow an empty default (no poller).
* Mutually exclusive with {@link #reactive()}. * Mutually exclusive with {@link #reactive()}.
*/ */
Poller[] poller() default { }; Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
/** /**
* @return the {@link Reactive} marker for a consumer endpoint. * @return the {@link Reactive} marker for a consumer endpoint.

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ import org.springframework.messaging.handler.annotation.ValueConstants;
* @author Mark Fisher * @author Mark Fisher
* @author Gary Russell * @author Gary Russell
* @author Artem Bilan * @author Artem Bilan
* @author Chris Bono
*/ */
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE }) @Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@@ -92,10 +93,9 @@ public @interface Transformer {
/** /**
* @return the {@link Poller} options for a polled endpoint * @return the {@link Poller} options for a polled endpoint
* ({@link org.springframework.integration.scheduling.PollerMetadata}). * ({@link org.springframework.integration.scheduling.PollerMetadata}).
* This attribute is an {@code array} just to allow an empty default (no poller).
* Mutually exclusive with {@link #reactive()}. * Mutually exclusive with {@link #reactive()}.
*/ */
Poller[] poller() default { }; Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
/** /**
* @return the {@link Reactive} marker for a consumer endpoint. * @return the {@link Reactive} marker for a consumer endpoint.

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -84,7 +84,6 @@ import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.SubscribableChannel; import org.springframework.messaging.SubscribableChannel;
import org.springframework.messaging.core.DestinationResolutionException; import org.springframework.messaging.core.DestinationResolutionException;
import org.springframework.messaging.core.DestinationResolver; import org.springframework.messaging.core.DestinationResolver;
import org.springframework.messaging.handler.annotation.ValueConstants;
import org.springframework.scheduling.Trigger; import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.support.CronTrigger; import org.springframework.scheduling.support.CronTrigger;
import org.springframework.scheduling.support.PeriodicTrigger; import org.springframework.scheduling.support.PeriodicTrigger;
@@ -103,6 +102,7 @@ import reactor.core.publisher.Flux;
* @author Mark Fisher * @author Mark Fisher
* @author Artem Bilan * @author Artem Bilan
* @author Gary Russell * @author Gary Russell
* @author Chris Bono
*/ */
public abstract class AbstractMethodAnnotationPostProcessor<T extends Annotation> public abstract class AbstractMethodAnnotationPostProcessor<T extends Annotation>
implements MethodAnnotationPostProcessor<T> { implements MethodAnnotationPostProcessor<T> {
@@ -363,24 +363,24 @@ public abstract class AbstractMethodAnnotationPostProcessor<T extends Annotation
protected AbstractEndpoint doCreateEndpoint(MessageHandler handler, MessageChannel inputChannel, protected AbstractEndpoint doCreateEndpoint(MessageHandler handler, MessageChannel inputChannel,
List<Annotation> annotations) { List<Annotation> annotations) {
Poller[] pollers = MessagingAnnotationUtils.resolveAttribute(annotations, "poller", Poller[].class); Poller poller = MessagingAnnotationUtils.resolveAttribute(annotations, "poller", Poller.class);
Reactive reactive = MessagingAnnotationUtils.resolveAttribute(annotations, "reactive", Reactive.class);
boolean reactiveProvided = reactive != null && !ValueConstants.DEFAULT_NONE.equals(reactive.value());
Assert.state(!reactiveProvided || ObjectUtils.isEmpty(pollers), Reactive reactive = MessagingAnnotationUtils.resolveAttribute(annotations, "reactive", Reactive.class);
Assert.state(reactive == null || poller == null,
"The 'poller' and 'reactive' are mutually exclusive."); "The 'poller' and 'reactive' are mutually exclusive.");
if (inputChannel instanceof Publisher || handler instanceof ReactiveMessageHandlerAdapter || reactiveProvided) { if (inputChannel instanceof Publisher || handler instanceof ReactiveMessageHandlerAdapter || reactive != null) {
return reactiveStreamsConsumer(inputChannel, handler, reactiveProvided ? reactive : null); return reactiveStreamsConsumer(inputChannel, handler, reactive);
} }
else if (inputChannel instanceof SubscribableChannel) { else if (inputChannel instanceof SubscribableChannel) {
Assert.state(ObjectUtils.isEmpty(pollers), () -> Assert.state(poller == null, () ->
"A '@Poller' should not be specified for Annotation-based " + "A '@Poller' should not be specified for Annotation-based " +
"endpoint, since '" + inputChannel + "' is a SubscribableChannel (not pollable)."); "endpoint, since '" + inputChannel + "' is a SubscribableChannel (not pollable).");
return new EventDrivenConsumer((SubscribableChannel) inputChannel, handler); return new EventDrivenConsumer((SubscribableChannel) inputChannel, handler);
} }
else if (inputChannel instanceof PollableChannel) { else if (inputChannel instanceof PollableChannel) {
return pollingConsumer(inputChannel, handler, pollers); return pollingConsumer(inputChannel, handler, poller);
} }
else { else {
throw new IllegalArgumentException("Unsupported 'inputChannel' type: '" throw new IllegalArgumentException("Unsupported 'inputChannel' type: '"
@@ -414,19 +414,15 @@ public abstract class AbstractMethodAnnotationPostProcessor<T extends Annotation
return reactiveStreamsConsumer; return reactiveStreamsConsumer;
} }
private PollingConsumer pollingConsumer(MessageChannel inputChannel, MessageHandler handler, Poller[] pollers) { private PollingConsumer pollingConsumer(MessageChannel inputChannel, MessageHandler handler, Poller poller) {
PollingConsumer pollingConsumer = new PollingConsumer((PollableChannel) inputChannel, handler); PollingConsumer pollingConsumer = new PollingConsumer((PollableChannel) inputChannel, handler);
configurePollingEndpoint(pollingConsumer, pollers); configurePollingEndpoint(pollingConsumer, poller);
return pollingConsumer; return pollingConsumer;
} }
protected void configurePollingEndpoint(AbstractPollingEndpoint pollingEndpoint, Poller[] pollers) { protected void configurePollingEndpoint(AbstractPollingEndpoint pollingEndpoint, Poller poller) {
PollerMetadata pollerMetadata; PollerMetadata pollerMetadata;
if (!ObjectUtils.isEmpty(pollers)) { if (poller != null) {
Assert.state(pollers.length == 1,
"The 'poller' for an Annotation-based endpoint can have only one '@Poller'.");
Poller poller = pollers[0];
String ref = poller.value(); String ref = poller.value();
String triggerRef = poller.trigger(); String triggerRef = poller.trigger();
String executorRef = poller.taskExecutor(); String executorRef = poller.taskExecutor();

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2014-2021 the original author or authors. * Copyright 2014-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -44,6 +44,7 @@ import org.springframework.util.Assert;
* @author Artem Bilan * @author Artem Bilan
* @author Gary Russell * @author Gary Russell
* @author Oleg Zhurakousky * @author Oleg Zhurakousky
* @author Chris Bono
* *
* @since 4.0 * @since 4.0
*/ */
@@ -82,8 +83,8 @@ public class InboundChannelAdapterAnnotationPostProcessor extends
SourcePollingChannelAdapter adapter = new SourcePollingChannelAdapter(); SourcePollingChannelAdapter adapter = new SourcePollingChannelAdapter();
adapter.setOutputChannelName(channelName); adapter.setOutputChannelName(channelName);
adapter.setSource(messageSource); adapter.setSource(messageSource);
Poller[] pollers = MessagingAnnotationUtils.resolveAttribute(annotations, "poller", Poller[].class); Poller poller = MessagingAnnotationUtils.resolveAttribute(annotations, "poller", Poller.class);
configurePollingEndpoint(adapter, pollers); configurePollingEndpoint(adapter, poller);
return adapter; return adapter;
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2014-2021 the original author or authors. * Copyright 2014-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -30,8 +30,9 @@ import org.springframework.messaging.MessagingException;
import org.springframework.messaging.handler.annotation.Header; import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Headers; import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload; import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.ValueConstants;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
/** /**
* Utility methods to support annotation processing. * Utility methods to support annotation processing.
@@ -41,17 +42,16 @@ import org.springframework.util.StringUtils;
* @author Gunnar Hillert * @author Gunnar Hillert
* @author Soby Chacko * @author Soby Chacko
* @author Artem Bilan * @author Artem Bilan
* @author Chris Bono
* *
* @since 4.0 * @since 4.0
*/ */
public final class MessagingAnnotationUtils { public final class MessagingAnnotationUtils {
/** /**
* Get the attribute value from the annotation hierarchy, returning the first non-empty * Get the attribute value from the annotation hierarchy, returning the first
* value closest to the annotated method. While traversing up the hierarchy, for string-valued * {@link MessagingAnnotationUtils#hasValue non-empty}) value closest to the annotated method.
* attributes, an empty string is ignored. For array-valued attributes, an empty *
* array is ignored.
* The overridden attribute must be the same type.
* @param annotations The meta-annotations in order (closest first). * @param annotations The meta-annotations in order (closest first).
* @param name The attribute name. * @param name The attribute name.
* @param requiredType The expected type. * @param requiredType The expected type.
@@ -69,9 +69,30 @@ public final class MessagingAnnotationUtils {
return null; return null;
} }
public static boolean hasValue(Object value) { /**
return value != null && (!(value instanceof String) || (StringUtils.hasText((String) value))) // NOSONAR * Determine if the value of a named attribute from an annotation instance contains an actual value.
&& (!value.getClass().isArray() || ((Object[]) value).length > 0); * @param annotationValue the value of the annotation attribute
* @return {@code false} when {@code annotationValue} is null, an empty string, an empty array, or any annotation
* whose 'value' field is set to {@link ValueConstants#DEFAULT_NONE} - {@code true} otherwise
*/
public static boolean hasValue(Object annotationValue) {
if (annotationValue == null) {
return false;
}
// Empty array
if (ObjectUtils.isArray(annotationValue) && ObjectUtils.isEmpty(annotationValue)) {
return false;
}
// Empty string
if ((annotationValue instanceof String) && ObjectUtils.isEmpty(annotationValue)) {
return false;
}
// Annotation with 'value' set to special 'none' string
if ((annotationValue instanceof Annotation) &&
ValueConstants.DEFAULT_NONE.equals(AnnotationUtils.getValue((Annotation) annotationValue))) {
return false;
}
return true;
} }
public static Method findAnnotatedMethod(Object target, final Class<? extends Annotation> annotationType) { public static Method findAnnotatedMethod(Object target, final Class<? extends Annotation> annotationType) {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2014-2021 the original author or authors. * Copyright 2014-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -127,6 +127,7 @@ import org.springframework.messaging.MessageDeliveryException;
import org.springframework.messaging.MessageHandler; import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.PollableChannel; import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.handler.annotation.Payload; import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.ValueConstants;
import org.springframework.messaging.support.ChannelInterceptor; import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.messaging.support.GenericMessage; import org.springframework.messaging.support.GenericMessage;
import org.springframework.scheduling.Trigger; import org.springframework.scheduling.Trigger;
@@ -148,6 +149,7 @@ import reactor.core.publisher.Mono;
* @author Artem Bilan * @author Artem Bilan
* @author Gary Russell * @author Gary Russell
* @author Michael Wiles * @author Michael Wiles
* @author Chris Bono
* *
* @since 4.0 * @since 4.0
*/ */
@@ -1506,7 +1508,7 @@ public class EnableIntegrationTests {
String phase() default ""; String phase() default "";
Poller[] poller() default { }; Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
} }
@@ -1525,7 +1527,7 @@ public class EnableIntegrationTests {
String phase() default ""; String phase() default "";
Poller[] poller() default { }; Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
} }
@@ -1631,7 +1633,7 @@ public class EnableIntegrationTests {
String phase() default ""; String phase() default "";
Poller[] poller() default { }; Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
} }
@@ -1664,7 +1666,7 @@ public class EnableIntegrationTests {
String phase() default ""; String phase() default "";
Poller[] poller() default { }; Poller poller() default @Poller(ValueConstants.DEFAULT_NONE);
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2018-2021 the original author or authors. * Copyright 2018-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -56,6 +56,7 @@ import java.util.stream.Collectors
/** /**
* @author Artem Bilan * @author Artem Bilan
* @author Chris Bono
* *
* @since 5.1 * @since 5.1
*/ */
@@ -171,7 +172,7 @@ class FunctionsTests {
@Bean @Bean
@InboundChannelAdapter(value = "counterChannel", autoStartup = "false", @InboundChannelAdapter(value = "counterChannel", autoStartup = "false",
poller = [Poller(fixedRate = "10", maxMessagesPerPoll = "1")]) poller = Poller(fixedRate = "10", maxMessagesPerPoll = "1"))
@EndpointId("kotlinSupplierChannelAdapter") @EndpointId("kotlinSupplierChannelAdapter")
fun kotlinSupplier(): () -> String { fun kotlinSupplier(): () -> String {
return { "baz" } return { "baz" }

View File

@@ -26,6 +26,9 @@ See <<./graphql.adoc#graphql,GraphQL Support>> for more information.
[[x6.0-general]] [[x6.0-general]]
=== General Changes === General Changes
The messaging annotations don't require a poller attribute as an array of @Poller any more.
See <<./configuration.adoc#configuration-using-poller-annotation,Using the @Poller Annotation>> for more information.
[[x6.0-http]] [[x6.0-http]]
=== HTTP Changes === HTTP Changes
@@ -36,4 +39,4 @@ See <<./http.adoc#http,HTTP Support>> for more information.
=== RMI Removal === RMI Removal
The `spring-integration-rmi` module has been removed altogether after being deprecated in previous versions. The `spring-integration-rmi` module has been removed altogether after being deprecated in previous versions.
There is no replacement: it is recommended to migrate to more secure network and application protocols, such as WebSockets, RSockets, gRPC or REST. There is no replacement: it is recommended to migrate to more secure network and application protocols, such as WebSockets, RSockets, gRPC or REST.