- Начало работы с Apache Camel с Java
- Улучшение запуска маршрутов с помощью CamelRunner
- Создание приложения на основе сообщений с использованием Camel
Но так как я подготовил camel-demo-1.0.0-SNAPSHOT-project.zip , в который включены все эти материалы, я подумал, что будет проще объединить их и представить в целом.
Начало работы с Apache Camel с Java
Испытать Camel с несколькими строками Groovy — это одно, а получить полноценный проект на Java — другое дело. Сегодня я покажу вам, как начать работу над Apache Camel с проектом на основе Maven . Вы также можете использовать предоставленную camel-demo
качестве шаблона проекта, чтобы начать свой собственный проект Apache Camel. Вам просто нужно переименовать пакет Java и переименовать группу pom и идентификаторы артефактов в соответствии с вашими потребностями.
Подготовка Maven-проекта с зависимостями Camel
Разархивируйте исходный код проекта camel-demo
, и вы увидите базовый макет каталога.
1
2
3
4
5
6
7
|
camel-demo +- bin +- config +- data +- src +- pom.xml +- README.txt |
Что делает эту демонстрацию проектом на основе Camel, так это просто объявление в pom.xml
. Давайте посмотрим файл и его зависимости.
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
<? 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' < 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
я объявил, предназначен только для этой цели, и вы можете изменить или удалить его, чтобы удовлетворить потребности вашего проекта.
Для верблюжьих зависимостей вам потребуется минимальное camel-core
для построения маршрутов. И тогда вы можете добавить любые дополнительные компоненты, которые вы планируете использовать в своем проекте. Я добавил следующее для построения типичной разработки приложений на основе сообщений:
-
camel-spring
— мы хотим иметь возможность объявить маршруты Camel в XML-файлах как конфигурацию. Смотрите каталогcamel-demo/config
для примеров. -
camel-jackson
— мы хотим обрабатывать данные сообщений в нашем приложении в формате JSON. -
camel-mina
— мы хотим отправлять данные сообщений по сети через TCP-сокет. -
camel-groovy
— [необязательно], мы хотим иметь возможность добавлять динамические сценарии в маршрут даже внутри конфигурации xml. Это отлично подходит для отладки и POC.
Обратите внимание, что поскольку мы используем несколько зависимостей компонентов верблюда, я решил установить свойство Maven ${camel.version}
чтобы при обновлении Camel было проще поддерживать файл pom.xml
в одном месте.
Вы должны иметь возможность перейти в каталог проекта и запустить mvn compile
чтобы убедиться, что проект. Должен компилироваться без ошибок.
Улучшение запуска маршрутов с помощью CamelRunner
pom.xml
файл проекта pom.xml
, вы можете приступить к созданию маршрутов Camel для обработки собственной бизнес-логики. Прежде чем мы будем слишком взволнованы, давайте попробуем простой HelloRoute
чтобы увидеть, как он работает и как мы можем запустить его в первую очередь. Вот код определения маршрута в src/main/java/deng/cameldemo/HelloRoute.java
.
01
02
03
04
05
06
07
08
09
10
11
|
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 мы бы написали этот установочный код в Main
классе. На самом деле Camel поставляется с абстрактным классом org.apache.camel.main.MainSupport
который вы можете использовать для расширения своего собственного Main
. Тем не менее, я думаю, что было бы еще лучше, если бы Camel предоставил CamelRunner
который может работать так.
1
|
$ java CamelRunner deng.cameldemo.HelloRoute |
Такой CamelRunner
был бы очень CamelRunner
для пользователя и CamelRunner
для повторного использования, так что я так и сделал. Я написал один такой:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
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.
1
2
|
$ 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
во время фазы package
, тогда используйте mvn dependency:copy-dependencies
будет работать нормально.
Пробная поездка на Camel, часть 2: запуск Camel с конфигурацией Spring xml
Приведенный HelloRoute
пример HelloRoute
просто предоставит определение маршрута, сформированное с использованием URI компонента. Было бы хорошо, если бы мы могли настроить маршрут декларативным образом, чтобы мы могли изменить маршрут без повторной компиляции файла класса. Это будет очень удобно, особенно если вы не знакомы с опциями каждого компонента и хотите изучить и опробовать его. Ну, вот для чего camel-spring
. Помимо предоставления возможности загрузки маршрута в конфигурационном файле xml, он также предоставляет очень гибкий способ регистрации bean-компонентов пользовательских служб / процессоров в контейнере Spring IoC.
Если вы увлеченный читатель, вы заметите в CamelRunner
выше коде CamelRunner
что у него есть дополнительная часть runWithSpringConfig
. Таким образом, CamelRunner
может фактически CamelRunner
любой файл Spring xml и запустить контекст как сервер. Вы можете использовать это так:
1
|
$ bin /run-java deng.cameldemo.CamelRunner -Dspring= true config /hellocamel-spring .xml |
config/hellocamel-spring.xml
является просто эквивалентом нашего кода HelloRoute
но в форме Spring xml:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
xsi:schemaLocation=' http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd < 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
. Первый шаг — вам нужен маршрут.
01
02
03
04
05
06
07
08
09
10
11
12
|
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()); } } |
Тогда следующий шаг … сделан! Нет, ты имеешь в виду, что это все для сервера? Слишком хорошо, чтобы быть правдой? Ну, давай попробуем
01
02
03
04
05
06
07
08
09
10
|
$ 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 для написания тонкого клиента.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
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
может отправлять любой текстовый файл на конечную точку вашего сервера. Попробуйте это во время работы вашего сервера:
1
2
3
4
5
6
|
$ 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
, который содержит этот простой текст:
1
|
{ 'firstName' : 'Zemian' , 'lastName' : 'Deng' } |
Обратите внимание, что наш сервер просто получает простой текст и регистрирует его. Мы обсудим, как обработать сообщение дальше.
Обработка данных сообщения в формате JSON с конфигурацией Camel и Spring xml
Вы думали, что серверный код был простым сверху, угадайте снова. Вы можете заменить TcpMsgRoute
несколькими простыми строками XML!
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
xsi:schemaLocation=' http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd < route > < from uri = 'mina:tcp://localhost:12345?sync=false' /> < to uri = 'log://deng.cameldemo.TcpMsgServer' /> </ route > </ camelContext > </ beans > |
Сохраните его как config/tcpmsgserver-spring.xml
. Затем перезапустите сервер, и вы получите тот же результат, что и выше.
1
|
$ bin /run-java deng.cameldemo.CamelRunner -Dspring= true config /tcpmsgserver-spring .xml |
Теперь давайте улучшим вышеупомянутый xml для дальнейшей обработки данных сообщения JSON. Мы хотим преобразовать простой текст в объект Java, а затем обработать его с помощью пользовательского компонента. Для этого сначала нужно добавить немаршальный компонент к маршруту. Это где camel-jackson
вступает в игру. В нашей демонстрации шаг демаршаллинга преобразует текст JSON в java.util.Map
а затем передает его компоненту с именем myMsgProcessor
. Давайте создадим новый XML-файл с именем config/tcpmsgserver-json-spring.xml
следующим образом.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
xsi:schemaLocation=' http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd < 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. Вот пример один:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
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-файлом, приведенным выше, и вы сможете повторно вызвать ту же команду клиента, чтобы протестировать ее. Вот пример вывода моего сервера:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
$ 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-карты. Затем он передает объект карты в наш компонент EJB. Кроме того, в этой демонстрации я решил использовать универсальный java.util.Map
качестве аргумента метода процессора (который является выводом демаршала JSON), но вы можете легко определить свой собственный тип бизнес-данных, такой как MyCustomerData
. Это показывает мощь Camel, поскольку вам не нужно помещать сообщение в свой поток, а беспокоиться только о том, чтобы записать свой «процессор» в виде POJO. Camel «склеит» компоненты вместе, чтобы сформировать маршрут и передать данные сообщения по конвейеру.
В то же время, когда вы пишете свою бизнес-логику на одном или нескольких процессорах, неплохо бы ограничить логику POJO настолько малой единицей, насколько это возможно. Когда вы сделаете это, вы сможете максимизировать возможность повторного использования процессоров. Чем больше вы делаете POJO, со множеством бизнес-логик, это также затруднит тестирование. Поэтому я рекомендую вам при разработке этих процессорных компонентов пытаться воспринимать их как кусочки LEGO — маленький POJO. Вы хотите, чтобы Camel определил маршрут и склеил кусочки LEGO вместе. Когда вы привыкнете думать, вы сможете использовать Camel более эффективно для решения многих проблем вашего домена.
Ну вот и все на сегодня, ребята. Я надеюсь, вам понравилась поездка на верблюде.
Приятного кодирования и не забудьте поделиться!
Ссылка: Создание приложения на основе сообщений с использованием Camel от нашего партнера по JCG Земьяна Дена в блоге A Programmer’s Journal .