From f85a3849fcd4e8ab8b6839397087122b3d3fa26d Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Fri, 13 Mar 2020 11:15:24 -0400 Subject: [PATCH] GH-1175: Add @SpringRabbitTest Resolves https://github.com/spring-projects/spring-amqp/issues/1175 - provision boilerplate infrastructure * Fix test name in doc * Remove `@ContextConfiguration` from doc. --- build.gradle | 2 +- .../amqp/rabbit/junit/package-info.java | 3 +- .../SpringRabbitContextCustomizer.java | 82 +++++++++++ .../SpringRabbitContextCustomizerFactory.java | 46 +++++++ .../rabbit/test/context/SpringRabbitTest.java | 79 +++++++++++ .../rabbit/test/context/package-info.java | 4 + .../main/resources/META-INF/spring.factories | 3 + .../test/context/SpringRabbitTestTests.java | 70 ++++++++++ .../RabbitBootstrapConfiguration.java | 7 +- src/reference/asciidoc/appendix.adoc | 126 +++++++++++++++++ src/reference/asciidoc/testing.adoc | 50 +++++++ src/reference/asciidoc/whats-new.adoc | 127 +----------------- 12 files changed, 474 insertions(+), 125 deletions(-) create mode 100644 spring-rabbit-test/src/main/java/org/springframework/amqp/rabbit/test/context/SpringRabbitContextCustomizer.java create mode 100644 spring-rabbit-test/src/main/java/org/springframework/amqp/rabbit/test/context/SpringRabbitContextCustomizerFactory.java create mode 100644 spring-rabbit-test/src/main/java/org/springframework/amqp/rabbit/test/context/SpringRabbitTest.java create mode 100644 spring-rabbit-test/src/main/java/org/springframework/amqp/rabbit/test/context/package-info.java create mode 100644 spring-rabbit-test/src/main/resources/META-INF/spring.factories create mode 100644 spring-rabbit-test/src/test/java/org/springframework/amqp/rabbit/test/context/SpringRabbitTestTests.java diff --git a/build.gradle b/build.gradle index a24a42a2..ddfa2ade 100644 --- a/build.gradle +++ b/build.gradle @@ -396,7 +396,7 @@ project('spring-rabbit-junit') { exclude group: 'org.springframework', module: 'spring-web' } api 'org.springframework:spring-web' - optionalApi 'org.junit.jupiter:junit-jupiter-api' + api 'org.junit.jupiter:junit-jupiter-api' api "org.assertj:assertj-core:$assertjVersion" optionalApi "ch.qos.logback:logback-classic:$logbackVersion" optionalApi 'org.apache.logging.log4j:log4j-core' diff --git a/spring-rabbit-junit/src/main/java/org/springframework/amqp/rabbit/junit/package-info.java b/spring-rabbit-junit/src/main/java/org/springframework/amqp/rabbit/junit/package-info.java index 108900af..a57318ae 100644 --- a/spring-rabbit-junit/src/main/java/org/springframework/amqp/rabbit/junit/package-info.java +++ b/spring-rabbit-junit/src/main/java/org/springframework/amqp/rabbit/junit/package-info.java @@ -1,4 +1,5 @@ /** - * Provides support classes (Rules etc) for JUnit tests. + * Provides support classes (Rules etc. with no spring-rabbit dependencies) for JUnit + * tests. */ package org.springframework.amqp.rabbit.junit; diff --git a/spring-rabbit-test/src/main/java/org/springframework/amqp/rabbit/test/context/SpringRabbitContextCustomizer.java b/spring-rabbit-test/src/main/java/org/springframework/amqp/rabbit/test/context/SpringRabbitContextCustomizer.java new file mode 100644 index 00000000..583d010f --- /dev/null +++ b/spring-rabbit-test/src/main/java/org/springframework/amqp/rabbit/test/context/SpringRabbitContextCustomizer.java @@ -0,0 +1,82 @@ +/* + * Copyright 2020 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.context; + +import org.springframework.amqp.rabbit.annotation.RabbitBootstrapConfiguration; +import org.springframework.amqp.rabbit.config.AbstractRabbitListenerContainerFactory; +import org.springframework.amqp.rabbit.config.DirectRabbitListenerContainerFactory; +import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; +import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; +import org.springframework.amqp.rabbit.core.RabbitAdmin; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.amqp.rabbit.junit.BrokerRunningSupport; +import org.springframework.amqp.rabbit.junit.RabbitAvailableCondition; +import org.springframework.amqp.rabbit.test.context.SpringRabbitTest.ContainerType; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.test.context.ContextCustomizer; +import org.springframework.test.context.MergedContextConfiguration; +import org.springframework.util.Assert; + +/** + * Adds infrastructure beans to the Spring test context. + * + * @author Gary Russell + * @since 2.3 + * + */ +class SpringRabbitContextCustomizer implements ContextCustomizer { + + private final SpringRabbitTest springRabbitTest; + + SpringRabbitContextCustomizer(SpringRabbitTest test) { + this.springRabbitTest = test; + } + + @Override + public void customizeContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) { + Assert.isInstanceOf(GenericApplicationContext.class, context); + GenericApplicationContext applicationContext = (GenericApplicationContext) context; + BrokerRunningSupport brokerRunning = RabbitAvailableCondition.getBrokerRunning(); + CachingConnectionFactory cf; + if (brokerRunning != null) { + cf = new CachingConnectionFactory(brokerRunning.getConnectionFactory()); + } + else { + cf = new CachingConnectionFactory(this.springRabbitTest.host(), this.springRabbitTest.port()); + cf.setUsername(this.springRabbitTest.user()); + cf.setPassword(this.springRabbitTest.password()); + } + applicationContext.registerBean("autoConnectionFactory", CachingConnectionFactory.class, () -> cf); + applicationContext.registerBean("autoRabbitTemplate", RabbitTemplate.class, () -> new RabbitTemplate(cf)); + applicationContext.registerBean("autoRabbitAdmin", RabbitAdmin.class, () -> new RabbitAdmin(cf)); + AbstractRabbitListenerContainerFactory factory; + if (this.springRabbitTest.containerType().equals(ContainerType.simple)) { + factory = new SimpleRabbitListenerContainerFactory(); + } + else { + factory = new DirectRabbitListenerContainerFactory(); + } + factory.setConnectionFactory(cf); + applicationContext.registerBean("autoContainerFactory", AbstractRabbitListenerContainerFactory.class, + () -> factory); + new RabbitBootstrapConfiguration().registerBeanDefinitions(null, + (BeanDefinitionRegistry) applicationContext.getBeanFactory()); + } + +} diff --git a/spring-rabbit-test/src/main/java/org/springframework/amqp/rabbit/test/context/SpringRabbitContextCustomizerFactory.java b/spring-rabbit-test/src/main/java/org/springframework/amqp/rabbit/test/context/SpringRabbitContextCustomizerFactory.java new file mode 100644 index 00000000..8d7cc16d --- /dev/null +++ b/spring-rabbit-test/src/main/java/org/springframework/amqp/rabbit/test/context/SpringRabbitContextCustomizerFactory.java @@ -0,0 +1,46 @@ +/* + * Copyright 2020 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.context; + +import java.util.List; + +import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.test.context.ContextConfigurationAttributes; +import org.springframework.test.context.ContextCustomizer; +import org.springframework.test.context.ContextCustomizerFactory; + +/** + * The {@link ContextCustomizerFactory} implementation to produce a + * {@link SpringRabbitContextCustomizer} if a {@link SpringRabbitTest} annotation + * is present on the test class. + * + * @author Gary Russell + * + * @since 2.3 + * + */ +class SpringRabbitContextCustomizerFactory implements ContextCustomizerFactory { + + @Override + public ContextCustomizer createContextCustomizer(Class testClass, + List configAttributes) { + SpringRabbitTest test = + AnnotatedElementUtils.findMergedAnnotation(testClass, SpringRabbitTest.class); + return test != null ? new SpringRabbitContextCustomizer(test) : null; + } + +} diff --git a/spring-rabbit-test/src/main/java/org/springframework/amqp/rabbit/test/context/SpringRabbitTest.java b/spring-rabbit-test/src/main/java/org/springframework/amqp/rabbit/test/context/SpringRabbitTest.java new file mode 100644 index 00000000..7277cc71 --- /dev/null +++ b/spring-rabbit-test/src/main/java/org/springframework/amqp/rabbit/test/context/SpringRabbitTest.java @@ -0,0 +1,79 @@ +/* + * Copyright 2020 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.context; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.amqp.rabbit.junit.RabbitAvailable; + +/** + * Adds infrastructure beans to a Spring test context; do not use with Spring Boot since + * it has its own auto configuration mechanism. + * + * @author Gary Russell + * @since 2.3 + * + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface SpringRabbitTest { + + /** + * Container type. + */ + enum ContainerType { + simple, direct + } + + /** + * Set the host when not using {@link RabbitAvailable}. + * @return the host. + */ + String host() default "localhost"; + + /** + * Set the port when not using {@link RabbitAvailable}. + * @return the port. + */ + int port() default 5672; + + /** + * Set the user when not using {@link RabbitAvailable}. + * @return the user. + */ + String user() default "guest"; + + /** + * Set the password when not using {@link RabbitAvailable}. + * @return the password. + */ + String password() default "guest"; + + /** + * Set the container type to determine which container factory to configure. + * @return the type. + */ + ContainerType containerType() default ContainerType.simple; + +} diff --git a/spring-rabbit-test/src/main/java/org/springframework/amqp/rabbit/test/context/package-info.java b/spring-rabbit-test/src/main/java/org/springframework/amqp/rabbit/test/context/package-info.java new file mode 100644 index 00000000..3f1e810f --- /dev/null +++ b/spring-rabbit-test/src/main/java/org/springframework/amqp/rabbit/test/context/package-info.java @@ -0,0 +1,4 @@ +/** + * Provides classes relating to the test application context. + */ +package org.springframework.amqp.rabbit.test.context; diff --git a/spring-rabbit-test/src/main/resources/META-INF/spring.factories b/spring-rabbit-test/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000..2bddfbb0 --- /dev/null +++ b/spring-rabbit-test/src/main/resources/META-INF/spring.factories @@ -0,0 +1,3 @@ +# Spring Test ContextCustomizerFactories +org.springframework.test.context.ContextCustomizerFactory=\ +org.springframework.amqp.rabbit.test.context.SpringRabbitContextCustomizerFactory diff --git a/spring-rabbit-test/src/test/java/org/springframework/amqp/rabbit/test/context/SpringRabbitTestTests.java b/spring-rabbit-test/src/test/java/org/springframework/amqp/rabbit/test/context/SpringRabbitTestTests.java new file mode 100644 index 00000000..b4c2fc7e --- /dev/null +++ b/spring-rabbit-test/src/test/java/org/springframework/amqp/rabbit/test/context/SpringRabbitTestTests.java @@ -0,0 +1,70 @@ +/* + * Copyright 2020 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.context; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +import org.springframework.amqp.rabbit.config.AbstractRabbitListenerContainerFactory; +import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; +import org.springframework.amqp.rabbit.core.RabbitAdmin; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.amqp.rabbit.junit.RabbitAvailable; +import org.springframework.amqp.rabbit.junit.RabbitAvailableCondition; +import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistry; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +/** + * @author Gary Russell + * @since 2.3 + * + */ +@RabbitAvailable +@SpringJUnitConfig +@SpringRabbitTest +public class SpringRabbitTestTests { + + @Autowired + private RabbitTemplate template; + + @SuppressWarnings("unused") + @Autowired + private RabbitAdmin admin; + + @SuppressWarnings("unused") + @Autowired + private AbstractRabbitListenerContainerFactory factory; + + @SuppressWarnings("unused") + @Autowired + private RabbitListenerEndpointRegistry registry; + + @Test + void testAutowiring() { + assertThat(((CachingConnectionFactory) template.getConnectionFactory()).getRabbitConnectionFactory()) + .isSameAs(RabbitAvailableCondition.getBrokerRunning().getConnectionFactory()); + } + + @Configuration + public static class Config { + + } + +} diff --git a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/annotation/RabbitBootstrapConfiguration.java b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/annotation/RabbitBootstrapConfiguration.java index c53efc34..9789a3b0 100644 --- a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/annotation/RabbitBootstrapConfiguration.java +++ b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/annotation/RabbitBootstrapConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata; +import org.springframework.lang.Nullable; /** * An {@link ImportBeanDefinitionRegistrar} class that registers @@ -44,7 +45,9 @@ import org.springframework.core.type.AnnotationMetadata; public class RabbitBootstrapConfiguration implements ImportBeanDefinitionRegistrar { @Override - public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + public void registerBeanDefinitions(@Nullable AnnotationMetadata importingClassMetadata, + BeanDefinitionRegistry registry) { + if (!registry.containsBeanDefinition( RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)) { diff --git a/src/reference/asciidoc/appendix.adoc b/src/reference/asciidoc/appendix.adoc index d2e96e9e..04f659de 100644 --- a/src/reference/asciidoc/appendix.adoc +++ b/src/reference/asciidoc/appendix.adoc @@ -1,3 +1,4 @@ +[[change-history]] == Change History This section describes what changes have been made as versions have changed. @@ -9,6 +10,131 @@ See <>. [[previous-whats-new]] === Previous Releases +==== Changes in 2.2 Since 2.1 + +This section describes the changes between version 2.1 and version 2.2. + +===== Package Changes + +The following classes/interfaces have been moved from `org.springframework.amqp.rabbit.core.support` to `org.springframework.amqp.rabbit.batch`: + +* `BatchingStrategy` +* `MessageBatch` +* `SimpleBatchingStrategy` + +In addition, `ListenerExecutionFailedException` has been moved from `org.springframework.amqp.rabbit.listener.exception` to `org.springframework.amqp.rabbit.support`. + +===== Dependency Changes + +JUnit (4) is now an optional dependency and will no longer appear as a transitive dependency. + +The `spring-rabbit-junit` module is now a *compile* dependency in the `spring-rabbit-test` module for a better target application development experience when with only a single `spring-rabbit-test` we get the full stack of testing utilities for AMQP components. + +===== "Breaking" API Changes + +the JUnit (5) `RabbitAvailableCondition.getBrokerRunning()` now returns a `BrokerRunningSupport` instance instead of a `BrokerRunning`, which depends on JUnit 4. +It has the same API so it's just a matter of changing the class name of any references. +See <> for more information. + +===== ListenerContainer Changes + +Messages with fatal exceptions are now rejected and NOT requeued, by default, even if the acknowledge mode is manual. +See <> for more information. + +Listener performance can now be monitored using Micrometer `Timer` s. +See <> for more information. + +===== @RabbitListener Changes + +You can now configure an `executor` on each listener, overriding the factory configuration, to more easily identify threads associated with the listener. +You can now override the container factory's `acknowledgeMode` property with the annotation's `ackMode` property. +See <> for more information. + +When using <>, `@RabbitListener` methods can now receive a complete batch of messages in one call instead of getting them one-at-a-time. + +When receiving batched messages one-at-a-time, the last message has the `isLastInBatch` message property set to true. + +In addition, received batched messages now contain the `amqp_batchSize` header. + +Listeners can also consume batches created in the `SimpleMessageListenerContainer`, even if the batch is not created by the producer. +See <> for more information. + +Spring Data Projection interfaces are now supported by the `Jackson2JsonMessageConverter`. +See <> for more information. + +The `Jackson2JsonMessageConverter` now assumes the content is JSON if there is no `contentType` property, or it is the default (`application/octet-string`). +See <> for more information. + +Similarly. the `Jackson2XmlMessageConverter` now assumes the content is XML if there is no `contentType` property, or it is the default (`application/octet-string`). +See <> for more information. + +When a `@RabbitListener` method returns a result, the bean and `Method` are now available in the reply message properties. +This allows configuration of a `beforeSendReplyMessagePostProcessor` to, for example, set a header in the reply to indicate which method was invoked on the server. +See <> for more information. + +You can now configure a `ReplyPostProcessor` to make modifications to a reply message before it is sent. +See <> for more information. + +===== AMQP Logging Appenders Changes + +The Log4J and Logback `AmqpAppender` s now support a `verifyHostname` SSL option. + +Also these appenders now can be configured to not add MDC entries as headers. +The `addMdcAsHeaders` boolean option has been introduces to configure such a behavior. + +The appenders now support the `SaslConfig` property. + +See <> for more information. + +===== MessageListenerAdapter Changes + +The `MessageListenerAdapter` provides now a new `buildListenerArguments(Object, Channel, Message)` method to build an array of arguments to be passed into target listener and an old one is deprecated. +See <> for more information. + +===== Exchange/Queue Declaration Changes + +The `ExchangeBuilder` and `QueueBuilder` fluent APIs used to create `Exchange` and `Queue` objects for declaration by `RabbitAdmin` now support "well known" arguments. +See <> for more information. + +The `RabbitAdmin` has a new property `explicitDeclarationsOnly`. +See <> for more information. + +===== Connection Factory Changes + +The `CachingConnectionFactory` has a new property `shuffleAddresses`. +When providing a list of broker node addresses, the list will be shuffled before creating a connection so that the order in which the connections are attempted is random. +See <> for more information. + +When using Publisher confirms and returns, the callbacks are now invoked on the connection factory's `executor`. +This avoids a possible deadlock in the `amqp-clients` library if you perform rabbit operations from within the callback. +See <> for more information. + +Also, the publisher confirm type is now specified with the `ConfirmType` enum instead of the two mutually exclusive setter methods. + +The `RabbitConnectionFactoryBean` now uses TLS 1.2 by default when SSL is enabled. +See <> for more information. + +===== New MessagePostProcessor Classes + +Classes `DeflaterPostProcessor` and `InflaterPostProcessor` were added to support compression and decompression, respectively, when the message content-encoding is set to `deflate`. + +===== Other Changes + +The `Declarables` object (for declaring multiple queues, exchanges, bindings) now has a filtered getter for each type. +See <> for more information. + +You can now customize each `Declarable` bean before the `RabbitAdmin` processes the declaration thereof. +See <> for more information. + +`singleActiveConsumer()` has been added to the `QueueBuilder` to set the `x-single-active-consumer` queue argument. +See <> for more information. + +Outbound headers with values of type `Class` are now mapped using `getName()` instead of `toString()`. +See <> for more information. + +Recovery of failed producer-created batches is now supported. +See <> for more information. + ==== Changes in 2.1 Since 2.0 ===== AMQP Client library diff --git a/src/reference/asciidoc/testing.adoc b/src/reference/asciidoc/testing.adoc index fff27576..81c56381 100644 --- a/src/reference/asciidoc/testing.adoc +++ b/src/reference/asciidoc/testing.adoc @@ -13,6 +13,56 @@ Spring AMQP version 1.6 introduced the `spring-rabbit-test` jar, which provides It is anticipated that this project will expand over time, but we need community feedback to make suggestions for the features needed to help with testing. Please use https://jira.spring.io/browse/AMQP[JIRA] or https://github.com/spring-projects/spring-amqp/issues[GitHub Issues] to provide such feedback. +[[spring-rabbit-test]] +==== @SpringRabbitTest + +Use this annotation to add infrastructure beans to the Spring test `ApplicationContext`. +This is not necessary when using, for example `@SpringBootTest` since Spring Boot's auto configuration will add the beans. + +Beans that are registered are: + +* `CachingConnectionFactory` (`autoConnectionFactory`). If `@RabbitEnabled` is present, its connectionn factory is used. +* `RabbitTemplate` (`autoRabbitTemplate`) +* `RabbitAdmin` (`autoRabbitAdmin`) +* `RabbitListenerContainerFactory` (`autoContainerFactory`) + +In addition, the beans associated with `@EnableRabbit` (to support `@RabbitListener`) are added. + +.Junit5 example +==== +[source, java] +---- +@SpringJunitConfig +@SpringRabbitTest +public class MyRabbitTests { + + @Autowired + private RabbitTemplate template; + + @Autowired + private RabbitAdmin admin; + + @Autowired + private RabbitListenerEndpointRegistry registry; + + @Test + void test() { + ... + } + + @Configuration + public static class Config { + + ... + + } + +} +---- +==== + +With JUnit4, replace `@SpringJunitConfig` with `@RunWith(SpringRunnner.class)`. + [[mockito-answer]] ==== Mockito `Answer` Implementations diff --git a/src/reference/asciidoc/whats-new.adoc b/src/reference/asciidoc/whats-new.adoc index 6f04d6bc..12cd2e3e 100644 --- a/src/reference/asciidoc/whats-new.adoc +++ b/src/reference/asciidoc/whats-new.adoc @@ -1,127 +1,12 @@ [[whats-new]] == What's New -=== Changes in 2.2 Since 2.1 +=== Changes in 2.3 Since 2.2 -This section describes the changes between version 2.1 and version 2.2. +This section describes the changes between version 2.2 and version 2.3. +See <> for changes in previous versions. -==== Package Changes +==== Testing Changes -The following classes/interfaces have been moved from `org.springframework.amqp.rabbit.core.support` to `org.springframework.amqp.rabbit.batch`: - -* `BatchingStrategy` -* `MessageBatch` -* `SimpleBatchingStrategy` - -In addition, `ListenerExecutionFailedException` has been moved from `org.springframework.amqp.rabbit.listener.exception` to `org.springframework.amqp.rabbit.support`. - -==== Dependency Changes - -JUnit (4) is now an optional dependency and will no longer appear as a transitive dependency. - -The `spring-rabbit-junit` module is now a *compile* dependency in the `spring-rabbit-test` module for a better target application development experience when with only a single `spring-rabbit-test` we get the full stack of testing utilities for AMQP components. - -==== "Breaking" API Changes - -the JUnit (5) `RabbitAvailableCondition.getBrokerRunning()` now returns a `BrokerRunningSupport` instance instead of a `BrokerRunning`, which depends on JUnit 4. -It has the same API so it's just a matter of changing the class name of any references. -See <> for more information. - -==== ListenerContainer Changes - -Messages with fatal exceptions are now rejected and NOT requeued, by default, even if the acknowledge mode is manual. -See <> for more information. - -Listener performance can now be monitored using Micrometer `Timer` s. -See <> for more information. - -==== @RabbitListener Changes - -You can now configure an `executor` on each listener, overriding the factory configuration, to more easily identify threads associated with the listener. -You can now override the container factory's `acknowledgeMode` property with the annotation's `ackMode` property. -See <> for more information. - -When using <>, `@RabbitListener` methods can now receive a complete batch of messages in one call instead of getting them one-at-a-time. - -When receiving batched messages one-at-a-time, the last message has the `isLastInBatch` message property set to true. - -In addition, received batched messages now contain the `amqp_batchSize` header. - -Listeners can also consume batches created in the `SimpleMessageListenerContainer`, even if the batch is not created by the producer. -See <> for more information. - -Spring Data Projection interfaces are now supported by the `Jackson2JsonMessageConverter`. -See <> for more information. - -The `Jackson2JsonMessageConverter` now assumes the content is JSON if there is no `contentType` property, or it is the default (`application/octet-string`). -See <> for more information. - -Similarly. the `Jackson2XmlMessageConverter` now assumes the content is XML if there is no `contentType` property, or it is the default (`application/octet-string`). -See <> for more information. - -When a `@RabbitListener` method returns a result, the bean and `Method` are now available in the reply message properties. -This allows configuration of a `beforeSendReplyMessagePostProcessor` to, for example, set a header in the reply to indicate which method was invoked on the server. -See <> for more information. - -You can now configure a `ReplyPostProcessor` to make modifications to a reply message before it is sent. -See <> for more information. - -==== AMQP Logging Appenders Changes - -The Log4J and Logback `AmqpAppender` s now support a `verifyHostname` SSL option. - -Also these appenders now can be configured to not add MDC entries as headers. -The `addMdcAsHeaders` boolean option has been introduces to configure such a behavior. - -The appenders now support the `SaslConfig` property. - -See <> for more information. - -==== MessageListenerAdapter Changes - -The `MessageListenerAdapter` provides now a new `buildListenerArguments(Object, Channel, Message)` method to build an array of arguments to be passed into target listener and an old one is deprecated. -See <> for more information. - -==== Exchange/Queue Declaration Changes - -The `ExchangeBuilder` and `QueueBuilder` fluent APIs used to create `Exchange` and `Queue` objects for declaration by `RabbitAdmin` now support "well known" arguments. -See <> for more information. - -The `RabbitAdmin` has a new property `explicitDeclarationsOnly`. -See <> for more information. - -==== Connection Factory Changes - -The `CachingConnectionFactory` has a new property `shuffleAddresses`. -When providing a list of broker node addresses, the list will be shuffled before creating a connection so that the order in which the connections are attempted is random. -See <> for more information. - -When using Publisher confirms and returns, the callbacks are now invoked on the connection factory's `executor`. -This avoids a possible deadlock in the `amqp-clients` library if you perform rabbit operations from within the callback. -See <> for more information. - -Also, the publisher confirm type is now specified with the `ConfirmType` enum instead of the two mutually exclusive setter methods. - -The `RabbitConnectionFactoryBean` now uses TLS 1.2 by default when SSL is enabled. -See <> for more information. - -==== New MessagePostProcessor Classes - -Classes `DeflaterPostProcessor` and `InflaterPostProcessor` were added to support compression and decompression, respectively, when the message content-encoding is set to `deflate`. - -==== Other Changes - -The `Declarables` object (for declaring multiple queues, exchanges, bindings) now has a filtered getter for each type. -See <> for more information. - -You can now customize each `Declarable` bean before the `RabbitAdmin` processes the declaration thereof. -See <> for more information. - -`singleActiveConsumer()` has been added to the `QueueBuilder` to set the `x-single-active-consumer` queue argument. -See <> for more information. - -Outbound headers with values of type `Class` are now mapped using `getName()` instead of `toString()`. -See <> for more information. - -Recovery of failed producer-created batches is now supported. -See <> for more information. +A new annotation `@SpringBootTest` is provided to automatically configure some infrastructure beans for when you are not using `SpringBootTest`. +See <> for more information.