Spring Boot

Spring Boot component provides auto-configuration for Apache Camel. Our opinionated auto-configuration of the Camel context auto-detects Camel routes available in the Spring context and registers the key Camel utilities (like producer template, consumer template and the type converter) as beans.

Maven users will need to add the following dependency to their pom.xml in order to use this component:

<dependency>
    <groupId>org.apache.camel.springboot</groupId>
    <artifactId>camel-spring-boot</artifactId>
    <version>${camel.version}</version> <!-- use the same version as your Camel core version -->
</dependency>

camel-spring-boot jar comes with the org.springframework.boot.autoconfigure.AutoConfiguration.imports file, so as soon as you add that dependency into your classpath, Spring Boot will automatically auto-configure Camel for you.

Camel Spring Boot Starter

Apache Camel ships a Spring Boot Starter module that allows you to develop Spring Boot applications using starters. There is a sample application in the source code also.

To use the starter, add the following to your spring boot pom.xml file:

<dependency>
    <groupId>org.apache.camel.springboot</groupId>
    <artifactId>camel-spring-boot-starter</artifactId>
    <version>${camel.version}</version> <!-- use the same version as your Camel core version -->
</dependency>

Then you can just add classes with your Camel routes such as:

package com.example;

import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;

@Component
public class MyRoute extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        from("timer:foo").to("log:bar");
    }
}

Then these routes will be started automatically.

You can customize the Camel application in the application.properties or application.yml file.

Spring Boot Auto-Configuration

The Spring Boot auto-configuration options are documented in the Core starter page.

Auto-configured Camel context

The most important piece of functionality provided by the Camel auto-configuration is CamelContext instance. Camel auto-configuration creates a SpringCamelContext for you and takes care of the proper initialization and shutdown of that context. The created Camel context is also registered in the Spring application context (under camelContext bean name), so you can access it just as any other Spring bean.

@Configuration
public class MyAppConfig {

  @Autowired
  CamelContext camelContext;

  @Bean
  MyService myService() {
    return new DefaultMyService(camelContext);
  }

}

Auto-detecting Camel routes

Camel auto-configuration collects all the RouteBuilder instances from the Spring context and automatically injects them into the provided CamelContext. That means that creating new Camel routes with the Spring Boot starter is as simple as adding the @Component annotated class to your classpath:

@Component
public class MyRouter extends RouteBuilder {

  @Override
  public void configure() throws Exception {
    from("jms:invoices").to("file:/invoices");
  }

}

Or creating a new route RouteBuilder bean in your @Configuration class:

@Configuration
public class MyRouterConfiguration {

  @Bean
  RoutesBuilder myRouter() {
    return new RouteBuilder() {

      @Override
      public void configure() throws Exception {
        from("jms:invoices").to("file:/invoices");
      }

    };
  }

}

Camel properties

Spring Boot auto-configuration automatically connects to Spring Boot external configuration (like properties placeholders, OS environment variables or system properties) with the Camel properties support. It basically means that any property defined in application.properties file:

route.from = jms:invoices

Or set via system property:

java -Droute.to=jms:processed.invoices -jar mySpringApp.jar

…​can be used as placeholders in Camel route:

@Component
public class MyRouter extends RouteBuilder {

  @Override
  public void configure() throws Exception {
    from("{{route.from}}").to("{{route.to}}");
  }

}

Custom Camel context configuration

If you would like to perform some operations on CamelContext bean created by Camel auto-configuration, register CamelContextConfiguration instance in your Spring context:

@Configuration
public class MyAppConfig {

  @Bean
  CamelContextConfiguration contextConfiguration() {
    return new CamelContextConfiguration() {
      @Override
      void beforeApplicationStart(CamelContext context) {
        // your custom configuration goes here
      }
    };
  }

}

Method beforeApplicationStart will be called just before the Spring context is started, so the CamelContext instance passed to this callback is fully auto-configured. You can add many instances of CamelContextConfiguration into your Spring context - all of them will be executed.

Auto-configured consumer and producer templates

Camel auto-configuration provides pre-configured ConsumerTemplate and ProducerTemplate instances. You can simply inject them into your Spring-managed beans:

@Component
public class InvoiceProcessor {

  @Autowired
  private ProducerTemplate producerTemplate;

  @Autowired
  private ConsumerTemplate consumerTemplate;

  public void processNextInvoice() {
    Invoice invoice = consumerTemplate.receiveBody("jms:invoices", Invoice.class);
    ...
    producerTemplate.sendBody("netty-http:http://invoicing.com/received/" + invoice.id());
  }

}

By default, consumer templates and producer templates come with the endpoint cache sizes set to 1000. You can change those values via the following Spring properties:

camel.main.consumer-template-cache-size = 100
camel.main.producer-template-cache-size = 200

Auto-configured TypeConverter

Camel auto-configuration registers a TypeConverter instance named typeConverter in the Spring context.

@Component
public class InvoiceProcessor {

  @Autowired
  private TypeConverter typeConverter;

  public long parseInvoiceValue(Invoice invoice) {
    String invoiceValue = invoice.grossValue();
    return typeConverter.convertTo(Long.class, invoiceValue);
  }

}

Spring type conversion API bridge

Spring comes with the powerful type conversion API. Spring API happens to be very similar to the Camel type converter API. As those APIs are so similar, Camel Spring Boot automatically registers a bridge converter (SpringTypeConverter) that delegates to the Spring conversion API.That means that out-of-the-box Camel will treat Spring Converters like Camel ones. With this approach you can enjoy both Camel and Spring converters accessed via Camel TypeConverter API:

@Component
public class InvoiceProcessor {

  @Autowired
  private TypeConverter typeConverter;

  public UUID parseInvoiceId(Invoice invoice) {
    // Using Spring's StringToUUIDConverter
    UUID id = invoice.typeConverter.convertTo(UUID.class, invoice.getId());
  }

}

Under the hood Camel Spring Boot delegates conversion to the Spring’s ConversionService instances available in the application context. If no ConversionService instance is available, Camel Spring Boot auto-configuration will create one for you.

Keeping the application alive

Camel applications having this feature enabled launch a new thread on startup for the sole purpose of keeping the application alive by preventing JVM termination. It means that after you start a Camel application with Spring Boot, your application waits for a Ctrl+C signal and does not exit immediately.

The controller thread can be activated using the camel.main.run-controller to true.

camel.main.run-controller = true

Applications using web modules (e.g. importing the org.springframework.boot:spring-boot-web-starter module), usually don’t need to use this feature because the application is kept alive by the presence of other non-daemon threads.

Adding XML routes

By default, you can put Camel XML routes in the classpath under the directory camel, which camel-spring-boot will auto-detect and include. You can configure the directory name or turn this off using the configuration option

# turn off
camel.main.routes-include-pattern = false
# scan only in the com/foo/routes classpath
camel.main.routes-include-pattern = classpath:com/foo/routes/*.xml

The XML files should be Camel XML routes (not <CamelContext>) such as

<routes xmlns="http://camel.apache.org/schema/spring">
    <route id="test">
        <from uri="timer://trigger"/>
        <transform>
            <simple>ref:myBean</simple>
        </transform>
        <to uri="log:out"/>
    </route>
</routes>

Testing the JUnit 6 way

For testing, Maven users will need to add the following dependencies to their pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <version>${spring-boot.version}</version> <!-- Use the same version as your Spring Boot version -->
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-test-spring-junit6</artifactId>
    <version>${camel.version}</version> <!-- use the same version as your Camel core version -->
    <scope>test</scope>
</dependency>

To test a Camel Spring Boot application, annotate your test class(es) with @CamelSpringBootTest. This brings Camel’s Spring Test support to your application, so that you can write tests using Spring Boot test conventions.

To get the CamelContext or ProducerTemplate, you can inject them into the class in the normal Spring manner, using @Autowired.

You can also use camel-test-spring-junit6 to configure tests declaratively. This example uses the @MockEndpoints annotation to auto-mock an endpoint:

@CamelSpringBootTest
@SpringBootApplication
@MockEndpoints("direct:end")
public class MyApplicationTest {

    @Autowired
    private ProducerTemplate template;

    @EndpointInject("mock:direct:end")
    private MockEndpoint mock;

    @Test
    public void testReceive() throws Exception {
        mock.expectedBodiesReceived("Hello");
        template.sendBody("direct:start", "Hello");
        mock.assertIsSatisfied();
    }

}

Camel Spring Boot Native

One of the most interesting features added to Spring Boot 3 is the support of GraalVM Native Image which allows you to reduce significantly the memory footprint and the startup time of your application. Those improvements are only possible thanks to the Ahead-Of-Time (AOT) compilation that relies on a closed-world assumption which means that everything needs to be known at build type, all dynamic aspects included such as reflection, JNI, Proxy, and resources loading from a ClassLoader.

For now, only Camel routes written using the Java, XML, and/or YAML DSL with basic components that don’t rely on dynamic aspects to work are covered out of the box. For other components, you will need to provide GraalVM some hints to let it know all the dynamic aspects needed by your application either by implementing your custom RuntimeHintsRegistrar or by providing GraalVM JSON hint files that can be generated by the Tracing Agent.

For more details about GraalVM Native Image Support in Spring Boot please refer to https://docs.spring.io/spring-boot/docs/current/reference/html/native-image.html

Camel Asynchronous Health Checks

Camel health checks can be executed asynchronously via a Task Scheduler so that the result can be cached and the actual health check is executed in background every few seconds. Asynchronous Camel health checks are disabled by default but can be enabled with the following property:

camel.health.async-camel-health-check=true

moreover the Camel health check task scheduler can be customized with the following properties:

camel.health.healthCheckPoolSize=5
camel.health.healthCheckFrequency=10
camel.health.healthCheckThreadNamePrefix=CamelHealthTaskScheduler

Camel Readiness and Liveness State Indicators

Camel specific Readiness and Liveness checks can be added to a Spring Boot 3 application including respectively in the readiness and livenss groups camelLivenessStateHealthIndicator and camelReadinessStateHealthIndicator. In particular:

management.endpoint.health.group.liveness.include=livenessState,camelLivenessState
management.endpoint.health.group.readiness.include=readinessState,camelReadinessState

Using Camel specific readiness and liveness health indicators, the probes will be augmented with camel components health checks that support this feature. In enable the probes locally, they need to be enabled

management.endpoint.health.probes.enabled=true

Finally, http://localhost:8080/actuator/health/liveness will show the updated probe.

Management Access Log Control

When running actuator endpoints on a separate management port, you can disable access logging for the management context while keeping access logs for the main application. This is useful to avoid cluttering access logs with health check requests.

This feature requires management.server.port to be different from the main application port.

Tomcat

server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.directory=logs
server.tomcat.basedir=./target
management.server.port=9090
management.server.accesslog.enabled=false

Result: Main app logs to ./target/logs/access_log.<date>.log, actuator has no access logs.

Undertow

server.undertow.accesslog.enabled=true
server.undertow.accesslog.dir=logs
management.server.port=9090
management.server.accesslog.enabled=false

Result: Main app logs to logs/access_log.log, actuator has no access logs.

Camel Logging to Control Management Access Log

This is valid only when using spring-boot-starter-undertow.

If you want to defer the http access log control to whatever camel logging mechanism, you have to set management.server.undertow.accesslog.use-camel-logging=true. Optionally you can set a message pattern with management.server.accesslog.pattern=combined.

Example:

management.server.undertow.accesslog.use-camel-logging=true
management.server.accesslog.pattern=combined

Security Policy

Camel Spring Boot automatically enforces security policies at startup, detecting insecure configuration such as disabled SSL verification, plain-text secrets, enabled Java deserialization, or development-only features.

The global policy controls how Camel reacts when insecure configuration is detected:

# allow  — no warnings, allow the configuration
# warn   — log a warning at startup (default)
# fail   — throw an exception and prevent startup
camel.security.policy=warn

Category Overrides

Each security category can override the global policy independently:

camel.security.policy=fail
camel.security.insecure-ssl-policy=warn
camel.security.insecure-serialization-policy=warn
camel.security.insecure-dev-policy=allow
camel.security.secret-policy=fail

To exclude specific properties from all checks, use allowed-properties:

camel.security.allowed-properties=camel.component.http.trustAllCertificates,camel.component.netty.allowJavaSerializedObject

Per-Environment Policies with Spring Profiles

Spring profiles allow you to enforce strict security in production while keeping a relaxed policy during development.

In application-prod.properties:

camel.security.policy=fail

In application-dev.properties:

camel.security.policy=allow

Activate the profile via spring.profiles.active:

# application.properties
spring.profiles.active=dev

Or at runtime:

java -Dspring.profiles.active=prod -jar myApp.jar

This way, developers can freely use options like trustAllCertificates=true locally, while production deployments will fail fast if any insecure configuration is detected.

Virtual Threads Support

Camel Spring Boot provides comprehensive support for JDK 21+ Virtual Threads, offering significant performance improvements for I/O-intensive applications. Virtual threads are lightweight threads that can dramatically reduce memory overhead and improve scalability compared to traditional platform threads.

Enabling Virtual Threads

To enable virtual threads in your Camel Spring Boot application, simply set the Spring Boot virtual threads property:

spring.threads.virtual.enabled=true

When this property is set to true, Camel Spring Boot automatically:

  1. Enables Camel Virtual Threads: Automatically sets camel.threads.virtual.enabled=true

  2. Optimizes Executors: Configures components to use SimpleAsyncTaskExecutor which is optimized for virtual threads

  3. Updates Component Configurations: Automatically configures supported components for optimal virtual thread performance

Automatic Configuration

When virtual threads are enabled, Camel Spring Boot provides automatic configuration for several components:

Platform HTTP Component

The Platform HTTP component automatically uses SimpleAsyncTaskExecutor when virtual threads are enabled, providing better performance for HTTP endpoints:

@Component
public class MyRoute extends RouteBuilder {
    @Override
    public void configure() {
        from("platform-http:/api/data")
            .to("http://external-service/api")  // Benefits from virtual threads
            .setBody(constant("Response processed"));
    }
}
Undertow Metrics

When using the Platform HTTP component with Undertow as the underlying web server, comprehensive metrics are automatically available through Spring Boot Actuator. To enable Undertow metrics:

  1. Exclude Tomcat from Spring Boot Web starter in your pom.xml:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
  2. Add Spring Boot Undertow starter:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-undertow</artifactId>
    </dependency>
  3. Include Spring Boot Actuator:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
  4. Expose actuator metrics and enable Undertow session statistics

    server.undertow.options.server.ENABLE_STATISTICS=true
    management.endpoints.web.exposure.include=metrics,health,info

With this configuration, Undertow-specific metrics will be automatically exposed under /actuator/metrics, providing detailed insights into HTTP server including: session management, connection pools and thread usage These metrics help monitor the health and performance of your Platform HTTP endpoints running on Undertow.

JMS and AMQP Components

JMS and AMQP components benefit from virtual threads through the global virtual thread configuration. When spring.threads.virtual.enabled=true is set, these components will use virtual threads for message processing through the standard Spring Boot virtual thread integration:

spring.threads.virtual.enabled=true
# JMS and AMQP components will automatically benefit from virtual threads

Manual Configuration

If you need to manually configure specific components for virtual threads, you can use the VirtualThreadAwareExecutorFactory:

@Configuration
public class VirtualThreadConfig {

    @Bean
    @ConditionalOnProperty(name = "spring.threads.virtual.enabled", havingValue = "true")
    public TaskExecutor customTaskExecutor() {
        return VirtualThreadAwareExecutorFactory.createOptimalExecutor();
    }
}

Performance Benefits

Virtual threads provide several performance advantages:

  • Reduced Memory Overhead: Virtual threads use significantly less memory than platform threads

  • Higher Concurrency: Support for millions of concurrent virtual threads

  • Better Resource Utilization: Reduced thread pool contention and context switching

  • Simplified Programming Model: No need for complex async/reactive programming patterns

Best Practices

When using virtual threads with Camel Spring Boot:

  1. Avoid Thread Pinning: Minimize use of synchronized blocks in route processing

  2. Use Simple Async Executors: Let Camel Spring Boot auto-configure optimal executors

  3. Monitor Performance: Use Spring Boot Actuator to monitor virtual thread usage

  4. Test Thoroughly: Validate behavior under load with virtual threads enabled

Example Application

Here’s a complete example of a Camel Spring Boot application optimized for virtual threads:

# application.properties
spring.threads.virtual.enabled=true
camel.main.routes-include-pattern=classpath:routes/*
@SpringBootApplication
public class VirtualThreadsApplication {

    public static void main(String[] args) {
        SpringApplication.run(VirtualThreadsApplication.class, args);
    }

    @Component
    public static class ApiRoutes extends RouteBuilder {
        @Override
        public void configure() {
            from("platform-http:/api/process")
                .log("Processing request with virtual thread: ${threadName}")
                .to("http://external-api/data")
                .transform(body().prepend("Processed: "))
                .setHeader("X-Thread-Type", constant("virtual"));
        }
    }
}

Compatibility

Virtual threads support requires:

  • JDK 21+: Virtual threads are a JDK 21+ feature

  • Spring Boot 3.2+: Spring Boot virtual thread support

  • Camel 4.0+: Camel virtual thread integration

Troubleshooting

If you encounter issues with virtual threads:

  1. Check JDK Version: Ensure you’re running JDK 21 or later

  2. Verify Property Setting: Confirm spring.threads.virtual.enabled=true is set

  3. Review Logs: Check for virtual thread configuration messages in startup logs

  4. Monitor Thread Usage: Use JVM monitoring tools to observe virtual thread behavior