Vzory integrácie s Apache Camel

1. Prehľad

Tento článok sa bude venovať niektorým základným modelom podnikovej integrácie (EIP) podporovaným serverom Apache Camel. Vzory integrácie pomáhajú poskytovaním riešení pre štandardizované spôsoby integrácie systémov.

Ak si potrebujete najskôr prečítať základné informácie o aplikácii Apache Camel, rozhodne navštívte tento článok, kde si oprášte základné informácie.

2. Informácie o EIP

Podnikové integračné vzory sú návrhové vzory, ktorých cieľom je poskytnúť riešenia pre integračné výzvy. Camel poskytuje implementácie pre mnohé z týchto vzorov. Celý zoznam podporovaných vzorov nájdete na tomto odkaze.

V tomto článku sa budeme zaoberať vzormi integrácie smerovača založeného na obsahu, prekladača správ, multicastu, rozdeľovača a mŕtveho písmena.

2. Router založený na obsahu

Content Based Router je smerovač správ, ktorý smeruje správu do jej cieľa na základe hlavičky správy, časti užitočného zaťaženia alebo v podstate čohokoľvek z výmeny správ, čo považujeme za obsah.

Začína sa to výber () Vyhlásenie DSL nasledované jedným alebo viacerými kedy() Vyhlásenia DSL. Každý kedy() obsahuje predikátový výraz, ktorý, ak je splnený, bude mať za následok vykonanie obsiahnutých krokov spracovania.

Ilustrujme tento EIP definovaním cesty, ktorá spotrebúva súbory z jedného priečinka a presúva ich do dvoch rôznych priečinkov v závislosti od prípony súboru. Na našu cestu sa odkazuje v súbore Spring XML pomocou vlastnej syntaxe XML pre Camel:

Definícia trasy je obsiahnutá v ContentBasedFileRouter trieda, kde sú súbory smerované zo zdrojového priečinka do dvoch rôznych cieľových priečinkov v závislosti od ich prípony.

Prípadne by sme tu mohli použiť Spring Java config prístup na rozdiel od použitia Spring XML súboru. Aby sme to dosiahli, musíme do nášho projektu pridať ďalšiu závislosť:

 org.apache.camel ťava-jar-javaconfig 2.18.1 

Najnovšiu verziu artefaktu nájdete tu.

Potom musíme predĺžiť CamelConfiguration triedy a prepísať trasy () metóda, ktorá bude odkazovať ContentBasedFileRouter:

@Configuration verejná trieda ContentBasedFileRouterConfig rozširuje CamelConfiguration {@Bean ContentBasedFileRouter getContentBasedFileRouter () {vrátiť nový ContentBasedFileRouter (); } @Override public List routes () {return Arrays.asList (getContentBasedFileRouter ()); }}

Rozšírenie sa vyhodnocuje pomocou jazyka Simple Expression Language cez jednoduché() Príkaz DSL, ktorý sa mal použiť na hodnotenie výrazov a predikátov:

verejná trieda ContentBasedFileRouter rozširuje RouteBuilder {private static final String SOURCE_FOLDER = "src / test / source-folder"; private static final String DESTINATION_FOLDER_TXT = "src / test / destination-folder-txt"; private static final String DESTINATION_FOLDER_OTHER = "src / test / destination-folder-other"; @Override public void configure () vyvolá výnimku {from ("file: //" + SOURCE_FOLDER + "? Delete = true"). Choice () .when (simple ("$ {file: ext} == 'txt'" )) .to ("súbor: //" + DESTINATION_FOLDER_TXT). inak () .to ("súbor: //" + DESTINATION_FOLDER_OTHER); }}

Tu navyše používame inak() Príkaz DSL, aby sa smerovali všetky správy, ktoré nevyhovujú predikátom uvedeným v kedy() Vyhlásenia.

3. Prekladač správ

Pretože každý systém používa svoj vlastný dátový formát, je často potrebné preložiť správu prichádzajúcu z iného systému do dátového formátu podporovaného cieľovým systémom.

Camel podporuje Prekladateľ správ router, ktorý nám umožňuje transformovať správy pomocou vlastného procesora v smerovacej logike, pomocou špecifickej fazule na vykonanie transformácie alebo pomocou transformovať () Vyhlásenie DSL.

Príklad s použitím vlastného procesora je možné nájsť v predchádzajúcom článku, kde sme definovali procesor, ktorý pred každým súborom prichádzajúceho súboru pridá časovú značku.

Poďme si teraz demonštrovať, ako používať Prekladač správ pomocou transformovať () vyhlásenie:

verejná trieda MessageTranslatorFileRouter rozširuje 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 () vyvolá výnimku {from ("file: //" + SOURCE_FOLDER + "? Delete = true") .transform (body (). Append (header (Exchange.FILE_NAME))) .to ("file : // "+ DESTINATION_FOLDER); }}

V tomto príklade pripájame názov súboru k obsahu súboru pomocou transformovať () príkaz pre každý súbor zo zdrojového priečinka a presunutie transformovaných súborov do cieľového priečinka.

4. Multicast

Multicast nám to umožňuje nasmerovať tú istú správu na súbor rôznych koncových bodov a spracovať ich iným spôsobom.

To je možné pomocou multicast () Vyhlásenie DSL a potom uvedením koncových bodov a krokov spracovania v nich.

Štandardne sa spracovanie na rôznych koncových bodoch nevykonáva paralelne, ale je možné to zmeniť použitím parallelProcessing () Vyhlásenie DSL.

Camel predvolene použije poslednú odpoveď ako odchádzajúcu správu po multicastoch. Je však možné definovať inú agregačnú stratégiu, ktorá sa použije na zostavenie odpovedí z multicastov.

Pozrime sa, ako vyzerá Multicast EIP na príklade. Súbory viacnásobného vysielania zo zdrojového priečinka rozdelíme na dve rôzne cesty, kde ich obsah transformujeme a pošleme do rôznych cieľových priečinkov. Tu používame priamy: komponent, ktorý nám umožňuje spojiť dve trasy dohromady:

verejná trieda MulticastFileRouter rozširuje RouteBuilder {private static final String SOURCE_FOLDER = "src / test / source-folder"; private static final String DESTINATION_FOLDER_WORLD = "src / test / destination-folder-world"; private static final String DESTINATION_FOLDER_HELLO = "src / test / destination-folder-hello"; @ Override public void configure () vyvolá výnimku {from ("file: //" + SOURCE_FOLDER + "? Delete = true") .multicast () .to ("direct: append", "direct: prepend"). End ( ); from ("direct: append") .transform (body (). append ("World")) .to ("file: //" + DESTINATION_FOLDER_WORLD); from ("direct: prepend") .transform (body (). prepend ("Hello")) .to ("file: //" + DESTINATION_FOLDER_HELLO); }}

5. Splitter

Rozdeľovač nám to umožňuje rozdeliť prichádzajúcu správu na niekoľko častí a každú z nich spracovať jednotlivo. To je možné pomocou split () Vyhlásenie DSL.

Na rozdiel od Multicastu, Splitter zmení prichádzajúcu správu, zatiaľ čo Multicast ju nechá tak, ako je.

Aby sme to demonštrovali na príklade, definujeme trasu, kde je každý riadok zo súboru rozdelený a transformovaný do samostatného súboru, ktorý je potom presunutý do iného cieľového priečinka. Každý nový súbor bude vytvorený s názvom súboru, ktorý sa rovná obsahu súboru:

verejná trieda SplitterFileRouter rozširuje 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 () vyvolá výnimku {from ("file: //" + SOURCE_FOLDER + "? Delete = true") .split (body (). ConvertToString (). Tokenize ("\ n")) .setHeader ( Exchange.FILE_NAME, body ()) .to ("súbor: //" + DESTINATION_FOLDER); }}

6. Kanál mŕtveho listu

Je bežné a malo by sa očakávať, že niekedy môžu nastať problémy, napríklad zablokovanie databázy, ktoré môže spôsobiť, že správa nebude doručená podľa očakávania. V určitých prípadoch však pomôže opakovanie s určitým oneskorením a správa sa spracuje.

Dead Letter Channel nám umožňuje kontrolovať, čo sa stane so správou, keď sa nepodarí doručiť. Pomocou kanálu mŕtveho písmena môžeme určiť, či sa má hodená výnimka rozšíriť na volajúceho a kam sa má smerovať neúspešná ústredňa.

Ak sa správu nepodarí doručiť, kanál nedoručených správ (ak sa používa) presunie správu do koncového bodu nedoručeného textu.

Ukážme si to na príklade vytvorením výnimky na trase:

public class DeadLetterChannelFileRouter rozširuje RouteBuilder {private static final String SOURCE_FOLDER = "src / test / source-folder"; @Override public void configure () vyvolá výnimku {errorHandler (deadLetterChannel ("log: dead? Level = ERROR") .maximumRedeliveries (3) .redeliveryDelay (1000) .retryAttemptedLogLevel (LoggingLevel.ERROR)); from ("file: //" + SOURCE_FOLDER + "? delete = true") .process (exchange -> {throw new IllegalArgumentException ("Exception thrown!");}); }}

Tu sme definovali errorHandler ktorá zaznamenáva neúspešné dodávky a definuje stratégiu opätovného doručenia. Nastavením retryAttemptedLogLevel (), každý pokus o opätovné doručenie bude zaznamenaný so zadanou úrovňou protokolu.

Aby to bolo úplne funkčné, musíme navyše nakonfigurovať záznamník.

Po vykonaní tohto testu sú v konzole viditeľné nasledujúce príkazy protokolu:

CHYBA DeadLetterChannel: 156 - Zlyhanie doručenia pre (MessageId: ID-ZAG0025-50922-1481340325657-0-1 na ExchangeId: ID-ZAG0025-50922-1481340325657-0-2). Pri pokuse o doručenie: 0 zachytené: java.lang.IllegalArgumentException: výnimka vyhodená! CHYBA DeadLetterChannel: 156 - zlyhalo doručenie pre (MessageId: ID-ZAG0025-50922-1481340325657-0-1 na ExchangeId: ID-ZAG0025-50922-1481340325657-0-2). Pri pokuse o doručenie: 1 zachytený: java.lang.IllegalArgumentException: výnimka vyhodená! CHYBA DeadLetterChannel: 156 - Zlyhanie doručenia pre (MessageId: ID-ZAG0025-50922-1481340325657-0-1 na ExchangeId: ID-ZAG0025-50922-1481340325657-0-2). Pri pokuse o doručenie: 2 zachytené: java.lang.IllegalArgumentException: výnimka vyhodená! CHYBA DeadLetterChannel: 156 - zlyhalo doručenie pre (MessageId: ID-ZAG0025-50922-1481340325657-0-1 na ExchangeId: ID-ZAG0025-50922-1481340325657-0-2). Pri pokuse o doručenie: 3 zachytené: java.lang.IllegalArgumentException: výnimka vyhodená! CHYBA mŕtva: 156 - Exchange [ExchangePattern: InOnly, BodyType: org.apache.camel.component.file.GenericFile, Body: [Body je založený na súbore: GenericFile [File.txt]]]

Ako si môžete všimnúť, každý pokus o opätovné doručenie sa zaznamenáva so zobrazením servera Exchange, ktorého doručenie nebolo úspešné.

7. Záver

V tomto článku sme predstavili úvod do integračných vzorov pomocou Apache Camel a demonštrovali ich na niekoľkých príkladoch.

Predviedli sme, ako tieto integračné vzory používať a prečo sú prospešné pri riešení integračných výziev.

Kód z tohto článku nájdete na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found