Статьи

Создание приложения на основе сообщений с использованием Camel

Это длинная статья, которая содержит три отдельные темы:

  • Начало работы с Apache Camel с Java
  • Улучшение запуска маршрутов с помощью CamelRunner
  • Создание приложения на основе сообщений с использованием Camel

Но так как я подготовил camel-demo-1.0.0-SNAPSHOT-project.zip , в который включены все эти материалы, я подумал, что будет проще объединить их и представить в целом.

Начало работы с Apache Camel с Java

Испытать Camel с несколькими строками Groovy — это одно, а получить полноценный проект на Java — другое дело. Сегодня я покажу вам, как начать работу над Apache Camel с проектом на основе Maven . Вы также можете использовать предоставленную верблюжье демо в качестве шаблона проекта, чтобы начать свой собственный проект Apache Camel. Вам просто нужно переименовать пакет Java и переименовать группу pom и идентификаторы артефактов в соответствии с вашими потребностями.

Подготовка Maven-проекта с зависимостями Camel

Разархивируйте исходный код проекта camel-demo, и вы увидите базовый макет каталога.

camel-demo
    +- bin
    +- config
    +- data
    +- src
    +- pom.xml
    +- README.txt

 

Что делает эту демонстрацию проектом на основе Camel, так это просто объявление в 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   http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>deng.cameldemo</groupId>
    <artifactId>camel-demo</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <slf4j.version>1.6.6</slf4j.version>
        <camel.version>2.10.1</camel.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>project</descriptorRef>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>

        <!-- Unit testing lib -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit-dep</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-library</artifactId>
            <version>1.2.1</version>
            <scope>test</scope>
        </dependency>

        <!-- Logging lib -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!-- Apache Commons lib -->
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.0.1</version>
        </dependency>

        <!-- Apache Camel -->
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-core</artifactId>
            <version>${camel.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-spring</artifactId>
            <version>${camel.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-groovy</artifactId>
            <version>${camel.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-jackson</artifactId>
            <version>${camel.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-mina</artifactId>
            <version>${camel.version}</version>
        </dependency>

    </dependencies>

</project>

 

Этот pom.xml декаляризирует приложение на основе Java, и он создаст jar. Требуется минимум JDK 6 или выше. Помимо типичного junit и hamcrest для модульного тестирования, я также добавил slf4j для ведения журнала. Я также добавил в проект пару Apache’s commons-lang / io. Я думаю, что это основные настройки, которые должно использовать любое приложение на основе Java.

Плагин maven-assembly-plugin, который я объявил, предназначен только для этой цели, и вы можете изменить или удалить его в соответствии со своими потребностями проекта.

Для верблюжьих зависимостей вам потребуется минимальное ядро ​​верблюда для построения маршрутов. И тогда вы можете добавить любые дополнительные компоненты, которые вы планируете использовать в своем проекте. Я добавил следующее для построения типичной разработки приложений на основе сообщений:

  1. Camel-spring — мы хотим иметь возможность объявить маршруты Camel в XML-файлах как конфигурацию. Смотрите каталог camel-demo / config для примеров.
  2. Верблюд-Джексон — мы хотим обрабатывать данные сообщений в нашем приложении в формате JSON.
  3. Верблюд-мина — мы хотим отправлять данные сообщений по сети через TCP-сокет.
  4. Camel-groovy — [необязательно], мы хотим иметь возможность добавлять динамические сценарии в маршрут даже внутри конфигурации xml. Это отлично подходит для отладки и POC.

Обратите внимание, что, поскольку мы используем несколько зависимостей компонентов верблюда, я решил установить свойство Maven $ {camel.version}, чтобы при обновлении Camel было проще поддерживать файл pom.xml в одном месте.

Вы должны иметь возможность перейти в каталог проекта и запустить mvn compile, чтобы убедиться, что проект. Должен компилироваться без ошибок.

Улучшение запуска маршрутов с помощью CamelRunner

Подготовив файл проекта pom.xml, вы можете приступить к созданию маршрутов Camel для обработки собственной бизнес-логики. Прежде чем мы будем слишком взволнованы, давайте попробуем простой HelloRoute, чтобы увидеть, как он работает и как мы можем запустить его в первую очередь. Вот код определения маршрута в src / main / java / deng / cameldemo / HelloRoute.java.

package deng.cameldemo;

import org.apache.camel.builder.RouteBuilder;

public class HelloRoute extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        from("timer://helloTimer?period=3000").
            to("log:" + getClass().getName());
    }
}

 

Проведи пробную поездку на верблюде

Чтобы увидеть выше в действии, нам нужно добавить его в CamelContext и запустить контекст. Для автономной программы на Java мы бы написали этот установочный код в главном классе. На самом деле Camel поставляется с абстрактным классом org.apache.camel.main.MainSupport, который вы можете использовать для расширения своего собственного Main. Тем не менее, я думаю, что было бы еще лучше, если бы Camel предоставил CamelRunner, который может работать так.

$ java CamelRunner deng.cameldemo.HelloRoute

Такой CamelRunner был бы очень удобен для пользователя и пригоден для повторного использования, так что я так и сделал. Я написал один такой:

package deng.cameldemo;

import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

/** 
 * A main program to start Camel and run as a server using RouteBuilder class names or 
 * Spring config files.
 * 
 * <p>Usage:
 * 
 * java deng.cameldemo.CamelRunner deng.cameldemo.HelloRoute
 * 
 * or
 * 
 * java -Dspring=true deng.cameldemo.CamelRunner /path/to/camel-spring.xml
 * 
 * @author Zemian Deng
 */
public class CamelRunner {
    public static void main(String[] args) throws Exception {
        CamelRunner runner = new CamelRunner();
        runner.run(args);
    }

    private static Logger logger = LoggerFactory.getLogger(CamelRunner.class);
    public void run(String[] args) throws Exception {
        if (Boolean.parseBoolean(System.getProperty("spring", "false")))
            runWithSpringConfig(args);
        else
            runWithCamelRoutes(args);

        // Wait for user to hit CRTL+C to stop the service
        synchronized(this) {
            this.wait();
        }
    }

    private void runWithSpringConfig(String[] args) {
        final ConfigurableApplicationContext springContext = new FileSystemXmlApplicationContext(args);

        // Register proper shutdown.
        Runtime.getRuntime().addShutdownHook(new Thread() { 
            @Override
            public void run() {
                try {
                    springContext.close();
                    logger.info("Spring stopped.");
                } catch (Exception e) {
                    logger.error("Failed to stop Spring.", e);
                }
            }
        });

        // Start spring
        logger.info("Spring started.");
    }

    private void runWithCamelRoutes(String[] args) throws Exception {
        final CamelContext camelContext = new DefaultCamelContext();        
        // Register proper shutdown.
        Runtime.getRuntime().addShutdownHook(new Thread() { 
            @Override
            public void run() {
                try {
                    camelContext.stop();
                    logger.info("Camel stopped for {}", camelContext);
                } catch (Exception e) {
                    logger.error("Failed to stop Camel.", e);
                }
            }
        });

        // Added RouteBuilder from args
        for (String className : args) {
            Class<?> cls = Class.forName(className);
            if (RouteBuilder.class.isAssignableFrom(cls)) {
                Object obj = cls.newInstance();
                RouteBuilder routeBuilder = (RouteBuilder)obj;
                camelContext.addRoutes(routeBuilder);
            } else {
                throw new RuntimeException("Unable to add Camel RouteBuilder " + className);
            }
        }

        // Start camel
        camelContext.start();
        logger.info("Camel started for {}", camelContext);
    }
}

 

Чтобы помочь вам запустить основной класс, я предоставил скрипт обертку run-java в каталоге bin проекта, чтобы вы могли быстро протестировать его без необходимости установки classpath.

$ mvn package
$ bin/run-java deng.cameldemo.CamelRunner deng.cameldemo.HelloRoute

 

Вы увидите, что программа загрузит HelloRoute в DefaultCamelContext и запустит его как сервер. Сам HelloRoute сгенерирует сообщение таймера на 3 секунды и отправит его регистратору, который должен распечатать на экране вашей консоли. Это будет продолжаться вечно, пока вы не нажмете CTRL + C, чтобы завершить его.

ПРИМЕЧАНИЕ. Вам нужно всего лишь один раз вызвать команду mvn package, чтобы она упаковала все jar-файлы зависимостей, чтобы run-java мог автоматически их обнаружить. Если вы не собираетесь использовать maven-assembly-plugin во время фазы пакета, тогда используйте команду mvn dependency: копия-зависимость также будет работать нормально.

Пробная поездка на Camel, часть 2: запуск Camel с конфигурацией Spring xml

Приведенный выше пример HelloRoute просто предоставит определение маршрута, сформированное с использованием URI компонента. Было бы хорошо, если бы мы могли настроить маршрут декларативным образом, чтобы мы могли изменить маршрут без повторной компиляции файла класса. Это будет очень удобно, особенно если вы не знакомы с опциями каждого компонента и хотите изучить и опробовать его. Ну, вот для чего верблюжья весна. Помимо предоставления возможности загрузки маршрута в конфигурационном файле xml, он также предоставляет очень гибкий способ регистрации bean-компонентов пользовательских служб / процессоров в контейнере Spring IoC.

Если вы увлеченный читатель, вы заметите в приведенном выше коде CamelRunner, что у него есть дополнительная часть runWithSpringConfig. Таким образом, CamelRunner может фактически загрузить любой файл Spring xml и запустить контекст как сервер. Вы можете использовать это так:

$ bin/run-java deng.cameldemo.CamelRunner -Dspring=true config/hellocamel-spring.xml

Config / hellocamel-spring.xml является просто эквивалентом нашего кода HelloRoute, но в форме Spring xml:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

    <camelContext id="helloCamel" xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="timer://jdkTimer?period=3000"/>
            <to uri="log://deng.cameldemo.HelloCamel"/>
        </route>
    </camelContext>

</beans>

 

Это устраняет необходимость компилировать / перекомпилировать HelloRoute для определения маршрута Camel для запуска.

Создание приложения на основе сообщений с использованием Camel

Чтобы представить вам более практическую демонстрацию, я покажу вам, как настроить Camel для обработки приложения на основе сообщений. Во многих ИТ-магазинах принято, что у вас есть сервер, который принимает данные сообщений в качестве входных данных и обрабатывает их. Практический вариант использования — взять любое сообщение в формате JSON, преобразовать его в объект и обработать. Чтобы сделать это в Camel, вы хотите построить маршрут, который будет принимать входные сообщения от порта TCP, а затем обрабатывать его в конвейерном потоке с любой имеющейся у вас бизнес-логикой. Вы будете запускать маршрут как сервер, а затем клиент может использовать любое средство для отправки сообщения на порт TCP. Клиент может даже быть еще одним тонким клиентским приложением Camel для отправки данных. Позвольте мне показать вам, как начать.

Написание кода на стороне сервера с использованием маршрута Camel

На стороне сервера потребуется маршрут для прослушивания через порт TCP, и это обеспечивается компонентом Camel-Mina. Первый шаг — вам нужен маршрут.

package deng.cameldemo;

import org.apache.camel.builder.RouteBuilder;

public class TcpMsgRoute extends RouteBuilder {
    @Override
    public void configure() throws Exception {
        String port = System.getProperty("port", "12345");
        from("mina:tcp://localhost:" + port + "?sync=false").
            to("log:" + getClass().getName());
    }
}

 

Тогда следующий шаг … сделан! Нет, ты имеешь в виду, что это все для сервера? Слишком хорошо, чтобы быть правдой? Ну, давай попробуем

$ bin/run-java deng.cameldemo.CamelRunner deng.cameldemo.TcpMsgRoute -Dport=12345
15:21:41 main INFO  org.apache.camel.impl.DefaultCamelContext:1391 | Apache Camel 2.10.1 (CamelContext: camel-1) is starting
15:21:41 main INFO  org.apache.camel.management.ManagementStrategyFactory:43 | JMX enabled.
15:21:42 main INFO  org.apache.camel.impl.converter.DefaultTypeConverter:45 | Loaded 172 type converters
15:21:42 main INFO  org.apache.camel.component.mina.MinaConsumer:59 | Binding to server address: localhost/127.0.0.1:12345 using acceptor: org.apache.mina.transport.socket.nio.SocketAcceptor@2ffad8fe
15:21:42 main INFO  org.apache.camel.impl.DefaultCamelContext:2045 | Route: route1 started and consuming from: Endpoint[mina://tcp://localhost:12345?sync=true]
15:21:42 main INFO  org.apache.camel.management.DefaultManagementLifecycleStrategy:859 | StatisticsLevel at All so enabling load performance statistics
15:21:42 main INFO  org.apache.camel.impl.DefaultCamelContext:1426 | Total 1 routes, of which 1 is started.
15:21:42 main INFO  org.apache.camel.impl.DefaultCamelContext:1427 | Apache Camel 2.10.1 (CamelContext: camel-1) started in 0.505 seconds
15:21:42 main INFO  deng.cameldemo.CamelRunner:93 | Camel started for CamelContext(camel-1)

 

Вуаля! Сервер запущен и ждет, пока ваши пользователи отправят сообщения через порт 12345. Не так уж плохо для нескольких строк кода.

Написание кода на стороне клиента с помощью Camel ProducerTemplate

Поскольку наш сервер предоставляет порт TCP и принимает любое текстовое сообщение, вы можете создать любого клиента, способного записывать данные в сокет TCP. Здесь я покажу вам, как использовать Camel для написания тонкого клиента.

package deng.cameldemo.client;

import java.io.FileReader;
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TcpMsgSender {
    public static void main(String[] args) throws Exception {
        TcpMsgSender runner = new TcpMsgSender();
        runner.run(args);
    }

    private static Logger logger = LoggerFactory.getLogger(TcpMsgSender.class);
    public void run(String[] args) throws Exception {
        String fileName = args.length > 0 ? args[0] : "data/msg.txt";
        String[] hostPort = (args.length > 1 ? args[1] : "localhost:12345").split(":");
        String host = hostPort[0];
        String port = hostPort.length > 1 ? hostPort[1] : "12345";
        logger.info("Sending tcp message {} to host={}, port={}", new Object[]{ fileName, host, port});

        String text = IOUtils.toString(new FileReader(fileName));
        logger.debug("File size={}", text.length());

        CamelContext camelContext = new DefaultCamelContext();
        ProducerTemplate producer = camelContext.createProducerTemplate();
        producer.sendBody("mina:tcp://" + host + ":" + port + "?sync=false", text);
        logger.info("Message sent.");
    }
}

 

Этот TcpMsgSender может отправлять любой текстовый файл на конечную точку вашего сервера. Попробуйте это во время работы вашего сервера:

$ bin/run-java deng.cameldemo.client.TcpMsgSender data/test-msg.json localhost:12345
15:22:35 main INFO  deng.cameldemo.client.TcpMsgSender:24 | Sending tcp message data/test-msg.json to host=localhost, port=12345
15:22:35 main DEBUG deng.cameldemo.client.TcpMsgSender:27 | File size=47
15:22:35 main INFO  org.apache.camel.impl.converter.DefaultTypeConverter:45 | Loaded 172 type converters
15:22:35 main INFO  org.apache.camel.management.ManagementStrategyFactory:43 | JMX enabled.
15:22:35 main INFO  deng.cameldemo.client.TcpMsgSender:32 | Message sent.

 

Вы должны быть в состоянии проверить с вашего сервера вывод консоли, что он получил сообщение. Сообщение, которое я отправил, находится в data / test-msg.json, который содержит этот простой текст:

{ "firstName" : "Zemian", "lastName" : "Deng" }

 

Обратите внимание, что наш сервер просто получает простой текст и регистрирует его. Мы обсудим, как обработать сообщение дальше.

Обработка данных сообщения в формате JSON с конфигурацией Camel и Spring xml

Вы думали, что серверный код был простым сверху, угадайте снова. Вы можете заменить TcpMsgRoute несколькими простыми строками XML!

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

    <camelContext id="tcpMsgServer" xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="mina:tcp://localhost:12345?sync=false"/>
            <to uri="log://deng.cameldemo.TcpMsgServer"/>
        </route>
    </camelContext>

</beans>

 

Сохраните его как config / tcpmsgserver-spring.xml. Затем перезапустите сервер, и вы получите тот же результат, что и выше.

$ bin/run-java deng.cameldemo.CamelRunner -Dspring=true config/tcpmsgserver-spring.xml

 

Теперь давайте улучшим вышеупомянутый xml для дальнейшей обработки данных сообщения JSON. Мы хотим преобразовать простой текст в объект Java, а затем обработать его с помощью пользовательского компонента. Для этого сначала нужно добавить немаршальный компонент к маршруту. Это где верблюд-Джексон вступает в игру. В нашей демонстрации шаг демаршаллинга преобразует текст JSON в java.util.Map и затем передает его компоненту с именем myMsgProcessor. Давайте создадим новый XML-файл с именем config / tcpmsgserver-json-spring.xml следующим образом.

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

    <camelContext id="tcpMsgServer" xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="mina:tcp://localhost:12345?sync=false"/>
            <to uri="log://deng.cameldemo.TcpMsgServer"/>
            <unmarshal>
                <json library="Jackson"/>
            </unmarshal>
            <to uri="bean:myMsgProcessor?method=process"/>
        </route>
    </camelContext>

    <bean id="myMsgProcessor" class="deng.cameldemo.MyMsgProcessor">
    </bean>

</beans>

 

MyMsgProcessor — это bean-компонент Spring, для предоставления данных которого мы предоставляем специальный логический код. На данный момент у нас есть полный Java-объект для манипулирования. Содержимое процессора может быть любым POJO с именем метода, указанным в URI. Вот пример один:

package deng.cameldemo;

import org.apache.camel.builder.RouteBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;

public class MyMsgProcessor {
    private static Logger logger = LoggerFactory.getLogger(MyMsgProcessor.class);
    public void process(Map<String, String> data) {
        logger.info("We should slice and dice the data: " + data);
    }
}

 

Попробуйте перезапустить сервер с новым XML-файлом, приведенным выше, и вы сможете повторно вызвать ту же команду клиента, чтобы протестировать ее. Вот пример вывода моего сервера:

$ bin/run-java deng.cameldemo.CamelRunner -Dspring=true config/tcpmsgserver-json-spring.xml
17:05:25 main INFO  org.springframework.context.support.FileSystemXmlApplicationContext:456 | Refreshing org.springframework.context.support.FileSystemXmlApplicationContext@4200309: startup date [Sat Sep 15 17:05:25 EDT 2012]; root of context hierarchy
17:05:25 main INFO  org.springframework.beans.factory.xml.XmlBeanDefinitionReader:315 | Loading XML bean definitions from file [/Users/zemian/projects/sandbox/camel-demo/config/tcpmsgserver-json-spring.xml]
17:05:27 main INFO  org.springframework.beans.factory.support.DefaultListableBeanFactory:557 | Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@27b75165: defining beans [template,consumerTemplate,tcpMsgServer:beanPostProcessor,tcpMsgServer,myMsgProcessor]; root of factory hierarchy
17:05:27 main INFO  org.apache.camel.spring.SpringCamelContext:1391 | Apache Camel 2.10.1 (CamelContext: tcpMsgServer) is starting
17:05:27 main INFO  org.apache.camel.management.ManagementStrategyFactory:43 | JMX enabled.
17:05:27 main INFO  org.apache.camel.impl.converter.DefaultTypeConverter:45 | Loaded 172 type converters
17:05:28 main INFO  org.apache.camel.component.mina.MinaConsumer:59 | Binding to server address: localhost/127.0.0.1:12345 using acceptor: org.apache.mina.transport.socket.nio.SocketAcceptor@5a3cae4a
17:05:28 main INFO  org.apache.camel.spring.SpringCamelContext:2045 | Route: route1 started and consuming from: Endpoint[mina://tcp://localhost:12345?sync=false]
17:05:28 main INFO  org.apache.camel.management.DefaultManagementLifecycleStrategy:859 | StatisticsLevel at All so enabling load performance statistics
17:05:28 main INFO  org.apache.camel.spring.SpringCamelContext:1426 | Total 1 routes, of which 1 is started.
17:05:28 main INFO  org.apache.camel.spring.SpringCamelContext:1427 | Apache Camel 2.10.1 (CamelContext: tcpMsgServer) started in 0.695 seconds
17:05:28 main INFO  deng.cameldemo.CamelRunner:61 | Spring started.
17:05:35 Camel (tcpMsgServer) thread #3 - MinaThreadPool INFO  deng.cameldemo.TcpMsgServer:96 | Exchange[ExchangePattern:InOnly, BodyType:String, Body:{ "firstName" : "Zemian", "lastName" : "Deng" }]
17:05:35 Camel (tcpMsgServer) thread #3 - MinaThreadPool INFO  deng.cameldemo.MyMsgProcessor:11 | We should slice and dice the data: {lastName=Deng, firstName=Zemian}

Обратите внимание, что Camel автоматически преобразует формат данных в вашем маршруте! Наш клиент отправляет только простой текст в формате JSON, но когда сервер получает его, он демарширует его с помощью библиотеки Джексона, а затем преобразует его в объект Java-карты. Затем он передает объект карты в bean-компонент нашего процессора. Кроме того, в этой демонстрации я решил использовать универсальный java.util.Map в качестве аргумента метода процессора (который является выводом демаршала JSON), но вы можете легко определить свой собственный тип бизнес-данных, такой как MyCustomerData. Это раскрывает силу Camel, поскольку вам не нужно выдвигать сообщение в своем потоке, а беспокоиться только о том, чтобы записать свой «процессор» в виде POJO. Camel «склеит» компоненты вместе, чтобы сформировать маршрут и передать данные сообщения через поток конвейера.

В то же время, когда вы пишете свою бизнес-логику на одном или нескольких процессорах, неплохо бы ограничить логику POJO настолько малой единицей, насколько это возможно. Когда вы сделаете это, вы сможете максимизировать возможность повторного использования процессоров. Чем больше вы делаете POJO, со множеством бизнес-логик, это также затруднит тестирование. Поэтому я рекомендую вам при разработке этих процессорных компонентов пытаться воспринимать их как кусочки LEGO — маленький POJO. Вы хотите, чтобы Camel определил маршрут и склеил кусочки LEGO вместе. Когда вы привыкнете думать, вы сможете использовать Camel более эффективно для решения многих проблем вашего домена.

Ну вот и все на сегодня, ребята. Я надеюсь, вам понравилась поездка на верблюде. Удачного программирования!