You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Claus Ibsen (Jira)" <ji...@apache.org> on 2026/07/15 15:12:00 UTC

[jira] [Resolved] (CAMEL-24070) camel-spring-rabbitmq - SpringRabbitMQProducer lazy template creation is not thread-safe and can leak started AsyncRabbitTemplates

     [ https://issues.apache.org/jira/browse/CAMEL-24070?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Claus Ibsen resolved CAMEL-24070.
---------------------------------
    Resolution: Fixed

> camel-spring-rabbitmq - SpringRabbitMQProducer lazy template creation is not thread-safe and can leak started AsyncRabbitTemplates
> ----------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-24070
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24070
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-spring-rabbitmq
>    Affects Versions: 4.22.0
>            Reporter: Federico Mariani
>            Assignee: Claus Ibsen
>            Priority: Major
>             Fix For: 4.22.0
>
>         Attachments: SpringRabbitMQProducerTemplateRaceTest.java
>
>
> {{SpringRabbitMQProducer}} lazily creates its templates without synchronization:
> {code:java}
> public RabbitTemplate getInOnlyTemplate() {
>     if (inOnlyTemplate == null) {
>         inOnlyTemplate = getEndpoint().createInOnlyTemplate();
>     }
>     return inOnlyTemplate;
> }
> public AsyncRabbitTemplate getInOutTemplate() {
>     if (inOutTemplate == null) {
>         inOutTemplate = getEndpoint().createInOutTemplate();
>     }
>     inOutTemplate.start();
>     return inOutTemplate;
> }
> {code}
> A producer is a singleton that is invoked concurrently by route threads, so concurrent first messages can each create their own template; all but the last assignment are dropped without being stopped. In the InOut case each racing thread also *starts* its template, so the losers are leaked in started state. {{EndpointMessageListener.getTemplate()}} in the same component guards the identical lazy-init pattern with a {{ReentrantLock}} - the producer should do the same.
> Two related nits in the same methods:
> * {{getInOutTemplate()}} calls {{start()}} on every message instead of only when the template is created (or better: in {{doStart()}}).
> * {{processInOnly}} compares {{Boolean.FALSE == sent}} on a primitive boolean.
> Attached reproducer (no broker needed) calls {{getInOnlyTemplate()}} from 8 threads behind a barrier and fails immediately on current main:
> {noformat}
> concurrent getInOnlyTemplate() must always return the same template (round 0) ==> expected: <1> but was: <8>
> {noformat}
> ----
> _This issue was found during an AI-assisted code review of camel-spring-rabbitmq: Claude Code on behalf of Federico Mariani (fmariani). A failing unit test reproducing the issue is attached._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)