[[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 `spring.factories` 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-bom</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.springboot.consumer-template-cache-size = 100
camel.springboot.producer-template-cache-size = 200
----

== 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.springboot.main-run-controller` to `true`.

[source,properties]
----
camel.springboot.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.springboot.xml-routes = false
# scan in the com/foo/routes classpath
camel.springboot.xml-routes = 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>
----

== Adding XML Rest-DSL

By default, you can put Camel Rest-DSL XML routes in the classpath under the
directory camel-rest, 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.springboot.xml-rests = false
# scan in the com/foo/routes classpath
camel.springboot.xml-rests = classpath:com/foo/rests/*.xml
----

The Rest-DSL XML files should be Camel XML rests (not CamelContext) such as

[source,xml]
----
<rests xmlns="http://camel.apache.org/schema/spring">
  <rest>
     <post uri="/persons">
        <to uri="direct:postPersons"/>
     </post>
     <get uri="/persons">
        <to uri="direct:getPersons"/>
     </get>
     <get uri="/persons/{personId}">
         <to uri="direct:getPersionId"/>
     </get>
     <put uri="/persons/{personId}">
         <to uri="direct:putPersionId"/>
     </put>
     <delete uri="/persons/{personId}">
         <to uri="direct:deletePersionId"/>
     </delete>
  </rest>
</rests>
----

== Testing the JUnit 4 way (deprecated)

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</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
`@RunWith(CamelSpringBootRunner.class)`. 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]
----
@RunWith(CamelSpringBootRunner.class)
@SpringBootTest
@MockEndpoints("direct:end")
public class MyApplicationTest {

    @Autowired
    private ProducerTemplate template;

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

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

}
----

== 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();
    }

}
----
