LIBRARIES-1670 - update to springboot3 and java21/migration to junit5/mockito#20
LIBRARIES-1670 - update to springboot3 and java21/migration to junit5/mockito#20julian-eggers wants to merge 44 commits into
Conversation
Upgrades the module from Spring Boot 2.6.x/Java 11 to Spring Boot 3.5.16/Java 21 (spring-framework 6.2.19, spring-amqp/spring-rabbit 3.2.12), converting the entire test suite from JUnit4/PowerMock/EasyMock to JUnit5/Mockito along the way. Key fixes beyond the mechanical dependency bump: - DefaultMessageListenerContainer no longer overrides the internal createBlockingQueueConsumer()/BlockingQueueConsumer.setDeclarationRetries(...) extension point (still present unchanged in spring-rabbit 3.2.12, but not a stable API). It now calls the public SimpleMessageListenerContainer#setDeclarationRetries(int), which has applied the same value to every created BlockingQueueConsumer since Spring AMQP 1.3.9, eliminating the internal-API dependency entirely. - RabbitProperties#setAddresses/getAddresses/determineAddresses changed from comma-separated String to List<String> in Boot 3; fixed the address list conversion in CustomConnectionFactoryCreator/tests, and fixed a silent logic break in ConnectionFactoryProvider where the old ".contains(\",\")" multi-host guard against determineAddresses() always evaluated to a no-op against the new List<String>, which would have made the QueueMasterLocatorConnectionFactory bypass fire even when multiple hosts were configured. - QueueMasterLocatorConnectionFactory switched to building the RabbitMQ HTTP API Client via ClientParameters (JDK-native HttpClient) instead of the deprecated 3-arg Client(url, username, password) constructor, which hard-wires HttpComponentsRestTemplateConfigurator (Apache HttpClient 4.x); Spring Framework 6's HttpComponentsClientHttpRequestFactory only accepts Apache HttpClient 5.x, so that path now fails at runtime with NoClassDefFoundError. - Added META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports (replacing META-INF/spring.factories' EnableAutoConfiguration key, which Boot 3 no longer reads) so SpringRabbitAutoConfiguration is actually picked up. - SpringRabbitAutoConfiguration now sets an explicit ResolvableType target type when registering DefaultMessageListenerContainer beans, since Spring 6 is stricter about matching the generic type of @Autowired @qualifier(...) injection points against beans registered with a raw Class + Supplier. - javax.validation -> jakarta.validation, javax.xml.bind -> jakarta.xml.bind (JAXB test fixtures), removed a fragile javax.ws.rs dependency in AbstractIT. - Converted all PowerMock/EasyMock usage (15 files) and remaining JUnit4 tests to JUnit5 + Mockito (mockStatic/mockConstruction, ReflectionTestUtils instead of Whitebox). Version bumped to 3.0.0 (major/breaking) per the Spring Boot 3 migration. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
….annotation-api workaround springtainer-rabbitmq 2.0.1 carries the real fix (springtainer-common 2.0.1's explicit javax.annotation-api dependency) for docker-java's Jersey transport needing javax.annotation.Priority under Boot 3. The local test-scope workaround this pom carried since the original migration is now redundant. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…t 3.5.16 baseline springtainer-rabbitmq 2.0.2 carries springtainer-common 2.0.2's explicit DockerHttpClient configuration, fixing the "Falling back to Jersey" warning on every container-based IT run. awaitility 4.1.1 was behind the fleet's established 4.2.2 baseline. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Carries springtainer-common 2.0.3's fix for the stale-container check missing pileup once Spring's test-context cache stabilizes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Carries springtainer-common 2.0.5's corrected container-cleanup fix (periodic threshold-check + JVM shutdown hook; the proactive stop-previous approach tried in between was reverted as unsafe with Spring's test-context cache reuse). Verified clean across 3 consecutive full test suite runs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Carries springtainer-common 2.0.6's removal of the unused legacy Jersey/ JAX-RS 2.x transport dependency from docker-java. Full suite green (238 Unit / 20 IT, 0/0). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ound - maven-source-plugin: 3.3.1 -> 3.4.0, matching the rest of the ecosystem - Removed failOnError=false: the underlying javadoc bug was fixed in JDK 12/13 and no longer occurs on the JDK now in use (same finding already applied to springtainer-* and test-support) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Never dereferenced anywhere in the pom (unlike maven.build.timestamp.format, which Maven itself consumes to format its built-in timestamp). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VMKK3eM4V5EUoqUpbNxSJk
Removes the legacy Sonatype OSSRH setup (distributionManagement, repositories, nexus-staging-maven-plugin, github-release-plugin) in favor of central-publishing-maven-plugin + exists-maven-plugin, matching the springtainer-common OS reference. Bumps maven-gpg-plugin (3.0.1->3.2.8), maven-release-plugin (3.0.0-M5->3.3.1), and exists-maven-plugin (0.6.0->0.15.2) to the reference versions, and aligns the compiler-plugin config (adds <parameters>true</parameters>) so the <build> section is now 100% identical to springtainer-common's, per the java-module-structure convention. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VMKK3eM4V5EUoqUpbNxSJk
assertj.version -> assertj-core.version, glassfish-jaxb.version -> jaxb-runtime.version, jakarta-xml-bind.version -> jakarta.xml.bind-api.version, jakarta-el.version -> jakarta.el.version, junit-jupiter.version -> junit-jupiter-engine.version (only one consumer here, unlike the multi-module libraries); collapsed the logback/micrometer alias pairs down to their single-consumer specific property. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VMKK3eM4V5EUoqUpbNxSJk
Reorder the Spring property group to match its dependency declaration order (spring-framework.version was listed first even though its dependency, spring-web, is declared last in the group). Collapse the spring.version alias into spring-framework.version - it was only ever referenced by its own replacement, never directly by a dependency, same dead-weight pattern already fixed in vectis-core/vectis-avides. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VMKK3eM4V5EUoqUpbNxSJk
System+Build merged per the new fixed properties-frame rule. Validation (hibernate-validator, 1 member) and Other (lombok, 1 member) each fell below the new dependency-group minimum size of >1 - merged into a single Other group with both. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VMKK3eM4V5EUoqUpbNxSJk
Import spring-boot-dependencies BOM and drop BOM-managed pins (the manual Jackson convergence and byte-buddy 1.17.8 overrides are now enforced by the BOM). Update the stale springtainer-rabbitmq test dependency 2.0.7 -> 2.1.2. Kept non-BOM pins (rabbitmq http-client, httpclient 4.5.14, jaxb-runtime, jakarta.el, spring-xom-unmarshaller). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019yDnQ6P4qY2FcYTour9nQq
Unify the <project> schemaLocation on https://maven.apache.org/xsd/maven-4.0.0.xsd (replacing the legacy maven-v4_0_0.xsd / http variants). Cosmetic only; the POM namespace and modelVersion 4.0.0 are unchanged and the build is unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019yDnQ6P4qY2FcYTour9nQq
spring-boot-dependencies:3.5.16 imports org.glassfish.jaxb:jaxb-bom:4.0.9, which manages jaxb-runtime at exactly the pinned 4.0.9 - the explicit pin was redundant. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019yDnQ6P4qY2FcYTour9nQq
Part of the org-wide switch to a major-only X.0.0-RC1 version scheme used as a mutable snapshot during the ongoing SB3 migration. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019yDnQ6P4qY2FcYTour9nQq
|
There was a problem hiding this comment.
Pull request overview
This PR performs the migration of the library to the Spring Boot 3 / Java 21 ecosystem, including the transition from javax.* to jakarta.* APIs and updating the test stack from JUnit 4 / PowerMock/EasyMock to JUnit 5 / Mockito. It also modernizes Maven dependency management and CI workflows to align with the newer platform versions.
Changes:
- Migrate core code and configuration from
javax.validation.*tojakarta.validation.*, and adapt Rabbit/Spring Boot 3 API changes (e.g., Rabbit addresses now asList<String>). - Convert unit/integration tests to JUnit 5 and Mockito (replacing JUnit 4 + PowerMock/EasyMock patterns).
- Update build/release infrastructure: Maven Central publishing changes, Spring Boot BOM import, and refreshed GitHub Actions workflows.
Reviewed changes
Copilot reviewed 70 out of 70 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/test/java/com/avides/spring/rabbit/utils/ValidationUtilTest.java | Migrates JUnit4 assertions/expected-exception to JUnit5 (assertThrows). |
| src/test/java/com/avides/spring/rabbit/utils/ValidationUtil.java | Switches validation imports to jakarta.validation.*. |
| src/test/java/com/avides/spring/rabbit/utils/DomainTestSupport.java | Adjusts RabbitProperties#setAddresses usage to Spring Boot 3 List<String> API. |
| src/test/java/com/avides/spring/rabbit/utils/BeanValidationTestSupportTest.java | Migrates validation + assertions to Jakarta + JUnit5 Assertions. |
| src/test/java/com/avides/spring/rabbit/utils/BeanValidationTestSupport.java | Switches ConstraintViolation import to jakarta.validation. |
| src/test/java/com/avides/spring/rabbit/test/support/AbstractIT.java | Migrates JUnit runner to JUnit5 extension + JAXB/Jakarta adjustments. |
| src/test/java/com/avides/spring/rabbit/listener/RequestResponseSpringRabbitListenerTest.java | Replaces PowerMock/EasyMock with Mockito + ReflectionTestUtils for field injection. |
| src/test/java/com/avides/spring/rabbit/listener/OptionalResponseSpringRabbitListenerTest.java | Replaces PowerMock/EasyMock with Mockito + ReflectionTestUtils for field injection. |
| src/test/java/com/avides/spring/rabbit/listener/CountingRabbitListenerTest.java | Migrates listener tests to JUnit5/Mockito, replacing PowerMock TestSubject usage. |
| src/test/java/com/avides/spring/rabbit/listener/CountingContextAwareRabbitListenerTest.java | Migrates context-aware listener tests to JUnit5/Mockito. |
| src/test/java/com/avides/spring/rabbit/listener/container/DefaultMessageListenerContainerTest.java | Updates tests for new container behavior and exception assertions (AssertJ). |
| src/test/java/com/avides/spring/rabbit/listener/AbstractSpringRabbitListenerTest.java | Migrates to MockitoExtension and Mockito stubbing. |
| src/test/java/com/avides/spring/rabbit/converter/SpringRabbitJsonMessageConverterTest.java | Migrates to JUnit5. |
| src/test/java/com/avides/spring/rabbit/configuration/ValidationErrorHandlerTest.java | Removes reliance on Hibernate internal classes; uses Mockito mock for violations. |
| src/test/java/com/avides/spring/rabbit/configuration/util/MessagePostProcessorUtilsTest.java | Migrates from PowerMock/EasyMock to Mockito verification. |
| src/test/java/com/avides/spring/rabbit/configuration/util/DefaultValueResolverTest.java | Migrates from PowerMock/EasyMock to Mockito stubbing. |
| src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationWithoutConnectionsIT.java | Migrates integration test to JUnit5. |
| src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationWithBeforePublishPostProcessorCountingOutboundIT.java | Migrates lifecycle hooks to @BeforeEach/@AfterEach. |
| src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationWithBeforePublishPostProcessorCountingOutboundIsDisabledIT.java | Migrates assertions and lifecycle hooks to JUnit5. |
| src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationWithBeforePublishPostProcessorAppIdEnricherWithoutConfiguredAppIdIT.java | Migrates lifecycle hooks to JUnit5. |
| src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationWithBeforePublishPostProcessorAppIdEnricherWithConfiguredAppIdIT.java | Migrates lifecycle hooks to JUnit5. |
| src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationWithBeforePublishPostProcessorAppIdEnricherWithConfiguredAppIdByArtifactIdIT.java | Migrates lifecycle hooks to JUnit5. |
| src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationWithBeforePublishPostProcessorAppIdEnricherIsDisabledIT.java | Migrates lifecycle hooks to JUnit5. |
| src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationTest.java | Migrates to JUnit5 @BeforeEach and JUnit5 assertions. |
| src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationForSpringRabbitJsonMessageConverterIT.java | Migrates @After to @AfterEach. |
| src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationForRabbitTemplateManagementWithOneConnectionFactoryIT.java | Migrates to JUnit5 assertions/tests. |
| src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationForQueueManagementWithOneConnectionFactoryIT.java | Migrates to JUnit5 assertions/tests. |
| src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationForQueueCreationDisabledIT.java | Migrates to JUnit5 assertions/tests. |
| src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationForMultipleConnectionFactoriesWithSameListenerMultipleUsedIT.java | Migrates to JUnit5 assertions/tests. |
| src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationForMultipleConnectionFactoriesIT.java | Migrates to JUnit5 assertions/tests. |
| src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationForListenerCreationDisabledIT.java | Migrates to JUnit5 assertions/tests. |
| src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationForDifferentPrefetchCountIT.java | Migrates to JUnit5 assertions/tests. |
| src/test/java/com/avides/spring/rabbit/configuration/provider/ConnectionFactoryProviderTest.java | Replaces PowerMock static mocking with Mockito MockedStatic. |
| src/test/java/com/avides/spring/rabbit/configuration/domain/RabbitTemplatePropertiesTest.java | Migrates to JUnit5 assertions. |
| src/test/java/com/avides/spring/rabbit/configuration/domain/RabbitAdminPropertiesTest.java | Migrates to JUnit5 assertions. |
| src/test/java/com/avides/spring/rabbit/configuration/domain/QueuePropertiesTest.java | Migrates to JUnit5 assertions. |
| src/test/java/com/avides/spring/rabbit/configuration/domain/QueueMasterLocatorConnectionFactoryTest.java | Migrates to Mockito and JUnit5 lifecycle. |
| src/test/java/com/avides/spring/rabbit/configuration/domain/MessageConverterPropertiesTest.java | Migrates to JUnit5 assertions. |
| src/test/java/com/avides/spring/rabbit/configuration/domain/ListenerPropertiesTest.java | Migrates to JUnit5 assertions. |
| src/test/java/com/avides/spring/rabbit/configuration/domain/ExchangePropertiesTest.java | Migrates to JUnit5 assertions. |
| src/test/java/com/avides/spring/rabbit/configuration/domain/CustomConnectionFactoryPropertiesTest.java | Migrates to JUnit5 assertions. |
| src/test/java/com/avides/spring/rabbit/configuration/domain/BeanReferenceConnectionFactoryPropertiesTest.java | Migrates to JUnit5 assertions. |
| src/test/java/com/avides/spring/rabbit/configuration/creator/RabbitAdminCreatorTest.java | Migrates to MockitoExtension and JUnit5. |
| src/test/java/com/avides/spring/rabbit/configuration/creator/QueueCreatorTest.java | Migrates from EasyMock/PowerMock patterns to Mockito stubbing/verification. |
| src/test/java/com/avides/spring/rabbit/configuration/creator/ListenerCreatorTest.java | Migrates to MockitoExtension and JUnit5. |
| src/test/java/com/avides/spring/rabbit/configuration/creator/ExchangeCreatorTest.java | Migrates to JUnit5. |
| src/test/java/com/avides/spring/rabbit/configuration/creator/DlxQueueCreatorTest.java | Migrates to Mockito and JUnit5. |
| src/test/java/com/avides/spring/rabbit/configuration/creator/CustomConnectionFactoryCreatorTest.java | Migrates static mocking to Mockito mockStatic + adapts addresses list API. |
| src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports | Updates auto-configuration registration format for Spring Boot 3. |
| src/main/java/com/avides/spring/rabbit/listener/SpringRabbitListener.java | Switches @Valid to jakarta.validation.Valid. |
| src/main/java/com/avides/spring/rabbit/listener/RabbitListener.java | Switches @Valid to jakarta.validation.Valid. |
| src/main/java/com/avides/spring/rabbit/listener/container/DefaultMessageListenerContainer.java | Reworks declaration retry configuration to use public setDeclarationRetries. |
| src/main/java/com/avides/spring/rabbit/configuration/ValidationErrorHandler.java | Switches validation imports to jakarta.validation.*. |
| src/main/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfiguration.java | Updates validation imports and Spring 6 bean registration target type handling. |
| src/main/java/com/avides/spring/rabbit/configuration/provider/ConnectionFactoryProvider.java | Adapts multi-address detection for Spring Boot 3 address API changes. |
| src/main/java/com/avides/spring/rabbit/configuration/domain/RabbitTemplateProperties.java | Switches validation imports to jakarta.validation.*. |
| src/main/java/com/avides/spring/rabbit/configuration/domain/RabbitAdminProperties.java | Switches validation imports to jakarta.validation.*. |
| src/main/java/com/avides/spring/rabbit/configuration/domain/QueueProperties.java | Switches validation imports to jakarta.validation.*. |
| src/main/java/com/avides/spring/rabbit/configuration/domain/QueueMasterLocatorConnectionFactory.java | Updates RabbitMQ HTTP client construction to avoid Spring 6 HttpClient incompatibilities. |
| src/main/java/com/avides/spring/rabbit/configuration/domain/MessageConverterProperties.java | Switches validation imports to jakarta.validation.*. |
| src/main/java/com/avides/spring/rabbit/configuration/domain/ListenerProperties.java | Switches validation imports to jakarta.validation.*. |
| src/main/java/com/avides/spring/rabbit/configuration/domain/ExchangeProperties.java | Switches validation imports to jakarta.validation.*. |
| src/main/java/com/avides/spring/rabbit/configuration/domain/CustomConnectionFactoryProperties.java | Switches validation imports to jakarta.validation.*. |
| src/main/java/com/avides/spring/rabbit/configuration/domain/BeanReferenceConnectionFactoryProperties.java | Switches validation imports to jakarta.validation.*. |
| src/main/java/com/avides/spring/rabbit/configuration/creator/CustomConnectionFactoryCreator.java | Adapts RabbitProperties addresses handling for Spring Boot 3 (List<String>). |
| README.md | Updates documented dependency version to 3.0.0-RC1. |
| pom.xml | Upgrades to Java 21 / Spring Boot BOM import; modernizes plugins and publishing approach. |
| .github/workflows/review.yml | Updates review workflow actions, concurrency, Java version detection, and Sonar invocation. |
| .github/workflows/release.yml | Updates release pipeline for Maven Central publishing and modern actions/outputs usage. |
| .github/workflows/nightly.yml | Updates nightly pipeline with Java version detection and modern Sonar invocation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Fix Jaxb2Marshaller in AbstractIT scanning an empty package for JAXB classes (flagged by Copilot review): jakarta.ws.rs was intentionally removed as a dependency during the migration, leaving no bindable classes in the scanned package. Bind an explicit marker class instead. Also remove the "previously ... / since Spring Boot X" explainer comments left behind from the migration, per self-review notes on the PR - useful during the migration itself, noise for future readers. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
QueueMasterLocatorConnectionFactory builds the RabbitMQ management API client via ClientParameters, which defaults to com.rabbitmq:http-client's JDK-native HttpClient transport. The explicit org.apache.httpcomponents: httpclient 4.5.14 pin was only needed by the deprecated 3-arg Client constructor this code no longer uses, and isn't pulled in transitively by anything else - grep confirms zero references left in the codebase. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
| @Test | ||
| public void testResolveConnectionFactoryWithCustomPropertiesAndNotFound() | ||
| { | ||
| applicationContext.getBean("customConnectionFactoryBeanName", ConnectionFactory.class); | ||
| expectLastCall().andReturn(null); | ||
| when(applicationContext.getBean("customConnectionFactoryBeanName", ConnectionFactory.class)).thenReturn(null); | ||
|
|
||
| try | ||
| { | ||
| replayAll(); | ||
| resolveConnectionFactory(getCompleteBeanReferenceConnectionFactoryProperties(), null, applicationContext); | ||
| verifyAll(); | ||
| } | ||
| catch (IllegalArgumentException e) | ||
| { |
| @Test | ||
| public void testResolveConnectionFactoryWithDefaultBeanNameAndNotFound() | ||
| { | ||
| applicationContext.getBean("springRabbitConnectionFactory", ConnectionFactory.class); | ||
| expectLastCall().andReturn(null); | ||
| when(applicationContext.getBean("springRabbitConnectionFactory", ConnectionFactory.class)).thenReturn(null); | ||
|
|
||
| try | ||
| { | ||
| replayAll(); | ||
| resolveConnectionFactory(null, "springRabbitConnectionFactory", applicationContext); | ||
| verifyAll(); | ||
| } | ||
| catch (IllegalArgumentException e) | ||
| { |
| { | ||
| try | ||
| { | ||
| replayAll(); | ||
| resolveConnectionFactory(null, null, applicationContext); | ||
| verifyAll(); | ||
| } | ||
| catch (IllegalArgumentException e) | ||
| { |
| @Test | ||
| public void testResolveMessageConverterWithCustomPropertiesAndNotFound() | ||
| { | ||
| applicationContext.getBean("unknownBeanName", MessageConverter.class); | ||
| expectLastCall().andReturn(null); | ||
| when(applicationContext.getBean("unknownBeanName", MessageConverter.class)).thenReturn(null); | ||
|
|
||
| try | ||
| { | ||
| replayAll(); | ||
| resolveMessageConverter(getCompleteMessageConverterProperties("unknownBeanName"), null, applicationContext, Arrays | ||
| .asList(jsonMessageConverter, xmlMessageConverter)); | ||
| verifyAll(); | ||
| } | ||
| catch (IllegalArgumentException e) | ||
| { |
| @Test | ||
| public void testResolveMessageConverterWithDefaultPropertiesAndNotFound() | ||
| { | ||
| applicationContext.getBean("unknownBeanName", MessageConverter.class); | ||
| expectLastCall().andReturn(null); | ||
| when(applicationContext.getBean("unknownBeanName", MessageConverter.class)).thenReturn(null); | ||
|
|
||
| try | ||
| { | ||
| replayAll(); | ||
| resolveMessageConverter(null, getCompleteMessageConverterProperties("unknownBeanName"), applicationContext, Arrays | ||
| .asList(jsonMessageConverter, xmlMessageConverter)); | ||
| verifyAll(); | ||
| } | ||
| catch (IllegalArgumentException e) | ||
| { |
| verify(rabbitAdmin).declareQueue(any(Queue.class)); | ||
| verify(rabbitAdmin).declareExchange(exchange); |
| try | ||
| { | ||
| replayAll(); | ||
| QueueProperties completeQueueProperties = getCompleteQueueProperties(); | ||
| completeQueueProperties.setRoutingkey(""); | ||
| creator = new QueueCreator(completeQueueProperties, rabbitAdmin, exchange); | ||
| creator.createInstance(); | ||
| verifyAll(); | ||
| } |
| try | ||
| { | ||
| replayAll(); | ||
| QueueProperties completeQueueProperties = getCompleteQueueProperties(); | ||
| completeQueueProperties.setRoutingkey(null); | ||
| completeQueueProperties.setRoutingkeys(Arrays.asList("")); | ||
| creator = new QueueCreator(completeQueueProperties, rabbitAdmin, exchange); | ||
| creator.createInstance(); | ||
| verifyAll(); | ||
| } |
| try | ||
| { | ||
| replayAll(); | ||
| creator = new ListenerCreator(connectionFactory, "testQueueName", 50, 2, messageConverter, Integer.valueOf(12)); | ||
| creator.createInstance(); | ||
| verifyAll(); | ||
| } |
| var consumer = super.createBlockingQueueConsumer(); | ||
| consumer.setDeclarationRetries(1000000); // infinity | ||
| return consumer; | ||
| setDeclarationRetries(1000000); // infinity |
… property Avoids leaking the passphrase via a Maven -D property and silences the maven-gpg-plugin deprecation warning during Maven Central deployment.
| } | ||
|
|
||
| @Test | ||
| public void testResolveAdditionalMessagePostProcessorsWithCountingOutboundisDisabled() |
| creator = new ListenerCreator(connectionFactory, "testQueueName", 50, 2, messageConverter, Integer.valueOf(12)); | ||
| creator.createInstance(); | ||
| verifyAll(); | ||
| } |
| try | ||
| { | ||
| replayAll(); | ||
| resolveConnectionFactory(getCompleteBeanReferenceConnectionFactoryProperties(), null, applicationContext); | ||
| verifyAll(); | ||
| } |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 70 out of 70 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (1)
src/main/java/com/avides/spring/rabbit/configuration/creator/CustomConnectionFactoryCreator.java:49
- RabbitProperties#determineAddresses() is a List (Spring Boot 3.4+/3.5+), but CachingConnectionFactory#setAddresses expects a comma-delimited String in Spring AMQP. Passing the List through here will either not compile or misconfigure the connection factory. Join the addresses list before calling setAddresses.
CachingConnectionFactory factory = new CachingConnectionFactory();
factory.setHost(rabbitProperties.determineHost());
factory.setAddresses(rabbitProperties.determineAddresses());
factory.setPort(rabbitProperties.determinePort());
| @Test | ||
| public void testHandle() | ||
| { | ||
| meterRegistry.counter("rabbit.listener.event", "listener", "ImplementedCountingListener"); | ||
| expectLastCall().andReturn(mock(Counter.class)); | ||
| when(meterRegistry.counter("rabbit.listener.event", "listener", "ImplementedCountingListener")).thenReturn(mock(Counter.class)); | ||
| when(meterRegistry.counter("rabbit.listener.event.total.duration.milliseconds", "listener", "ImplementedCountingListener")).thenReturn(mock(Counter.class)); | ||
|
|
||
| meterRegistry.counter("rabbit.listener.event.total.duration.milliseconds", "listener", "ImplementedCountingListener"); | ||
| expectLastCall().andReturn(mock(Counter.class)); | ||
|
|
||
| replayAll(); | ||
| rabbitListener.handle("hello"); |
| @Test | ||
| public void testHandle() | ||
| { | ||
| Tags tags = Tags.of(Tag.of("listener", "ImplementedSpringRabbitListener"), Tag.of("from", "sender-app")); | ||
| expect(meterRegistry.counter("rabbit.listener.event", tags)).andReturn(mock(Counter.class)); | ||
| expect(meterRegistry.counter("rabbit.listener.event.total.duration.milliseconds", tags)).andReturn(mock(Counter.class)); | ||
| when(meterRegistry.counter("rabbit.listener.event", tags)).thenReturn(mock(Counter.class)); | ||
| when(meterRegistry.counter("rabbit.listener.event.total.duration.milliseconds", tags)).thenReturn(mock(Counter.class)); | ||
|
|
||
| replayAll(); | ||
| var messageProperties = new MessageProperties(); | ||
| messageProperties.setAppId("sender-app"); | ||
| rabbitListener.handle("hello", messageProperties); |
| @Test | ||
| public void testHandleEventWithoutCorrelationId() | ||
| { | ||
| var tags = Tags.of(Tag.of("listener", "SuccessRequestResponseSpringRabbitListener"), Tag.of("from", "sender-app")); | ||
|
|
||
| responseRabbitTemplate.convertAndSend(eq(""), eq("response-queue"), eq("response"), EasyMock.anyObject(MessagePostProcessor.class)); | ||
| expect(meterRegistry.counter("rabbit.listener.event", tags)).andReturn(mock(Counter.class)); | ||
| expect(meterRegistry.counter("rabbit.listener.event.total.duration.milliseconds", tags)).andReturn(mock(Counter.class)); | ||
| when(meterRegistry.counter("rabbit.listener.event", tags)).thenReturn(mock(Counter.class)); | ||
| when(meterRegistry.counter("rabbit.listener.event.total.duration.milliseconds", tags)).thenReturn(mock(Counter.class)); | ||
|
|
||
| replayAll(); | ||
| var messageProperties = new MessageProperties(); | ||
| messageProperties.setAppId("sender-app"); | ||
| messageProperties.setReplyTo("response-queue"); | ||
| successRabbitListener.handle("", messageProperties); | ||
| verifyAll(); | ||
|
|
||
| verify(responseRabbitTemplate).convertAndSend(eq(""), eq("response-queue"), eq("response"), any(MessagePostProcessor.class)); | ||
| } |
| @Test | ||
| public void testHandleEvent() | ||
| { | ||
| var tags = Tags.of(Tag.of("listener", "SuccessOptionalSpringRabbitListener"), Tag.of("from", "sender-app")); | ||
|
|
||
| responseRabbitTemplate.convertAndSend(eq(""), eq("response-queue"), eq("response"), EasyMock.anyObject(MessagePostProcessor.class)); | ||
| expect(meterRegistry.counter("rabbit.listener.event", tags)).andReturn(mock(Counter.class)); | ||
| expect(meterRegistry.counter("rabbit.listener.event.total.duration.milliseconds", tags)).andReturn(mock(Counter.class)); | ||
| when(meterRegistry.counter("rabbit.listener.event", tags)).thenReturn(mock(Counter.class)); | ||
| when(meterRegistry.counter("rabbit.listener.event.total.duration.milliseconds", tags)).thenReturn(mock(Counter.class)); | ||
|
|
||
| replayAll(); | ||
| var messageProperties = new MessageProperties(); | ||
| messageProperties.setAppId("sender-app"); | ||
| messageProperties.setCorrelationId("request1"); | ||
| messageProperties.setReplyTo("response-queue"); | ||
| successRabbitListener.handle("", messageProperties); | ||
| verifyAll(); | ||
|
|
||
| verify(responseRabbitTemplate).convertAndSend(eq(""), eq("response-queue"), eq("response"), any(MessagePostProcessor.class)); | ||
| } |
…release The git tag/version 3.0.0-RC1 was already published to Maven Central years ago (2022, commit c306c42 on master, Spring Boot 2.6.3 era) from an abandoned earlier attempt at a 3.0 release. The "major-only RC1" version scheme adopted on this branch reused that exact version string without realizing it was already permanently taken on Central, so today's publish of the actual Spring-Boot-3.5.16-based code could never really replace it: consumers fetching "3.0.0-RC1" keep getting the old 2.6.3 jar, which is binary-incompatible with 3.5.16 (RabbitProperties.determineAddresses() changed from String to List<String>), breaking anything that depends on spring-rabbit under Spring Boot 3.5.x (e.g. vectis-avides). Also temporarily releases from this migration branch directly (see release.yml) instead of requiring a merge to master first.
| <groupId>com.avides.spring</groupId> | ||
| <artifactId>spring-rabbit</artifactId> | ||
| <version>2.7.0</version> | ||
| <version>3.0.0-RC1</version> |
| var consumer = super.createBlockingQueueConsumer(); | ||
| consumer.setDeclarationRetries(1000000); // infinity | ||
| return consumer; | ||
| setDeclarationRetries(1000000); // infinity |
Same problem as 3.0.0-RC1: the 3.0.x version line was already used (and published to Maven Central) by an earlier, abandoned attempt at a 3.0 release. Skipping the whole 3.0.x line and moving to 4.0.0-RC1 to get a version string that was never previously published.
| private static List<String> splitAddresses(String addresses) | ||
| { | ||
| return Arrays.asList(StringUtils.commaDelimitedListToStringArray(addresses)); | ||
| } |
| verify(rabbitAdmin).declareQueue(any(Queue.class)); | ||
| verify(rabbitAdmin).declareExchange(exchange); | ||
| } |
| when(meterRegistry.counter("rabbit.listener.event", "listener", "ImplementedCountingListener")).thenReturn(mock(Counter.class)); | ||
| when(meterRegistry.counter("rabbit.listener.event.total.duration.milliseconds", "listener", "ImplementedCountingListener")).thenReturn(mock(Counter.class)); | ||
|
|
||
| meterRegistry.counter("rabbit.listener.event.total.duration.milliseconds", "listener", "ImplementedCountingListener"); | ||
| expectLastCall().andReturn(mock(Counter.class)); | ||
|
|
||
| replayAll(); | ||
| rabbitListener.handle("hello"); | ||
| verifyAll(); | ||
| } |
| rabbitListener.handle(() -> | ||
| { | ||
| return "hello"; | ||
| }); | ||
| verifyAll(); | ||
| } |
| when(meterRegistry.counter("rabbit.listener.event", "listener", "ImplementedCountingListener")).thenReturn(mock(Counter.class)); | ||
| when(meterRegistry.counter("rabbit.listener.event.total.duration.milliseconds", "listener", "ImplementedCountingListener")).thenReturn(mock(Counter.class)); | ||
|
|
||
| meterRegistry.counter("rabbit.listener.event.total.duration.milliseconds", "listener", "ImplementedCountingListener"); | ||
| expectLastCall().andReturn(mock(Counter.class)); | ||
|
|
||
| replayAll(); | ||
| rabbitListener.handle("hello", null); | ||
| verifyAll(); | ||
| } |
| rabbitListener.handle(() -> | ||
| { | ||
| return "hello"; | ||
| }, MessagePropertiesBuilder.newInstance().build()); | ||
| verifyAll(); | ||
| } |
| when(meterRegistry.counter("rabbit.listener.event", "listener", "ImplementedCountingListener")).thenReturn(mock(Counter.class)); | ||
| when(meterRegistry.counter("rabbit.listener.event.total.duration.milliseconds", "listener", "ImplementedCountingListener")).thenReturn(mock(Counter.class)); | ||
|
|
||
| replayAll(); | ||
| rabbitListener.handle(() -> | ||
| { |
| when(meterRegistry.counter("rabbit.listener.event", tags)).thenReturn(mock(Counter.class)); | ||
| when(meterRegistry.counter("rabbit.listener.event.total.duration.milliseconds", tags)).thenReturn(mock(Counter.class)); | ||
|
|
| when(meterRegistry.counter("rabbit.listener.event", tags)).thenReturn(mock(Counter.class)); | ||
| when(meterRegistry.counter("rabbit.listener.event.total.duration.milliseconds", tags)).thenReturn(mock(Counter.class)); | ||
|
|
||
| replayAll(); | ||
| rabbitListener.handle("hello", new MessageProperties()); | ||
| verifyAll(); | ||
| } |
# Conflicts: # .github/workflows/nightly.yml # .github/workflows/release.yml # .github/workflows/review.yml # README.md # pom.xml # src/test/java/com/avides/spring/rabbit/configuration/creator/DlxQueueCreatorTest.java # src/test/java/com/avides/spring/rabbit/configuration/creator/QueueCreatorTest.java
Failsafe had no jacoco-agent.destfile/append system properties, so integration-test coverage never accumulated. Worse, default-restore-instrumented-classes runs at its default phase (prepare-package) on every full lifecycle walk, undoing instrumentation before integration-test even runs. Added a re-instrument/restore pair bound to pre-integration-test/post-integration-test so Failsafe runs against instrumented classes again, while the packaged jar (built at package, before these fire) stays uninstrumented as before. Removed the default-report/integration-test-report/merge-results executions (dead ends - none were ever populated correctly) now that UT and Failsafe write into the same target/jacoco.exec directly. Added an explicit sonar.coverage.jacoco.xmlReportPaths property instead of relying on scanner-default path guessing. Same fix already verified and released in avides-application-parent 6.0.0-RC8. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HUDXZWmysRYmvLp1HRrj87
Needed to actually trigger a release of the previous JaCoCo fix commit - this repo's release.yml only ran on push to master. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HUDXZWmysRYmvLp1HRrj87
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HUDXZWmysRYmvLp1HRrj87
There is no more merge step (UT and Failsafe write into the same target/jacoco.exec directly via jacoco-agent.append), so the old name was misleading. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HUDXZWmysRYmvLp1HRrj87
|


No description provided.