[ 
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)

Reply via email to