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 13:22:00 UTC
[jira] [Resolved] (CAMEL-24067) camel-spring - SpringInjector does not inject CamelContext into CamelContextAware beans created via factory method
[ https://issues.apache.org/jira/browse/CAMEL-24067?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Claus Ibsen resolved CAMEL-24067.
---------------------------------
Resolution: Fixed
> camel-spring - SpringInjector does not inject CamelContext into CamelContextAware beans created via factory method
> ------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-24067
> URL: https://issues.apache.org/jira/browse/CAMEL-24067
> Project: Camel
> Issue Type: Bug
> Components: camel-spring
> Affects Versions: 4.21.0
> Reporter: Federico Mariani
> Assignee: Claus Ibsen
> Priority: Major
> Fix For: 4.22.0
>
>
> Core {{DefaultInjector.newInstance(type, factoryClass, factoryMethod)}} calls {{CamelContextAware.trySetCamelContext(answer, camelContext)}} after invoking the factory method. {{SpringInjector}} (the injector used by every {{SpringCamelContext}}, i.e. all camel-spring / camel-spring-boot applications) has the same factory-method code but *without* the {{trySetCamelContext}} call.
> As a result, a {{CamelContextAware}} bean created through a factory method - e.g. the property-binding syntax {{#class:com.foo.MyBean#createMyBean}} on an endpoint/component option - gets the {{CamelContext}} injected on a plain {{CamelContext}} but *not* when running in Spring. Same route, different behavior depending on runtime.
> Two smaller defects in the same method could be fixed together:
> * when the factory method exists but is not {{public static}}, the method silently returns {{null}} instead of raising an error (same silent-null exists in core, but core at least documents the contract via the same code path)
> * the guard {{fm.getReturnType() != Void.class}} tests the boxed {{Void}} wrapper; a {{void}} factory method has return type {{void.class}} ({{Void.TYPE}}), so the check never excludes anything (this quirk is shared with {{DefaultInjector}} and could be fixed in both)
> Reproducer (verified on 4.22.0-SNAPSHOT: the {{DefaultCamelContext}} test passes, the {{SpringCamelContext}} test fails; dependencies: camel-core, camel-spring, junit-jupiter):
> {code:java}
> package org.apache.camel.spring.repro;
> import org.apache.camel.CamelContext;
> import org.apache.camel.CamelContextAware;
> import org.apache.camel.impl.DefaultCamelContext;
> import org.apache.camel.spring.SpringCamelContext;
> import org.junit.jupiter.api.Test;
> import org.springframework.context.annotation.AnnotationConfigApplicationContext;
> import static org.junit.jupiter.api.Assertions.assertNotNull;
> public class SpringInjectorFactoryMethodTest {
> @Test
> void factoryMethodBeanGetsCamelContextWithDefaultInjector() throws Exception {
> try (DefaultCamelContext camel = new DefaultCamelContext()) {
> camel.start();
> MyBean bean = camel.getInjector().newInstance(MyBean.class, "createMyBean");
> assertNotNull(bean);
> // passes: DefaultInjector calls CamelContextAware.trySetCamelContext
> assertNotNull(bean.getCamelContext());
> }
> }
> @Test
> void factoryMethodBeanGetsCamelContextWithSpringInjector() throws Exception {
> try (AnnotationConfigApplicationContext appCtx = new AnnotationConfigApplicationContext()) {
> appCtx.refresh();
> SpringCamelContext camel = new SpringCamelContext(appCtx);
> camel.start();
> try {
> MyBean bean = camel.getInjector().newInstance(MyBean.class, "createMyBean");
> assertNotNull(bean);
> // EXPECTED: same behavior as DefaultInjector
> // ACTUAL: fails, SpringInjector skips CamelContextAware injection
> assertNotNull(bean.getCamelContext());
> } finally {
> camel.stop();
> }
> }
> }
> public static class MyBean implements CamelContextAware {
> private CamelContext camelContext;
> public static MyBean createMyBean() {
> return new MyBean();
> }
> @Override
> public CamelContext getCamelContext() {
> return camelContext;
> }
> @Override
> public void setCamelContext(CamelContext camelContext) {
> this.camelContext = camelContext;
> }
> }
> }
> {code}
> Suggested fix: mirror {{DefaultInjector}} - after {{answer = type.cast(obj);}} add {{CamelContextAware.trySetCamelContext(answer, camelContext)}}. {{SpringInjector}} currently has no {{CamelContext}} reference, but it is always created from {{SpringCamelContext.createInjector()}}, which can pass {{this}} (or the {{ApplicationContext}} lookup can be used).
> _This issue was found during an AI-assisted code review of the camel-spring component. Reported by Claude Code on behalf of Federico Mariani. The reproducers were executed and verified against 4.22.0-SNAPSHOT (main) before filing._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)