Spring Integration и Apache Camel — это платформы с открытым исходным кодом, обеспечивающие более простое решение проблем интеграции на предприятии, если ссылаться на их соответствующие веб-сайты:
Apache Camel —
Apache Camel — это мощная интегрированная среда с открытым исходным кодом, основанная на известных корпоративных шаблонах интеграции с мощной интеграцией компонентов.
Весенняя интеграция —
Он обеспечивает расширение модели программирования Spring для поддержки хорошо известных шаблонов корпоративной интеграции, опираясь на существующую поддержку Spring Framework для интеграции предприятия.
По сути Spring Integration и Apache Camel позволяют приложениям интегрироваться с другими системами.
Эта статья призвана обеспечить реализацию проблемы интеграции с использованием Spring Integration и Apache Camel. Цель состоит в том, чтобы показать, как легко использовать эти инфраструктуры для решения довольно сложной проблемы интеграции, и рекомендовать любой из этих замечательных продуктов для решения следующей задачи интеграции.
Проблема:
Чтобы проиллюстрировать использование этих структур, рассмотрим простой сценарий интеграции, описанный с использованием терминологии EIP:
Прикладная программа должна получить «Отчет» путем агрегирования «Разделов» из службы XML XML по разделу. Каждый запрос на отчет состоит из набора запросов на разделы — в этом конкретном примере есть запросы на три раздела, верхний и нижний колонтитулы. Служба XML через http возвращает раздел для запроса раздела. Ответы должны быть объединены в один отчет. Пример теста для этого сценария имеет следующий тип:
ReportGenerator reportGenerator = reportGeneratorFactory.createReportGenerator();
List<SectionRequest> sectionRequests = new ArrayList<SectionRequest>();
String entityId="A Company";
sectionRequests.add(new SectionRequest(entityId,"header"));
sectionRequests.add(new SectionRequest(entityId,"body"));
sectionRequests.add(new SectionRequest(entityId,"footer"));
ReportRequest reportRequest = new ReportRequest(sectionRequests);
Report report = reportGenerator.generateReport(reportRequest);
List<Section> sectionOfReport = report.getSections();
System.out.println(report);
assertEquals(3, sectionOfReport.size());
«ReportGenerator» — это шлюз обмена сообщениями, скрывающий детали базовой инфраструктуры обмена сообщениями, а в данном конкретном случае и API интеграции — Apache Camel или Spring Integration. Для начала давайте реализуем решение этой проблемы интеграции, используя Spring Integration в качестве платформы, а затем Apache Camel. Полный рабочий код с использованием Spring Integration и Apache Camel также доступен в статье.
Решение с использованием Spring Integration:
Компонент Gateway легко настраивается с помощью следующей записи в Spring Configuration. Внутренне Spring Integration использует AOP для подключения компонента, который направляет запросы из внутреннего входного канала и ожидает ответа в ответном канале.
<si:gateway default-reply-channel="exit" default-request-channel="enter" id="reportGenerator" service-interface="org.bk.report.ReportGenerator">
</si:gateway>
Компонент для разделения запроса входного отчета на запрос раздела довольно прост:
public class SectionRequestSplitter {
public List split(ReportRequest reportRequest){
return reportRequest.getSectionRequests();
}
}
и подключить этот сплиттер с помощью Spring Integration:
<bean class="org.bk.report.common.SectionRequestSplitter" id="sectionRequestSplitterBean">
<si:splitter id="sectionRequestSplitter" input-channel="enter" method="split" output-channel="sectionRequestToXMLChannel" ref="sectionRequestSplitterBean">
</si:splitter></bean>
Затем, чтобы преобразовать Запрос Раздела в формат XML — Компонент является следующим:
public class SectionRequestToXMLTransformer {
public String transform(SectionRequest sectionRequest){
//this needs to be optimized...purely for demonstration of the concept
String sectionRequestAsString = "<section><meta><entityId>" + sectionRequest.getEntityId()
+ "</entityId><sectionName>" + sectionRequest.getSectionId()
+ "</sectionName></meta></section>";
return sectionRequestAsString;
}
}
и подключается в файле конфигурации Spring Integration следующим образом:
<bean id="sectionRequestToXMLBean" class="org.bk.report.common.SectionRequestToXMLTransformer"/>
<si:transformer input-channel="sectionRequestToXMLChannel" ref="sectionRequestToXMLBean" method="transform" output-channel="sectionRequestChannel"/>
Чтобы отправить XML-запрос через http с помощью XML-запроса раздела в службу раздела:
<http:outbound-gateway id="httpHeaderGateway"
request-channel="sectionRequestChannel" reply-channel="sectionResponseChannel"
default-url="${sectionBaseURL}/section" extract-request-payload="true"
charset="UTF-8" request-timeout="1200" />
Чтобы преобразовать XML-код ответа секции в объект секции — Компонент имеет следующий вид:
public class SectionResponseXMLToSectionTransformer {
public Section transform(String sectionXML) {
SAXReader saxReader = new SAXReader();
Document document;
String sectionName = "";
String entityId = "";
try {
document = saxReader.read(new StringReader(sectionXML));
sectionName = document
.selectSingleNode("/section/meta/sectionName").getText();
entityId = document.selectSingleNode("/section/meta/entityId")
.getText();
} catch (DocumentException e) {
e.printStackTrace();
}
return new Section(entityId, sectionName, sectionXML);
}
}
и подключается в файле конфигурации Spring Integration следующим образом:
<bean id="sectionResponseXMLToSectionBean" class="org.bk.report.common.SectionResponseXMLToSectionTransformer" />
<si:transformer input-channel="sectionXMLResponseChannel"
ref="sectionResponseXMLToSectionBean" method="transform" output-channel="sectionResponseChannel" />
Чтобы объединить разделы в отчет, компонент имеет следующий вид:
public class SectionResponseAggregator {
public Report aggregate(List<Section> sections) {
return new Report(sections);
}
}
и подключается в файле конфигурации Spring Integration следующим образом:
<bean id="sectionResponseAggregator" class="org.bk.report.common.SectionResponseAggregator"/>
<si:aggregator input-channel="sectionResponseChannel" output-channel="exit" ref="sectionResponseAggregator" method="aggregate"/>
Это завершает реализацию Spring Integration для этой проблемы интеграции. Ниже приведен полный файл конфигурации Spring Integration:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:si="http://www.springframework.org/schema/integration"
xmlns:http="http://www.springframework.org/schema/integration/http"
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://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-1.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http-1.0.xsd
">
<context:property-placeholder />
<si:channel id="enter" />
<si:channel id="exit" />
<si:gateway id="reportGenerator" default-request-channel="enter"
default-reply-channel="exit" service-interface="org.bk.report.ReportGenerator" />
<si:channel id="sectionRequestToXMLChannel" />
<si:splitter id="sectionRequestSplitter" input-channel="enter"
ref="sectionRequestSplitterBean" method="split" output-channel="sectionRequestToXMLChannel" />
<si:channel id="sectionRequestChannel" />
<si:transformer input-channel="sectionRequestToXMLChannel"
ref="sectionRequestToXMLBean" method="transform" output-channel="sectionRequestChannel" />
<si:channel id="sectionXMLResponseChannel" />
<http:outbound-gateway id="httpHeaderGateway"
request-channel="sectionRequestChannel" reply-channel="sectionXMLResponseChannel"
default-url="${sectionBaseURL}/section" extract-request-payload="true"
charset="UTF-8" request-timeout="1200" />
<si:channel id="sectionResponseChannel" />
<si:transformer input-channel="sectionXMLResponseChannel"
ref="sectionResponseXMLToSectionBean" method="transform" output-channel="sectionResponseChannel" />
<si:aggregator input-channel="sectionResponseChannel"
output-channel="exit" ref="sectionResponseAggregator" method="aggregate" />
<bean id="sectionRequestSplitterBean" class="org.bk.report.common.SectionRequestSplitter" />
<bean id="sectionRequestToXMLBean" class="org.bk.report.common.SectionRequestToXMLTransformer" />
<bean id="sectionResponseXMLToSectionBean" class="org.bk.report.common.SectionResponseXMLToSectionTransformer" />
<bean id="sectionResponseAggregator" class="org.bk.report.common.SectionResponseAggregator" />
</beans>
Рабочий образец предоставляется вместе со статьей (скачать, распаковать и запустить «mvn test»)
Решение с использованием Apache Camel:
Apache Camel позволяет определять маршрут с использованием нескольких реализаций DSL — Java DSL, Scala DSL и DSL на основе XML. Рекомендуемый подход заключается в использовании Spring CamelContext в качестве среды выполнения и Java DSL для разработки маршрутов. Ниже приведено построение контекста Spring Camel:
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<template id="camelTemplate" />
<routeBuilder ref="routeBuilder"/>
</camelContext>
Маршрут настраивается DSL на основе Java:
public class CamelRouteBuilder extends RouteBuilder {
private String serviceURL;
@Override
public void configure() throws Exception {
from("direct:start")
.split().method("sectionRequestSplitterBean", "split")
.aggregationStrategy(new ReportAggregationStrategy())
.transform().method("sectionRequestToXMLBean", "transform")
.to(serviceURL)
.transform().method("sectionResponseXMLToSectionBean", "transform");
}
public void setServiceURL(String serviceURL) {
this.serviceURL = serviceURL;
}
}
Apache Camel не предоставляет встроенной функции шлюза сообщений, однако довольно легко создать компонент-обертку, который может скрывать основные детали следующим образом:
Reader davsclaus предоставил ссылки на два механизма с Apache Camel для предоставления готового шлюза обмена сообщениями — Messaging Gateway EIP и Camel Proxy, который позволяет использовать POJO в качестве шлюза обмена сообщениями.
Camel Proxy будет использоваться со статьей и может быть настроен в файлах конфигурации Camel следующим образом:
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <proxy id="consumerMessageGateway" serviceInterface="org.bk.report.ReportGenerator" serviceUrl="direct:start" /> <template id="camelTemplate" /> <routeBuilder ref="routeBuilder" /> </camelContext>
В davsclaus, есть ошибка в Apache Camel (версии 2.1 или старше) при вызове bean-компонента позже на маршруте (bean-сплиттера), который должен быть исправлен в Apache Camel 2.2. Чтобы обойти эту ошибку, на пути будет представлен шаг convertBody:
from("direct:start")
.convertBodyTo(ReportRequest.class)
.split(bean("sectionRequestSplitterBean", "split"), new ReportAggregationStrategy())
.transform().method("sectionRequestToXMLBean", "transform")
.to(serviceURL)
.transform().method("sectionResponseXMLToSectionBean", "transform");
Компонент для разделения запроса входного отчета на запрос раздела точно такой же, как компонент Spring Integration:
public class SectionRequestSplitter {
public List<SectionRequest> split(ReportRequest reportRequest){
return reportRequest.getSectionRequests();
}
}
Чтобы подключить компонент с Apache Camel:
<bean id="sectionRequestSplitterBean" class="org.bk.report.si.SectionRequestSplitter" />
from("direct:start")
.split().method("sectionRequestSplitterBean", "split")
....
Далее, чтобы преобразовать Запрос Раздела в формат XML, снова это точно так же, как реализация для Spring Integration, с ловушкой, предоставляемой следующим образом:
......
.transform().method("sectionRequestToXMLBean", "transform")
......
Чтобы отправить XML-запрос через http с помощью XML-запроса раздела в службу раздела:
......
.transform().method("sectionRequestToXMLBean", "transform")
.to(serviceURL)
.........
Чтобы преобразовать XML ответа секции в объект секции, компонент точно такой же, как тот, который используется в Spring Integration, со следующим выделенным хуком на маршруте Camel:
......
.transform().method("sectionResponseXMLToSectionBean", "transform");
Чтобы объединить ответы Раздела в отчет, этот компонент немного сложнее, чем Spring Integration. Apache Camel поддерживает шаблон Scatter / Gather, используя маршрут следующего типа:
......
.split().method("sectionRequestSplitterBean", "split")
.aggregationStrategy(new ReportAggregationStrategy())
с передачей стратегии агрегации в Splitter, реализация стратегии агрегации выглядит следующим образом:
public class ReportAggregationStrategy implements AggregationStrategy {
@Override
public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
if (oldExchange == null) {
Section section = newExchange.getIn().getBody(Section.class);
Report report = new Report();
report.addSection(section);
newExchange.getIn().setBody(report);
return newExchange;
}
Report report = oldExchange.getIn().getBody(Report.class);
Section section = newExchange.getIn().getBody(Section.class);
report.addSection(section);
oldExchange.getIn().setBody(report);
return oldExchange;
}
}
Это завершает реализацию на основе Apache Camel. В статье приведен рабочий образец для Camel — просто скачайте, распакуйте и запустите «mvn test».
Вывод:
Spring Integration и Apache Camel обеспечивают простой и понятный подход к проблемам интеграции в типичном предприятии. Это легковесные фреймворки — Spring Integration основывается на портфеле Spring и расширяет привычную модель программирования для домена Integration и легко выбирается; Apache camel предоставляет хороший DSL на основе Java и хорошо интегрируется с Spring Core, с довольно щадящим обучением кривая. Статья не рекомендует один продукт по сравнению с другим, но призывает читателя оценить и изучить обе эти основы.
Рекомендации:
Веб-сайт Spring Integration: http://www.springsource.org/spring-integration
Веб-сайт
Apache Camel:
http://camel.apache.org/
Справочник по интеграции Spring:
http://static.springsource.org/spring-integration/reference /htmlsingle/spring-integration-reference.html
Руководство пользователя Apache Camel:
http://camel.apache.org/user-guide.html
Плагин для моего блога:
http://biju-allandsundry.blogspot.com/