[[SpringBoot-SpringBoot]]
= Spring Boot
//Manually maintained attributes
:artifactid: camel-spring-boot
:shortname: spring-boot
:camel-spring-boot-name: 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:

[source,xml]
----
<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 https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-starters[Spring
Boot Starter] module that allows you to develop Spring Boot applications
using starters. There is a
https://github.com/apache/camel-spring-boot-examples/tree/main/spring-boot[sample
application] in the source code also.

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

[source,xml]
----
<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:

[source,java]
----
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-configure options: START
include::{page-component-version}@components:spring-boot:partial$starter.adoc[]
// spring-boot-auto-configure options: END

== 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.

[source,java]
----
@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:

[source,java]
----
@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:

[source,java]
----
@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 http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config[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:

[source,properties]
----
route.from = jms:invoices
----

Or set via system property:

[source,properties]
----
java -Droute.to=jms:processed.invoices -jar mySpringApp.jar
----

...can be used as placeholders in Camel route:

[source,java]
----
@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:

[source,java]
----
@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:

[source,java]
----
@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:

[source,properties]
----
camel.main.consumer-template-cache-size = 100
camel.main.producer-template-cache-size = 200
----
[[typeconverter]]
== Auto-configured TypeConverter

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

[source,java]
----
@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 http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert[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:

[source,java]
----
@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`.

[source,properties]
----
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

[source,properties]
----
# 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

[source,xml]
----
<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 5 way

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

[source,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-junit5</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
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html[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 xref:components:others:test-spring-junit5.adoc[camel-test-spring-junit5] to configure tests declaratively. This example uses the `@MockEndpoints` annotation to auto-mock an endpoint:

[source,java]
----
@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 https://docs.spring.io/spring-boot/docs/current/reference/html/native-image.html#native-image.advanced.custom-hints[`RuntimeHintsRegistrar`]
or by providing GraalVM JSON hint files that can be generated by the https://docs.spring.io/spring-boot/docs/current/reference/html/native-image.html#native-image.advanced.using-the-tracing-agent[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:

[source,properties]
----
camel.health.async-camel-health-check=true
----

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

[source,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:

[source,properties]
----
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

[source,properties]
----
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.

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

=== Tomcat

[source,properties]
----
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

[source,properties]
----
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:
[source,properties]
----
management.server.undertow.accesslog.use-camel-logging=true
management.server.accesslog.pattern=combined
----


== 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:

[source,properties]
----
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:

[source,java]
----
@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`:
+
[source,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:
+
[source,xml]
----
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
----

3. Include Spring Boot Actuator:
+
[source,xml]
----
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
----

4. Expose actuator metrics and enable Undertow session statistics
+
[source,properties]
----
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:

[source,properties]
----
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`:

[source,java]
----
@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:

[source,properties]
----
# application.properties
spring.threads.virtual.enabled=true
camel.main.routes-include-pattern=classpath:routes/*
----

[source,java]
----
@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