Статьи

Начало работы с Apache Camel с использованием Java

Apache Camel — очень полезная библиотека, которая помогает вам обрабатывать события или сообщения из разных источников. Вы можете перемещать эти сообщения по многим различным протоколам, таким как между ВМ, HTTP, FTP, JMS или даже DIRECTORY / FILE, и при этом сохранять код обработки свободным от транспортной логики. Это позволяет вам сконцентрироваться на переваривании содержимого сообщений.

Здесь я приведу учебное пособие о том, как начать работу с Apache Camel, используя Java вместо  Groovy .

Начнем с создания pom.xml файла проекта Maven  .

<?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
http://maven.apache.org/maven-v4_0_0.xsd">




<modelVersion>4.0.0</modelVersion>
<groupId>camel-spring-demo</groupId>
<artifactId>camel-spring-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>




<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<camel.version>2.11.1</camel.version>
</properties>




<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.5</version>
</dependency>
</dependencies>




</project>

Мы только собираемся исследовать  camel-core, который на самом деле содержит довольно мало полезных компонентов, которые вы можете использовать. Также для целей ведения журнала я добавил slf4j-simple в  качестве реализации средства ведения  журнала,  чтобы мы могли видеть вывод на консоли.

Далее вам просто нужен класс для создания  Route. Route подобен определению инструкции для Camel о том, как перемещать ваши сообщения из одной точки в другую. Мы собираемся создать src/main/java/camelcoredemo/TimerRouteBuilder.java файл, который будет генерировать сообщение таймера каждую секунду, а затем передавать процессору, который просто регистрирует его.

package camelcoredemo;




import org.slf4j.*;
import org.apache.camel.*;
import org.apache.camel.builder.*;




public class TimerRouteBuilder extends RouteBuilder {
static Logger LOG = LoggerFactory.getLogger(TimerRouteBuilder.class);
public void configure() {
from("timer://timer1?period=1000")
.process(new Processor() {
public void process(Exchange msg) {
LOG.info("Processing {}", msg);
}
});
}
}

Это все, что вам нужно для начала. Теперь вы можете создать и запустить эту простую демонстрацию.

bash> mvn compile
bash> mvn exec:java -Dexec.mainClass=org.apache.camel.main.Main -Dexec.args='-r camelcoredemo.TimerRouteBuilder'

Обратите внимание, что мы даже не написали основной  класс Java  , а просто использовали  org.apache.camel.main.Main опцию, чтобы принять  RouteBuilder имя класса в качестве параметра. Затем он загрузит и создаст маршрут автоматически.

Контролировать CamelContext

Когда вы запускаете Camel, он создает  CamelContext объект, который содержит много информации о том, как его запустить, включая определение, которое  Route мы создали. Теперь, если вы хотите иметь больше контроля над этим  CamelContext, вам нужно написать свой собственный  Main класс. Я покажу вам простой здесь.

package camelcoredemo;




import org.slf4j.*;
import org.apache.camel.*;
import org.apache.camel.impl.*;
import org.apache.camel.builder.*;




public class TimerMain {
static Logger LOG = LoggerFactory.getLogger(TimerMain.class);
public static void main(String[] args) throws Exception {
new TimerMain().run();
}
void run() throws Exception {
final CamelContext camelContext = new DefaultCamelContext();
camelContext.addRoutes(createRouteBuilder());
camelContext.setTracing(true);
camelContext.start();




Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
camelContext.stop();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});




waitForStop();
}
RouteBuilder createRouteBuilder() {
return new TimerRouteBuilder();
}
void waitForStop() {
while (true) {
try {
Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException e) {
break;
}
}
}
}

Как видите, мы повторно использовали существующий  TimerRouteBuilder класс внутри  createRouteBuilder() метода. Наш  Main класс теперь имеет полный контроль над тем, когда создавать, запускать и останавливать  CamelContext. Этот контекст позволяет вам контролировать настройку Camel глобально, а не на  Route уровне. Ссылка javadoc предоставляет все методы установки, которые вы можете изучить, что он может делать.

Заметил, что нам также нужно предоставить несколько кодов настройки в нашем  Main классе. Сначала нам нужно обработать корректное завершение работы, поэтому мы добавили ловушку Java shutdown для вызова контекста  stop(). Во-вторых, нам нужно добавить блок потока после запуска контекста. Причина этого в том, что  CamelContext#start() метод неблокирующий! Если вы не заблокируете свой  Main поток после запуска, он просто выйдет сразу после него, что не будет иметь большого значения. Вы хотите запускать Camel как службу (например, сервер), пока не нажмете явно,  CTRL+C чтобы завершить процесс.

Улучшение  Main класса для начала CamelContext

Если вы не хотите иметь дело с большей частью  Main кода установки класса, такого как выше, то вы можете просто   расширить org.apache.camel.main.Main класс, предоставляемый  camel-coreintead. Если вы вернетесь к этому классу, у вас не будет автоматической настройки контекста, но вы получите все дополнительные функции командной строки, такие как управление продолжительностью процесса, включение трассировки, загрузка пользовательского класса маршрута и т. Д.

Рефакторинг предыдущего примера, вот как это выглядит.

package camelcoredemo;




import org.slf4j.*;
import org.apache.camel.builder.*;
import org.apache.camel.main.Main;




public class TimerMain2 extends Main {
static Logger LOG = LoggerFactory.getLogger(TimerMain2.class);
public static void main(String[] args) throws Exception {
TimerMain2 main = new TimerMain2();
main.enableHangupSupport();
main.addRouteBuilder(createRouteBuilder());
main.run(args);
}
static RouteBuilder createRouteBuilder() {
return new TimerRouteBuilder();
}
}

Теперь наша система  TimerMain2 намного короче, и вы можете попробовать ее, и она должна функционировать так же, как и раньше.

bash> mvn compile
bash> mvn exec:java -Dexec.mainClass=camelcoredemo.TimerMain2 -Dexec.args='-t'

Обратите внимание, что мы указали  -t опцию, и она сбросит  Route трассировку. Используйте,  -h и вы увидите все доступные варианты.

Добавление бобов к верблюду Registry

В  TimerRouteBuilder приведенном выше примере мы создали  Processor на лету. Теперь, если бы вы объединили несколько разных  Processor вместе, было бы лучше минимизировать шум. Camel позволяет вам делать это, регистрируя компоненты обработки в их пространстве реестра, а затем вы просто указываете их в своем маршруте как  beanкомпонент. Вот как я могу преобразовать приведенный выше пример в обработку bean-компонентов.

package camelcoredemo;




import org.slf4j.*;
import org.apache.camel.*;
import org.apache.camel.builder.*;
import org.apache.camel.main.Main;




public class TimerBeansMain extends Main {
static Logger LOG = LoggerFactory.getLogger(TimerBeansMain.class);
public static void main(String[] args) throws Exception {
TimerBeansMain main = new TimerBeansMain();
main.enableHangupSupport();
main.bind("processByBean1", new Bean1());
main.bind("processAgainByBean2", new Bean2());
main.addRouteBuilder(createRouteBuilder());
main.run(args);
}
static RouteBuilder createRouteBuilder() {
return new RouteBuilder() {
public void configure() {
from("timer://timer1?period=1000")
.to("bean:processByBean1")
.to("bean:processAgainByBean2");
}
};
}




// Processor beans
static class Bean1 implements Processor {
public void process(Exchange msg) {
LOG.info("First process {}", msg);
}
}
static class Bean2 implements Processor {
public void process(Exchange msg) {
LOG.info("Second process {}", msg);
}
}
}

Теперь вы видите мой  Route очень тонкий и без шумового шума; и я реорганизовал мой код обработки в отдельные классы. Это способствует более эффективному управлению и тестированию кода, поскольку вы пишете более сложную  Route для решения бизнес-логики. Это позволило вам создать LEGO-подобный блок повторно используемых бобов POJO. Помимо обработки бобов, Camel использует это пространство реестра и для многих других сервисов. Например, вы можете настроить многие другие конечные точки компонентов с помощью дополнительных функций и / или конфигураций. Или такая вещь, как замена реализации стратегии пула потоков и т. Д.

Приведенный  Route выше пример построен с использованием так называемой Java DSL. Маршрут очень удобен для чтения, но вы получите полную поддержку IDE для просмотра всех методов, доступных для вашего маршрута.

Я надеюсь, что эта статья помогла вам начать езду на верблюде. Помимо timer упомянутого компонента, в  комплект поставки camel-core входят следующие компоненты.

Повеселись!