«1. Обзор

В этой статье мы представим Camel и рассмотрим одну из его основных концепций — маршрутизацию сообщений.

Мы начнем с рассмотрения этих основных понятий и терминологии, а затем представим два основных варианта определения маршрутов — Java DSL и Spring DSL.

Мы также продемонстрируем это на примере — определив маршрут, который использует файлы из одной папки и перемещает их в другую, добавляя метку времени к имени каждого файла.

2. Об Apache Camel

Apache Camel — это интеграционная среда с открытым исходным кодом, предназначенная для простой и легкой интеграции систем.

Он позволяет конечным пользователям интегрировать различные системы, используя один и тот же API, обеспечивая поддержку нескольких протоколов и типов данных, будучи расширяемым и позволяя вводить собственные протоколы.

3. Зависимости Maven

Чтобы использовать Camel, нам нужно сначала добавить зависимость Maven:

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-core</artifactId>
    <version>2.18.0</version>
</dependency>

Последнюю версию артефакта Camel можно найти здесь.

3. Язык предметной области

Маршруты и механизм маршрутизации являются центральной частью Camel. Маршруты содержат поток и логику интеграции между различными системами.

Чтобы определение маршрутов было более простым и понятным, Camel предлагает несколько различных предметно-ориентированных языков (DSL) для таких языков программирования, как Java или Groovy. С другой стороны, он также обеспечивает определение маршрутов в XML с помощью Spring DSL.

Использование Java DSL или Spring DSL в основном является предпочтением пользователя, поскольку большинство функций доступны в обоих.

Java DSL предлагает немного больше функций, которые не поддерживаются в Spring DSL. Однако Spring DSL иногда более выгоден, поскольку XML можно изменить без необходимости перекомпилировать код.

4. Терминология и архитектура

Давайте теперь обсудим основную терминологию и архитектуру Camel.

Сначала мы рассмотрим основные концепции Camel:

    Сообщение содержит данные, которые передаются по маршруту. Каждое сообщение имеет уникальный идентификатор и состоит из тела, заголовков и вложений. Exchange является контейнером сообщения и создается, когда сообщение получено потребителем в процессе маршрутизации. Exchange допускает различные типы взаимодействия между системами — он может определять одностороннее сообщение или сообщение типа «запрос-ответ». Конечная точка — это канал, по которому система может получать или отправлять сообщения. Он может ссылаться на URI веб-службы, URI очереди, файл, адрес электронной почты и т. д. Компонент действует как фабрика конечных точек. Проще говоря, компоненты предлагают интерфейс для различных технологий, используя один и тот же подход и синтаксис. Camel уже поддерживает множество компонентов в своих DSL почти для каждой возможной технологии, но также дает возможность писать пользовательские компоненты. Процессор — это простой интерфейс Java, который используется для добавления пользовательской логики интеграции в маршрут. Он содержит единственный метод процесса, используемый для преформирования пользовательской бизнес-логики в сообщении, полученном потребителем

На высоком уровне архитектура Camel проста. CamelContext представляет систему времени выполнения Camel и связывает различные концепции, такие как маршруты, компоненты или конечные точки.

И еще ниже процессоры обрабатывают маршрутизацию и преобразования между конечными точками, в то время как конечные точки интегрируют разные системы.

5. Определение маршрута

Маршруты можно определить с помощью Java DSL или Spring DSL.

Мы проиллюстрируем оба стиля, определив маршрут, который использует файлы из одной папки и перемещает их в другую папку, добавляя метку времени к имени каждого файла.

5.1. Маршрутизация с помощью Java DSL

Чтобы определить маршрут с помощью Java DSL, нам сначала нужно создать экземпляр DefaultCamelContext. После этого нам нужно расширить класс RouteBuilder и реализовать метод configure, который будет содержать поток маршрута:

private static final long DURATION_MILIS = 10000;
private static final String SOURCE_FOLDER = "src/test/source-folder";
private static final String DESTINATION_FOLDER 
  = "src/test/destination-folder";

@Test
public void moveFolderContentJavaDSLTest() throws Exception {
    CamelContext camelContext = new DefaultCamelContext();
    camelContext.addRoutes(new RouteBuilder() {
      @Override
      public void configure() throws Exception {
        from("file://" + SOURCE_FOLDER + "?delete=true").process(
          new FileProcessor()).to("file://" + DESTINATION_FOLDER);
      }
    });
    camelContext.start();
    Thread.sleep(DURATION_MILIS);
    camelContext.stop();
}

Метод configure можно прочитать так: читать файлы из исходной папки, обрабатывать их с помощью FileProcessor и отправлять результат в папку назначения. Установка delete=true означает, что файл будет удален из исходной папки после успешной обработки.

«Чтобы запустить Camel, нам нужно вызвать метод start для CamelContext. Thread.sleep вызывается, чтобы дать Camel время, необходимое для перемещения файлов из одной папки в другую.

FileProcessor реализует интерфейс Processor и содержит единственный метод процесса, который содержит логику для изменения имен файлов:

public class FileProcessor implements Processor {
    public void process(Exchange exchange) throws Exception {
        String originalFileName = (String) exchange.getIn().getHeader(
          Exchange.FILE_NAME, String.class);

        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat(
          "yyyy-MM-dd HH-mm-ss");
        String changedFileName = dateFormat.format(date) + originalFileName;
        exchange.getIn().setHeader(Exchange.FILE_NAME, changedFileName);
    }
}

Чтобы получить имя файла, мы должны получить входящее сообщение от обмена и получить доступ к его заголовку. Аналогично этому, чтобы изменить имя файла, мы должны обновить заголовок сообщения.

5.2. Маршрутизация с помощью Spring DSL

При определении маршрута с помощью Spring DSL мы используем файл XML для настройки наших маршрутов и процессоров. Это позволяет нам настраивать маршруты без использования кода с помощью Spring и, в конечном итоге, дает нам преимущество полной инверсии управления.

Это уже было описано в существующей статье, поэтому мы сосредоточимся на использовании как Spring DSL, так и Java DSL, который обычно является предпочтительным способом определения маршрутов.

В этом случае CamelContext определяется в XML-файле Spring с использованием пользовательского синтаксиса XML для Camel, но без определения маршрута, как в случае «чистого» Spring DSL с использованием XML:

<bean id="fileRouter" class="com.baeldung.camel.file.FileRouter" />
<bean id="fileProcessor" 
  class="com.baeldung.camel.file.FileProcessor" />

<camelContext xmlns="http://camel.apache.org/schema/spring">
    <routeBuilder ref="fileRouter" />
</camelContext>

Таким образом, мы говорим Верблюд для использования класса FileRouter, который содержит определение нашего маршрута в Java DSL:

public class FileRouter extends RouteBuilder {

    private static final String SOURCE_FOLDER = 
      "src/test/source-folder";
    private static final String DESTINATION_FOLDER = 
      "src/test/destination-folder";

    @Override
    public void configure() throws Exception {
        from("file://" + SOURCE_FOLDER + "?delete=true").process(
          new FileProcessor()).to("file://" + DESTINATION_FOLDER);
    }
}

Чтобы проверить это, мы должны создать экземпляр ClassPathXmlApplicationContext, который загрузит наш CamelContext весной:

@Test
public void moveFolderContentSpringDSLTest() throws InterruptedException {
    ClassPathXmlApplicationContext applicationContext = 
      new ClassPathXmlApplicationContext("camel-context.xml");
    Thread.sleep(DURATION_MILIS);
    applicationContext.close();
}

~~ ~ Используя этот подход, мы получаем дополнительную гибкость и преимущества, предоставляемые Spring, а также все возможности языка Java за счет использования Java DSL.

6. Заключение

В этой небольшой статье мы представили введение в Apache Camel и продемонстрировали преимущества использования Camel для задач интеграции, таких как маршрутизация файлов из одной папки в другую.

В нашем примере мы увидели, что Camel позволяет вам сосредоточиться на бизнес-логике и сокращает объем шаблонного кода.

Код из этой статьи можно найти на GitHub.