Skip to content

LIBRARIES-1670 - update to springboot3 and java21/migration to junit5/mockito#20

Open
julian-eggers wants to merge 44 commits into
masterfrom
spring-boot-3-migration
Open

LIBRARIES-1670 - update to springboot3 and java21/migration to junit5/mockito#20
julian-eggers wants to merge 44 commits into
masterfrom
spring-boot-3-migration

Conversation

@julian-eggers

Copy link
Copy Markdown
Member

No description provided.

julian-eggers and others added 18 commits July 8, 2026 23:02
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
Copilot AI review requested due to automatic review settings July 15, 2026 11:26
@github-actions

Copy link
Copy Markdown
  • Documentation added or updated?

    • Diff-Links as response added?
      • Not necessary
      • Added
  • Breaking-Change present?

    • Necessary deployment adjustments added as a comment (Ticket)?
      • Not necessary
      • Added
    • Necessary rollback adjustments added as a comment (Ticket)?
      • Not necessary
      • Added

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.* to jakarta.validation.*, and adapt Rabbit/Spring Boot 3 API changes (e.g., Rabbit addresses now as List<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.

Comment thread src/test/java/com/avides/spring/rabbit/test/support/AbstractIT.java
julian-eggers and others added 2 commits July 15, 2026 13:54
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>
Copilot AI review requested due to automatic review settings July 15, 2026 12:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 70 out of 70 changed files in this pull request and generated 11 comments.

Comment on lines 83 to 93
@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)
{
Comment on lines 119 to 129
@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)
{
Comment on lines 136 to 142
{
try
{
replayAll();
resolveConnectionFactory(null, null, applicationContext);
verifyAll();
}
catch (IllegalArgumentException e)
{
Comment on lines 214 to 225
@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)
{
Comment on lines 252 to 263
@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)
{
Comment on lines +139 to +140
verify(rabbitAdmin).declareQueue(any(Queue.class));
verify(rabbitAdmin).declareExchange(exchange);
Comment on lines 146 to 152
try
{
replayAll();
QueueProperties completeQueueProperties = getCompleteQueueProperties();
completeQueueProperties.setRoutingkey("");
creator = new QueueCreator(completeQueueProperties, rabbitAdmin, exchange);
creator.createInstance();
verifyAll();
}
Comment on lines 162 to 169
try
{
replayAll();
QueueProperties completeQueueProperties = getCompleteQueueProperties();
completeQueueProperties.setRoutingkey(null);
completeQueueProperties.setRoutingkeys(Arrays.asList(""));
creator = new QueueCreator(completeQueueProperties, rabbitAdmin, exchange);
creator.createInstance();
verifyAll();
}
Comment on lines 60 to 64
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.
Copilot AI review requested due to automatic review settings July 15, 2026 18:35

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 70 out of 70 changed files in this pull request and generated 3 comments.

}

@Test
public void testResolveAdditionalMessagePostProcessorsWithCountingOutboundisDisabled()
Comment on lines 62 to 64
creator = new ListenerCreator(connectionFactory, "testQueueName", 50, 2, messageConverter, Integer.valueOf(12));
creator.createInstance();
verifyAll();
}
Comment on lines 88 to 91
try
{
replayAll();
resolveConnectionFactory(getCompleteBeanReferenceConnectionFactoryProperties(), null, applicationContext);
verifyAll();
}
Copilot AI review requested due to automatic review settings July 16, 2026 18:14
Comment thread .github/workflows/nightly.yml Fixed
Comment thread .github/workflows/nightly.yml Fixed
Comment thread .github/workflows/release.yml Fixed
Comment thread .github/workflows/release.yml Fixed
Comment thread .github/workflows/review.yml Fixed
Comment thread .github/workflows/review.yml Fixed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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());

Comment on lines 24 to 30
@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");
Comment on lines 27 to 36
@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);
Comment on lines 49 to 63
@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));
}
Comment on lines 90 to 105
@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.
Copilot AI review requested due to automatic review settings July 16, 2026 20:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 70 out of 70 changed files in this pull request and generated 2 comments.

Comment thread README.md Outdated
<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.
Copilot AI review requested due to automatic review settings July 16, 2026 21:12

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 70 out of 70 changed files in this pull request and generated 9 comments.

Comment on lines +39 to +42
private static List<String> splitAddresses(String addresses)
{
return Arrays.asList(StringUtils.commaDelimitedListToStringArray(addresses));
}
Comment on lines +139 to 141
verify(rabbitAdmin).declareQueue(any(Queue.class));
verify(rabbitAdmin).declareExchange(exchange);
}
Comment on lines +27 to 31
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();
}
Comment on lines 39 to 43
rabbitListener.handle(() ->
{
return "hello";
});
verifyAll();
}
Comment on lines +29 to 33
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();
}
Comment on lines 41 to 45
rabbitListener.handle(() ->
{
return "hello";
}, MessagePropertiesBuilder.newInstance().build());
verifyAll();
}
Comment on lines +50 to 54
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(() ->
{
Comment on lines +31 to 33
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));

Comment on lines +43 to 47
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
Copilot AI review requested due to automatic review settings July 17, 2026 06:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 70 out of 70 changed files in this pull request and generated no new comments.

sdaus and others added 9 commits July 17, 2026 10:31
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
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
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
63.2% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

5 participants