This article has covered the integration of Apache Camel with the Spring Boot framework .
1. Introduction
Apache Camel β , . Apache Camel , , Camel 80 API . , β β , Camel . , Apache Camel Spring Boot.
Spring Boot, Camel.
1.1.
(message) β , .
1.2.
(exchange) β , . , .
1.3. Camel
Camel (CamelContext) β Camel, (, .).
1.4.
(routes) β , . , DSL, ().
1.5. -
- (Domain-Specific Language, DSL) β . DSL β Java Fluent API, Camel / XML - DSL.
1.6.
(processor) . , , .
1.7.
(component) β Apache Camel. Camel . , Camel. (URI).
1.8.
(endpoint) β , . , (URI). , FTP, URI: ftp://[@][:]/[?] β FTP .
1.9.
(producer) β Camel, .
1.10.
(consumer) β Camel, , , exchange .
Camel . , Camel . Spring Boot.
2.
:
: ;
;
(Camel Timer + Camel JPA);
REST (Camel REST);
Swagger (Camel Swagger).
H2, Spring Web, Spring JPA Apache Camel.
3.
. , IDE Spring Initializr. pom.xml :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--Get required dependencies from a parent-->
<parent>
<groupId>org.apache.camel</groupId>
<artifactId>camel-dependencies</artifactId>
<version>3.3.0</version>
</parent>
<artifactId>spring-boot-camel</artifactId>
<name>spring-boot-camel</name>
<description>Spring Boot Camel integration tutorial</description>
<properties>
<spring-boot-version>2.2.7.RELEASE</spring-boot-version>
<run.profiles>dev</run.profiles>
</properties>
<dependencyManagement>
<dependencies>
<!--Import as a pom to let spring-boot to manage spring-boot dependencies version -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--Import as a pom to let camel manage camel-spring-boot dependencies version-->
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-dependencies</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!--Spring boot dependencies to enable REST, JPA and Core features-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--Camel Spring Boot Dependencies to enable REST, JSON, SWAGGER, JPA features-->
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-servlet-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-jackson-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-swagger-java-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-jpa-starter</artifactId>
</dependency>
<!--In memory database-->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!--Spring boot testing-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot-version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
4.
Apache Camel, , .
4.1.
«» : , , . , Camel . « » , .
@Entity
@Table(name = "products")
@NamedQuery(name = "discounted-products", query = "select product from Product product where product.discounted IS NOT NULL")
public class Product {
@Id
@GeneratedValue
private int id;
private String name;
private Integer price;
private Integer discounted;
// Getters and setters
}
ProductRepository, CrudRepository
Spring Data. : findAll, findById, save . .
public interface ProductRepository extends CrudRepository<Product, Integer> {
}
4.2.
ProductService (service). ProductRepository Spring, . findById
, findAll
save
, .
@Service
public class ProductService {
private final ProductRepository products;
@Autowired
public ProductService(ProductRepository products) {
this.products = products;
}
public Product findById(Integer id) {
Optional < Product > product = products.findById(id);
if (!product.isPresent()) {
throw new IllegalStateException("Product could not found for given id:" + id);
}
return product.get();
}
public Iterable < Product > findAll() {
return products.findAll();
}
public void save(Product product) {
products.save(product);
}
}
, data.sql
src/main/resources
, . Spring data.sql
. .
INSERT INTO products (id, name, price, discounted)
VALUES
(1, 'Book', 25, NULL),
(2, 'Watch', 100, NULL),
(3, 'Shoes', 40, NULL);
4.3.
«» : , . , «» OneToOne.
@Entity @Table(name = "discounts") public class Discount { @Id @GeneratedValue private int id; private Integer amount; @OneToOne private Product product; // Getters and setters }
DiscountRepository, .
public interface DiscountRepository extends CrudRepository<Discount, Integer> {}
DiscountService ProductService. findDiscount
, findProduct
, makeDiscount
. , .
@Service
public class DiscountService {
private final DiscountRepository discounts;
private final ProductService productService;
private final Random random = new Random();
@Autowired
public DiscountService(DiscountRepository discounts,
ProductService productService) {
this.discounts = discounts;
this.productService = productService;
}
public Discount makeDiscount() {
// create a discount
Discount discount = new Discount();
int discountRate = this.random.nextInt(100);
discount.setAmount(discountRate);
// select random product
int productId = this.random.nextInt(3) + 1;
Product product = productService.findById(productId);
// set the discount to product and save
int discountedPrice = product.getPrice() - (discountRate * product.getPrice() / 100);
product.setDiscounted(discountedPrice);
productService.save(product);
discount.setProduct(product);
return discount;
}
public Discount findDiscount(Integer id) {
Optional < Discount > discount = discounts.findById(id);
if (!discount.isPresent()) {
throw new IllegalStateException("Discount could not found for given id:" + id);
}
return discount.get();
}
}
5.
application-dev.yml
, contextPath
Camel. , .
camel:
component:
servlet:
mapping:
contextPath: /javadevjournal/*
discount:
newDiscountPeriod: 2000
listDiscountPeriod: 6000/pre>
6. Apache Camel
, Apache Camel. .
6.1.
Camel : RouteBuilder. @Component
. , Apache Camel . SpringBoot Camel SpringBoot, CamelContext
, RouteBuilder
.
RouteBuilder . , . :
@Component class TimedJobs extends RouteBuilder { @Override public void configure() { from("timer:new-discount?delay=1000&period={{discount.newDiscountPeriod:2000}}") .routeId("make-discount") .bean("discountService", "makeDiscount") .to("jpa:org.apache.camel.example.spring.boot.rest.jpa.Discount") .log("Created %${body.amount} discount for ${body.product.name}"); // additional route will be added in the next step }
Spring Boot Camel. , Java DSL. β timer, Camel . «» Camel : ( ) .
, , Apache Camel Spring Boot, . , : {{_:__}}
.
make-discount, . makeDiscount bean- discountService. , , , . , , Simple. , .
from("jpa:org.apache.camel.example.spring.boot.rest.jpa.Product"
+ "?namedQuery=discounted-products"
+ "&delay={{discount.listDiscountPeriod:6000}}"
+ "&consumeDelete=false")
.routeId("list-discounted-products")
.log(
"Discounted product ${body.name}. Price dropped from ${body.price} to ${body.discounted}");
JPA «», namedQuery
. JPA , - , . consumeDelete
, «». JPA. :
Created %27 discount for Watch Created %84 discount for Book Created %92 discount for Shoes Discounted product Book. Price dropped from 25 to 4 Discounted product Watch. Price dropped from 100 to 73 Discounted product Shoes. Price dropped from 40 to 4
6.2. REST
. REST Swagger. RouteBuilder
. Camel restConfiguration
.
@Component class RestApi extends RouteBuilder { @Override public void configure() { restConfiguration() .contextPath("/javadevjournal") .apiContextPath("/api-doc") .apiProperty("api.title", "JAVA DEV JOURNAL REST API") .apiProperty("api.version", "1.0") .apiProperty("cors", "true") .apiContextRouteId("doc-api") .port(env.getProperty("server.port", "8080")) .bindingMode(RestBindingMode.json); rest("/products").description("Details of products") .get("/").description("List of all products") .route().routeId("products-api") .bean(ProductService.class, "findAll") .endRest() .get("discounts/{id}").description("Discount of a product") .route().routeId("discount-api") .bean(DiscountService.class, "findDiscount(${header.id})"); } }
contextPath
β javadevjournal β - API β api-doc
, Swagger. . Jackson JSON pom.xml, JSON. . /products
ProductService.findAll. /products
, /discounts/{id}
, DiscountService.findDiscount
id, . {header}
, Simple, {body}
.
http://localhost:8080/javadevjournal/api-doc
, Swagger. http://localhost:8080/javadevjournal/products
, :
[ { "id": 1, "name": "Book", "price": 25, "discounted": 4 }, { "id": 2, "name": "Watch", "price": 100, "discounted": 73 }, { "id": 3, "name": "Shoes", "price": 40, "discounted": 4 } ]
, http://localhost:8080/javadevjournal/products/discounts/1
, :
{ "id": 1, "amount": 92, "product": { "id": 3, "name": "Shoes", "price": 40, "discounted": 4 } }
, Apache Camel Spring Boot. , Apache Camel Spring Boot . Github.
14 demo day - , , -, , , .