Skip to content

spring-rabbit: Update auf Spring Boot 4.1.X und Java 25 - #21

Open
julian-eggers wants to merge 8 commits into
masterfrom
spring-boot-4-migration
Open

spring-rabbit: Update auf Spring Boot 4.1.X und Java 25#21
julian-eggers wants to merge 8 commits into
masterfrom
spring-boot-4-migration

Conversation

@julian-eggers

Copy link
Copy Markdown
Member

Hebt spring-rabbit auf Spring Boot 4.1.0 und Java 25. Zielversion 5.0.0-RC1.

  • com.rabbitmq:http-client 5 hat spring-web gegen httpclient5 getauscht. QueueMasterLocatorConnectionFactory faengt jetzt HttpClientException und wertet e.status() == 401 aus.
  • Dieser Zweig war ungetestet und ist jetzt durch zwei ITs abgedeckt: 401 ueber falsches Passwort, und eine nicht erreichbare Management-API darf nicht als Rechteproblem gemeldet werden.
  • RabbitMQ 4 hat transient_nonexcl_queues entfernt. Transiente exklusive Queues bleiben zulaessig, daher bleibt durable=false bei queueManagementWithOneConnectionFactory.
  • @Valid wandert ins Typargument (Hibernate Validator 9, HV000271).

Merge-Reihenfolge

Die CI dieses PRs bleibt so lange rot, bis die folgenden Libraries gemergt und released sind - ihre RC-Artefakte liegen bisher nur lokal:

  • spring-xom-unmarshaller
  • springtainer-rabbitmq

Ticket: https://avides.atlassian.net/browse/LIBRARIES-1753
Epic: https://avides.atlassian.net/browse/ITGS-470

julian-eggers and others added 5 commits July 31, 2026 15:47
Raise spring-boot.version 3.5.16 -> 4.1.0, java.version 21 -> 25,
spring-xom-unmarshaller to 3.0.0-RC1 and springtainer-rabbitmq to
3.0.0-RC1.

Add <proc>full</proc> to maven-compiler-plugin: Lombok and
spring-boot-configuration-processor are picked up from the classpath and
need annotation processing enabled explicitly.

Move SpringRabbitJsonMessageConverter onto JacksonJsonMessageConverter and
Jackson 3. The inherited mapper is a tools.jackson ObjectMapper and
readValue now throws the unchecked JacksonException, so the IOException
catch had become unreachable.

Jackson 3 sorts properties alphabetically where Jackson 2 used declaration
order, so the expected JSON in the converter test was reordered. The
payload is unchanged; only the key order differs.

RabbitProperties and RabbitAutoConfiguration moved from
org.springframework.boot.autoconfigure.amqp to
org.springframework.boot.amqp.autoconfigure.

HttpClientErrorException.getRawStatusCode() is gone in Spring 7; use
getStatusCode().value().
DefaultMessageListenerContainer now translates MessageConversionException
from the listener-side conversion into AmqpRejectAndDontRequeueException.

SimpleMessageListenerContainer consults its own FatalExceptionStrategy in
the consumer loop and treats MessageConversionException as fatal, throwing
FatalListenerExecutionException("Invalid listener") and shutting the
consumer down. A single unconvertible message would therefore take the
whole listener offline. That strategy is a protected final field with no
setter, so it cannot be replaced.

AmqpRejectAndDontRequeueException is not on the fatal list: the consumer
stays up and the message is routed to the dead-letter exchange via the
defaultRequeueRejected=false this container already sets.

Also convert SpringRabbitAutoConfiguration to constructor injection, with
the two optional dependencies marked @nullable. The two listener base
classes keep field injection: they are extended by 212 subclasses across 56
repositories and exactly one of them reads meterRegistry, so a constructor
parameter would be threaded through everywhere for nothing.
Version 5 dropped its spring-web dependency in favour of httpclient5, so
Client.getQueue no longer signals a failed request through Spring's
HttpClientErrorException. Catch com.rabbitmq.http.client.HttpClientException
instead and read the code through status(), otherwise the hint about the
missing monitoring role would never be logged again.

Stop declaring queue.one as transient: RabbitMQ 4 refuses a non-durable,
non-exclusive queue with "Feature `transient_nonexcl_queues` is deprecated"
and the context fails to start. Nothing asserts on the flag, and durable is
the default anyway.

Also update maven-scm-provider-gitexe to 2.2.1.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DK51mDYaArzg9zFLftpsd
Both branches of the failed-request handling were reachable only against a
broker that answers on its management port, which the springtainer now
provides. One test drives a 401 with a wrong password and expects the hint
about the missing monitoring role, the other points at a port without a
management API and expects the generic message instead, so the two cases
cannot silently collapse into one.

Declare queue.one as transient again in the queue-management profile: it is
exclusive there, and RabbitMQ 4 only rejects transient queues that are not.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DK51mDYaArzg9zFLftpsd
Hibernate Validator 9 deprecates @Valid on a container and reports
HV000271 for every queues, outbounds and connections entry on startup.
Moving the annotation onto the type argument keeps the same cascade
without the warning.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DK51mDYaArzg9zFLftpsd
Copilot AI review requested due to automatic review settings August 2, 2026 08:22
The README shows the coordinates consumers copy, and the build checks
them against the pom.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DK51mDYaArzg9zFLftpsd
@github-actions

github-actions Bot commented Aug 2, 2026

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

Updates spring-rabbit to the Spring Boot 4.1 / Java 25 baseline (targeting 5.0.0-RC1) and adapts integration points impacted by RabbitMQ 4 and the RabbitMQ HTTP client 5, including additional integration tests for the management-API behavior.

Changes:

  • Upgrade project baseline: Spring Boot 4.1.0, Java 25, and dependency updates for the RabbitMQ HTTP client + related libraries.
  • Adapt runtime behavior for message conversion failures (reject instead of letting conversion exceptions take the consumer down).
  • Add/adjust tests and configuration for RabbitMQ 4 queue durability rules and management-API error handling (401 vs unreachable).

Reviewed changes

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

Show a summary per file
File Description
src/test/resources/application-multipleConnectionFactories.properties Removes transient non-exclusive queue config and documents RabbitMQ 4 behavior.
src/test/java/com/avides/spring/rabbit/utils/DomainTestSupport.java Updates Spring Boot 4 package imports; adapts to new SpringRabbitAutoConfiguration constructor.
src/test/java/com/avides/spring/rabbit/utils/BeanValidationTestSupportTest.java Moves @Valid to type-use for HV 9 compatibility.
src/test/java/com/avides/spring/rabbit/converter/SpringRabbitJsonMessageConverterTest.java Switches test customization to JsonMapper and renames tests accordingly.
src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationWithoutConnectionsIT.java Updates Spring Boot 4 RabbitAutoConfiguration import.
src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationTest.java Centralizes construction for the new auto-config constructor and updates instantiation sites.
src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationForMultipleConnectionFactoriesWithSameListenerMultipleUsedIT.java Updates Spring Boot 4 RabbitAutoConfiguration import.
src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationForMultipleConnectionFactoriesIT.java Updates Spring Boot 4 RabbitAutoConfiguration import.
src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationForDifferentPrefetchCountIT.java Updates Spring Boot 4 RabbitAutoConfiguration import.
src/test/java/com/avides/spring/rabbit/configuration/provider/ConnectionFactoryProviderTest.java Updates Spring Boot 4 RabbitProperties import.
src/test/java/com/avides/spring/rabbit/configuration/domain/QueueMasterLocatorConnectionFactoryIT.java Adds new ITs covering 401 vs unreachable management-API behavior.
src/test/java/com/avides/spring/rabbit/configuration/creator/CustomConnectionFactoryCreatorTest.java Updates Spring Boot 4 RabbitProperties import.
src/main/java/com/avides/spring/rabbit/listener/container/DefaultMessageListenerContainer.java Wraps conversion failures as reject/no-requeue to prevent consumers being taken offline by bad messages.
src/main/java/com/avides/spring/rabbit/converter/SpringRabbitJsonMessageConverter.java Migrates to Spring AMQP’s Jackson 3 converter base and adapts exception handling.
src/main/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfiguration.java Refactors to constructor injection; updates @Valid annotations to type-use; updates Spring Boot 4 Rabbit properties import.
src/main/java/com/avides/spring/rabbit/configuration/provider/ConnectionFactoryProvider.java Updates Spring Boot 4 RabbitProperties import.
src/main/java/com/avides/spring/rabbit/configuration/domain/QueueMasterLocatorConnectionFactory.java Updates HTTP client exception handling to RabbitMQ http-client 5 APIs (HttpClientException).
src/main/java/com/avides/spring/rabbit/configuration/creator/CustomConnectionFactoryCreator.java Updates Spring Boot 4 RabbitProperties import.
pom.xml Bumps project/version baseline (5.0.0-RC1), upgrades Java/Spring Boot/http-client versions, adds Jackson dependency, and updates compiler config.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 58 to 59
throw new MessageConversionException("Could not convert incoming message with class [" + clazz + "] and body [" + new String(message
.getBody()) + "]", e);
Comment on lines +56 to +58
logger.detachAppender(logAppender);
defaultConnectionFactory.destroy();
}
Copilot AI review requested due to automatic review settings August 2, 2026 08:30

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 20 out of 21 changed files in this pull request and generated 1 comment.

Suppressed comments (4)

src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationTest.java:359

  • This test creates a SpringRabbitAutoConfiguration instance with meterRegistry set to null. While afterPropertiesSet() may not currently hit the meterRegistry path for this setup, keeping required constructor dependencies non-null makes the test setup more realistic and prevents future NPEs if template/post-processor configuration changes.
        SpringRabbitAutoConfiguration autoConfiguration = new SpringRabbitAutoConfiguration(connectionFactory, getCompleteRabbitProperties(), null,
                applicationContext, List.of(new SimpleMessageConverter()), List.of());

pom.xml:94

  • The new explicit tools.jackson.core:jackson-databind dependency is the key change that compensates for com.rabbitmq:http-client no longer bringing Spring Web/Jackson transitively. The existing comment further down references http-client 4.x and an old transitive Jackson, which is now misleading. Consider moving/updating the explanation right next to the explicit Jackson dependency (and removing the outdated wording).
    <dependency>
      <groupId>tools.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
    </dependency>

src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationTest.java:42

  • SpringRabbitAutoConfiguration now requires several constructor arguments; these tests currently pass null for required dependencies (MeterRegistry, GenericApplicationContext). Even if the current assertions don’t trigger those code paths, constructing the SUT in an invalid state makes the tests brittle and can hide NPEs introduced later. Prefer supplying simple concrete instances here.

This issue also appears on line 358 of the same file.

    private static SpringRabbitAutoConfiguration newAutoConfiguration()
    {
        return new SpringRabbitAutoConfiguration(null, null, null, null, List.of(), List.of());
    }

src/test/java/com/avides/spring/rabbit/utils/DomainTestSupport.java:53

  • getCompleteSpringRabbitAutoConfiguration() now instantiates SpringRabbitAutoConfiguration with null for required constructor dependencies (MeterRegistry, GenericApplicationContext). This makes the shared test fixture fragile if any test later calls afterPropertiesSet() or any method that touches those collaborators. Prefer providing simple concrete instances (or mocks) to keep the fixture valid.
        SpringRabbitAutoConfiguration springRabbitAutoConfiguration = new SpringRabbitAutoConfiguration(null, null, null, null, List.of(), List.of());

import jakarta.validation.constraints.NotNull;

import org.hibernate.validator.constraints.Range;
import org.jspecify.annotations.Nullable;
The workflow only listens on master. This is reverted by the review-side
autoupdate once the release has gone through.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DK51mDYaArzg9zFLftpsd
Copilot AI review requested due to automatic review settings August 2, 2026 10:36
@sonarqubecloud

sonarqubecloud Bot commented Aug 2, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

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

See analysis details on SonarQube Cloud

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 20 out of 21 changed files in this pull request and generated no new comments.

Suppressed comments (4)

src/test/java/com/avides/spring/rabbit/converter/SpringRabbitJsonMessageConverterTest.java:46

  • The test compares the full Message instance (including the raw JSON byte payload). This is brittle because JSON object field ordering is not guaranteed and can change with mapper upgrades/configuration, causing false-negative test failures. Prefer comparing the JSON structurally (e.g., JsonNode) and assert message properties separately.
    void testToMessageWithDefaultJsonMapper()
    {
        Message message = MESSAGE_CONVERTER_DEFAULT_MESSAGE_CONVERTER.toMessage(TestClass.buildBase(), new MessageProperties());

        assertThat(message).isEqualTo(MESSAGE);

src/test/java/com/avides/spring/rabbit/configuration/domain/QueueMasterLocatorConnectionFactoryIT.java:58

  • ListAppender is started in setUp() but never stopped. Detaching alone leaves the appender running and can leak resources across tests (especially when running suites in parallel). Stop the appender in tearDown().
    @AfterEach
    void tearDown()
    {
        logger.detachAppender(logAppender);
        defaultConnectionFactory.destroy();
    }

src/test/java/com/avides/spring/rabbit/utils/DomainTestSupport.java:53

  • SpringRabbitAutoConfiguration now has required constructor parameters (MeterRegistry, GenericApplicationContext, converter/post-processor lists). Passing null here makes the test support object violate the class contract and can lead to NPEs if later tests start exercising initialization logic. Use lightweight real instances for these required dependencies instead of null.
        SpringRabbitAutoConfiguration springRabbitAutoConfiguration = new SpringRabbitAutoConfiguration(null, null, null, null, List.of(), List.of());

src/test/java/com/avides/spring/rabbit/configuration/SpringRabbitAutoConfigurationTest.java:42

  • newAutoConfiguration() builds SpringRabbitAutoConfiguration with null for required constructor args (MeterRegistry, GenericApplicationContext, etc.). This can hide real wiring problems and risks NPEs if any test starts exercising behavior beyond simple getters. Prefer creating minimal real instances for required dependencies.
    private static SpringRabbitAutoConfiguration newAutoConfiguration()
    {
        return new SpringRabbitAutoConfiguration(null, null, null, null, List.of(), List.of());
    }

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.

3 participants