Hello all,

In my Camel app, I recently integrated Spring Boot to use its external 
configuration feature. Basically, I can put default properties in an 
src/main/resources/application.properties file. Then I can override them on 
different servers using various mechanisms, from using a 
config/application.properties on the classpath to using environment variables. 
It's really slick in that you can have a single WAR that can be configured for 
dev, test, staging and prod.

To read these properties in my Camel routes, I'm using the following 
setupCamelContext() method to read this file in. Problem is, it doesn't hook 
into Spring Boot's external override mechanism. Is there anyway to make Camel 
aware of Spring Boot's override feature?

@Configuration
@ImportResource("classpath:META-INF/cxf/cxf.xml")
@ComponentScan("com.company.app")
public class CamelConfig extends CamelConfiguration {
        @Value("${logging.trace.enabled}")
        private Boolean tracingEnabled;

        @Override
        protected void setupCamelContext(CamelContext camelContext) throws 
Exception {
                PropertiesComponent pc = new PropertiesComponent();
                pc.setLocation("classpath:application.properties");
                camelContext.addComponent("properties", pc);
                // see if trace logging is turned on
                if (tracingEnabled) {
                        camelContext.setTracing(true);
                }
                super.setupCamelContext(camelContext);
        }

        @Bean
        public Tracer camelTracer() {
                Tracer tracer = new Tracer();
                tracer.setTraceExceptions(false);
                tracer.setTraceInterceptors(true);
                tracer.setLogName("com.company.app.trace");
                return tracer;
        }
}

If not, I'm able to workaround this issue by changing the properties from being 
inlined to being separate Strings. For example, here's an onException handler 
that doesn't pick up overridden properties:

public abstract class AbstractRouteBuilder extends RouteBuilder {

        /**
         * Default exception handling for all routes.
         *
         * @throws Exception
         */
        @Override
        public void configure() throws Exception {
                onException(Exception.class)
                                .setHeader("routeId", 
property(Exchange.FAILURE_ROUTE_ID))
                                .setHeader("endpoint", 
property(Exchange.FAILURE_ENDPOINT))
                                .setHeader("exception", 
property(Exchange.EXCEPTION_CAUGHT))
                                .setHeader("subject", simple("Message Broker 
Error ({{esb.env}}) - ${exception.class.simpleName}"))
                                
.transform(simple("${exception.message}\n\nStacktrace 
Details:\n\n${exception.stacktrace}"))
                                .to("freemarker:/templates/mail/error.ftl")
                                
.to("smtp://{{mail.host}}?contentType=text/plain&to={{esb.alert.email}}" +
                                                
"&from={{mail.from}}&subject=${headers.subject})");
        }
}

If I change it to the following, things work as expected:

public abstract class AbstractRouteBuilder extends RouteBuilder {

        @Value("${esb.env}")
        private String esbEnv;

        @Value("${esb.alert.email}")
        private String esbAlertEmail;

        /**
         * Default exception handling for all routes.
         *
         * @throws Exception
         */
        @Override
        public void configure() throws Exception {
                onException(Exception.class)
                                .setHeader("routeId", 
property(Exchange.FAILURE_ROUTE_ID))
                                .setHeader("endpoint", 
property(Exchange.FAILURE_ENDPOINT))
                                .setHeader("exception", 
property(Exchange.EXCEPTION_CAUGHT))
                                .setHeader("subject", simple("Message Broker 
Error (" + esbEnv + ") - ${exception.class.simpleName}"))
                                
.transform(simple("${exception.message}\n\nStacktrace 
Details:\n\n${exception.stacktrace}"))
                                .to("freemarker:/templates/mail/error.ftl")
                                
.to("smtp://{{mail.host}}?contentType=text/plain&to=" + esbAlertEmail +
                                                
"&from={{mail.from}}&subject=${headers.subject})");
        }
}

However, I'd rather not have to do this for each route. 

Please let me know if it's possible to make Camel aware of Spring Boot's 
external properties configuration.

Thanks,

Matt

Reply via email to