Search code examples
spring-bootapache-camelspring-annotations

@Profile Spring Annotation in Camel


I have a Spring Boot + Apache Camel project that works brilliantly. I just added a new bean though where I wanted to have its implementation be profile-specific. I created Spring tests to verify it, and it works as expected, but when I run the server I get the following stack trace:

Caused by: org.apache.camel.NoSuchBeanException: No bean could be found in the registry for: MyFancyBean
    at org.apache.camel.component.bean.RegistryBean.getBean(RegistryBean.java:94)
    at org.apache.camel.model.language.MethodCallExpression.createExpression(MethodCallExpression.java:196)
    at org.apache.camel.model.language.MethodCallExpression.createPredicate(MethodCallExpression.java:210)
    at org.apache.camel.model.language.ExpressionDefinition.createPredicate(ExpressionDefinition.java:148)
    at org.apache.camel.model.ValidateDefinition.createProcessor(ValidateDefinition.java:63)
    at org.apache.camel.model.ValidateDefinition.createProcessor(ValidateDefinition.java:35)
    at org.apache.camel.model.ProcessorDefinition.makeProcessorImpl(ProcessorDefinition.java:545)
    at org.apache.camel.model.ProcessorDefinition.makeProcessor(ProcessorDefinition.java:506)
    at org.apache.camel.model.ProcessorDefinition.addRoutes(ProcessorDefinition.java:222)
    at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:1068)

I have an interface and two implementations:

public interface MyFancyBean { ... }

public class FooFancyBean implements MyFancyBean { ... }

public class NonFooFancyBean implements MyFancyBean { ... }

Depending on profile, the correct bean is read instantiated:

@Configuration
public class AppConfig {
    @Bean
    @Profile("foo")
    MyFancyBean fooBean() {
        return new FooFancyBean();
    }

    @Bean
    @Profile("!foo")
    MyFancyBean nonFooBean() {
        return new NonFooFancyBean();
    }
}

I've verified this works a couple of ways. First, a couple tests:

@ActiveProfiles("anything-but-foo")
@RunWith(SpringJUnit4ClassRunner.class)
@ComponentScan(basePackages = {"com.example", "com.jtv.spring.boot"})
@EnableAutoConfiguration
@Component
public class NonFooBean_SpringTest {

    @Autowired
    private MyFancyBean bean;

    @Test
    // ... here "bean" is instantiated as "NonFooFancyBean"

So the test works.

Further, when I start my app, depending on profile the correct bean in my @Configuration class above is called.

But Camel is still angry and says "NoSuchBeanException" on startup.

FWIW, here's how I'm referencing the bean:

@Component
public class MyCamelRoute extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        // [...]
        from("direct:processStuff").
        validate().method("MyFancyBean").
        process("MyProcessor");
    }


}

How do I get Camel to honor this config?


Solution

  • Whoooo... Y'all get to be my rubber duck today. I just autowired it. (This doesn't work for my processor, which is why it didn't occur to me initially.)

    @Component
    public class MyCamelRoute extends RouteBuilder {
        @Override
        public void configure() throws Exception {
            // [...]
            @Autowired MyFancyBean myFancyBean;
    
            from("direct:processStuff").
            validate().method(myFancyBean).
            process("MyProcessor");
        }
    }