GH-973: Higher order for RabbitListTestBootstrap (#976)
* GH-973: Higher order for RabbitListTestBootstrap Fixes https://github.com/spring-projects/spring-amqp/issues/973 When we use `@EnableRabbit` and `@RabbitListenerTest` in the same configuration set, e.g. mixing real `@Configuration` and test one for `@RabbitListenerTest`, we may end up with the case when `@EnableRabbit` is processed before `@RabbitListenerTest`, so, `RabbitListenerTestHarness` bean is not going to appear in the application context. * Implement a `DeferredImportSelector` with an `@Order` for the `@EnableRabbit` as well as `RabbitListenerTest` giving higher order to the `RabbitListenerTestSelector`, so `RabbitListenerTestBootstrap` is processed and register its `RabbitListenerTestHarness` earlier, than it is done by the `RabbitBootstrapConfiguration` **Cherry-pick to 2.1.x** * * Fix Checkstyle * Add JavaDocs to new classes
This commit is contained in:
committed by
Gary Russell
parent
ecb5e113fd
commit
24e8048e70
@@ -30,6 +30,8 @@ import org.springframework.context.annotation.Import;
|
||||
* {@code @RabbitListener} beans to capture arguments and result (if any).
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 1.6
|
||||
*
|
||||
*/
|
||||
@@ -37,7 +39,7 @@ import org.springframework.context.annotation.Import;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@EnableRabbit
|
||||
@Import(RabbitListenerTestBootstrap.class)
|
||||
@Import(RabbitListenerTestSelector.class)
|
||||
public @interface RabbitListenerTest {
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,36 +16,31 @@
|
||||
|
||||
package org.springframework.amqp.rabbit.test;
|
||||
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListenerAnnotationBeanPostProcessor;
|
||||
import org.springframework.amqp.rabbit.config.RabbitListenerConfigUtils;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportAware;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
|
||||
/**
|
||||
* Overrides the default BPP with a {@link RabbitListenerTestHarness}.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 1.6
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
public class RabbitListenerTestBootstrap implements ImportAware {
|
||||
|
||||
private AnnotationMetadata importMetadata;
|
||||
public class RabbitListenerTestBootstrap implements ImportBeanDefinitionRegistrar {
|
||||
|
||||
@Override
|
||||
public void setImportMetadata(AnnotationMetadata importMetadata) {
|
||||
this.importMetadata = importMetadata;
|
||||
}
|
||||
|
||||
@Bean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public RabbitListenerAnnotationBeanPostProcessor rabbitListenerAnnotationProcessor() {
|
||||
return new RabbitListenerTestHarness(this.importMetadata);
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
|
||||
registry.registerBeanDefinition(RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME,
|
||||
BeanDefinitionBuilder.rootBeanDefinition(RabbitListenerTestHarness.class)
|
||||
.addConstructorArgValue(importingClassMetadata)
|
||||
.getBeanDefinition());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -114,11 +114,6 @@ public class RabbitListenerTestHarness extends RabbitListenerAnnotationBeanPostP
|
||||
return (T) this.listeners.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return super.getOrder() - 100;
|
||||
}
|
||||
|
||||
private static final class CaptureAdvice implements MethodInterceptor {
|
||||
|
||||
private final BlockingQueue<InvocationData> invocationData = new LinkedBlockingQueue<>();
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.amqp.rabbit.test;
|
||||
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListenerConfigurationSelector;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
|
||||
/**
|
||||
* A {@link RabbitListenerConfigurationSelector} extension to register
|
||||
* a {@link RabbitListenerTestBootstrap}, but already with the higher order,
|
||||
* so the {@link RabbitListenerTestHarness} bean is registered earlier,
|
||||
* than {@link org.springframework.amqp.rabbit.annotation.RabbitListenerAnnotationBeanPostProcessor}.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 2.1.6
|
||||
*/
|
||||
@Order(Ordered.LOWEST_PRECEDENCE - 100)
|
||||
public class RabbitListenerTestSelector extends RabbitListenerConfigurationSelector {
|
||||
|
||||
@Override
|
||||
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
|
||||
return new String[] { RabbitListenerTestBootstrap.class.getName() };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -47,7 +47,8 @@ import org.springframework.context.annotation.Import;
|
||||
*
|
||||
* The {@code RabbitListenerContainerFactory} is responsible to create the listener container
|
||||
* responsible for a particular endpoint. Typical implementations, as the
|
||||
* {@link org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory SimpleRabbitListenerContainerFactory}
|
||||
* {@link org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory
|
||||
* SimpleRabbitListenerContainerFactory}
|
||||
* used in the sample above, provides the necessary configuration options that are supported by
|
||||
* the underlying {@link org.springframework.amqp.rabbit.listener.MessageListenerContainer MessageListenerContainer}.
|
||||
*
|
||||
@@ -111,9 +112,11 @@ import org.springframework.context.annotation.Import;
|
||||
* // process incoming message
|
||||
* }</pre>
|
||||
*
|
||||
* These features are abstracted by the {@link org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory
|
||||
* These features are abstracted by the
|
||||
* {@link org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory
|
||||
* MessageHandlerMethodFactory} that is responsible to build the necessary invoker to process
|
||||
* the annotated method. By default, {@link org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory
|
||||
* the annotated method. By default,
|
||||
* {@link org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory
|
||||
* DefaultMessageHandlerMethodFactory} is used.
|
||||
*
|
||||
* <p>When more control is desired, a {@code @Configuration} class may implement
|
||||
@@ -249,7 +252,10 @@ import org.springframework.context.annotation.Import;
|
||||
* definition registered in the context in case you use the XML configuration.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 1.4
|
||||
*
|
||||
* @see RabbitListener
|
||||
* @see RabbitListenerAnnotationBeanPostProcessor
|
||||
* @see org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistrar
|
||||
@@ -258,6 +264,6 @@ import org.springframework.context.annotation.Import;
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Import(RabbitBootstrapConfiguration.class)
|
||||
@Import(RabbitListenerConfigurationSelector.class)
|
||||
public @interface EnableRabbit {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.amqp.rabbit.annotation;
|
||||
|
||||
import org.springframework.context.annotation.DeferredImportSelector;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
|
||||
/**
|
||||
* A {@link DeferredImportSelector} implementation with the lowest order to import a
|
||||
* {@link RabbitBootstrapConfiguration} as late as possible.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 2.1.6
|
||||
*/
|
||||
@Order
|
||||
public class RabbitListenerConfigurationSelector implements DeferredImportSelector {
|
||||
|
||||
@Override
|
||||
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
|
||||
return new String[] { RabbitBootstrapConfiguration.class.getName() };
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user