Spring Integration
message channels, adapters, gateways
Spring Integration
A Spring Integration abban erős, hogy a kábelezést, routingot és transzformációt emeli elsőrangú fogalommá az alkalmazásodban.
1. Definíció / Definition
Mi ez? / What is it?
A Spring Integration egy framework a Spring ökoszisztémán belül, ami az Enterprise Integration Patterns (EIP) gyakorlati megvalósítását adja. Nem broker helyett van, hanem integrációs csővezetékek, csatornák és endpointok deklaratív megépítésére.
Miért létezik? / Why does it exist?
Mert sok alkalmazásban nem az üzleti logika a nehéz rész, hanem az, hogy különböző inputokat fogadj, transzformálj, route-olj, szűrj, gazdagíts és továbbíts. Ha ezt ad hoc @Service láncokkal csinálod, gyorsan elveszik a flow átláthatósága.
Hol helyezkedik el? / Where does it fit?
A Spring Integration jó választás application integration rétegként, főleg ha file, HTTP, JDBC, JMS, mail vagy más adapterek között kell összerakni egy folyamatot. Nem ugyanaz, mint Spring Cloud Stream, és nem egyszerűen Kafka wrapper.
2. Alapfogalmak / Core Concepts
2.1 Message és channel
A központi elem a Message<?>: payload + headers. A komponensek ezeket küldik csatornákon keresztül.
| Elem | Szerep |
|---|---|
Message |
adat + metadata |
MessageChannel |
útvonal két endpoint között |
MessageHandler |
üzenet feldolgozása |
Poller |
polling alapú feldolgozás ütemezése |
2.2 Channel típusok
- DirectChannel: synchronous, ugyanazon threadben adja át az üzenetet.
- QueueChannel: bufferelt, pollinggal olvasható.
- PublishSubscribeChannel: több subscriber ugyanazt az üzenetet kapja.
Tipikus integrációs flow:
- Inbound Adapter külső rendszerből beemeli az adatot.
- Channel továbbítja az üzenetet az endpointok között.
- Transformer átalakítja a payloadot vagy metadata-t.
- Router szabály alapján kiválasztja a következő csatornát.
- Handler végrehajtja az üzleti műveletet.
2.3 Endpoint minták
A fontosabb endpointok:
ServiceActivator: üzleti metódus hívásaTransformer: payload vagy message átalakításaFilter: nem megfelelő üzenetek eldobásaRouter: másik channelre küldés szabály alapjánSplitter: egy üzenet feldarabolása több üzenettéAggregator: több üzenet összerakása eggyé
2.4 Adapterek és gateway-ek
Az adapter a külvilág és a belső flow közötti csatlakozó. Lehet inbound vagy outbound. A gateway már inkább programozói API, ami mögött flow fut.
2.5 Java DSL és IntegrationFlow
A modern Spring Integration legtöbbször IntegrationFlow DSL-lel kellemes:
- olvashatóbb, mint az XML alapú régi konfigurációk;
- könnyen komponálható;
- jó helyre teszi az EIP elemeket.
2.6 Viszony más eszközökhöz
| Megoldás | Mire jó? |
|---|---|
| Spring Integration | komplex app-on-belüli vagy adapter-alapú flow |
| Spring Cloud Stream | binder-alapú broker integráció event streaminghez |
| Plain Kafka/Rabbit | közvetlen broker API, kisebb absztrakció |
3. Gyakorlati használat / Practical Usage
Képzelj el egy rendszert, ami partner SFTP-ről file-okat vesz át, parse-olja, validálja, majd hibátlan rekordokat DB-be rak, a hibásakat pedig külön error tárolóba küldi. Ez klasszikus Spring Integration terep. Nem csak egy consumer kell, hanem komplett flow: inbound file adapter, splitter, transformer, filter, service activator, outbound JDBC adapter.
Ugyanígy jó webhook gateway-k, HTTP bejövő kérésekből belső message flow építésére, vagy akár több backend rendszer közötti „wiring” rétegként. Ha azt látod, hogy sok adaptert és sok köztes transzformációt kell karbantartanod, a Spring Integration sokkal tisztábban modellezi a problémát, mint a kézzel összedrótozott service hívások.
A PublishSubscribeChannel hasznos audit + business processing szétválasztásra. A fő feldolgozás mehet egy ágra, az audit és monitoring mellékágba. A QueueChannel jó lehet átmeneti bufferként, de fontos érteni, hogy ezzel már implicit aszinkronitást és queue semantics-et vezetsz be.
Egy másik nagyon valós production példa a content enrichment. Bejön egy partner API payload, de önmagában kevés az üzleti feldolgozáshoz. A flow egyik lépése lekéri a referenciaadatokat JDBC-n vagy HTTP-n keresztül, majd a Transformer vagy ServiceActivator kiegészíti a message-et. Ezután Filter eldöntheti, hogy az enriched adat még mindig feldolgozható-e, vagy inkább quarantine/error channelre menjen.
Sok csapat ott szeret bele a Spring Integrationbe, amikor rájön, hogy a "mellékes" integrációs logika igazából önálló termékkomplexitás. Batch boundary-k, duplicate detection, throttling, retry branch, manuális újrajátszás: ezek nem kényelmesen kezelhető dolgok sima service metódusokban. Ha a flow diagramként értelmezhető, gyakran jobb, ha a kód is flow-ként van megírva.
4. Kód példák / Code Examples
4.1 HTTP inbound gateway és feldolgozó flow
@Configuration
@EnableIntegration
class OrderIntegrationConfig {
@Bean
IntegrationFlow orderHttpFlow(OrderProcessingService service) {
return IntegrationFlow
.from(Http.inboundGateway("/api/orders")
.requestMapping(mapping -> mapping.methods(HttpMethod.POST))
.requestPayloadType(OrderRequest.class))
.transform(OrderRequest.class, req -> new ValidatedOrder(req.customerId(), req.items()))
.handle(service, "process")
.get();
}
}
record OrderRequest(String customerId, List<String> items) {}
record ValidatedOrder(String customerId, List<String> items) {}
4.2 Router és külön channelök
@Bean
IntegrationFlow paymentRoutingFlow() {
return IntegrationFlow.from("paymentInputChannel")
.<PaymentMessage, String>route(PaymentMessage::type,
mapping -> mapping
.channelMapping("CARD", "cardChannel")
.channelMapping("BANK_TRANSFER", "bankTransferChannel"))
.get();
}
@Bean
@ServiceActivator(inputChannel = "cardChannel")
MessageHandler cardHandler() {
return message -> System.out.println("Card payment: " + message.getPayload());
}
4.3 File adapter + splitter + aggregator
@Bean
IntegrationFlow importFileFlow(FileImportService service) {
return IntegrationFlow.from(Files.inboundAdapter(new File("input"))
.patternFilter("*.csv"),
c -> c.poller(Pollers.fixedDelay(5000)))
.transform(File.class, service::readLines)
.split()
.filter(String.class, line -> !line.isBlank())
.transform(service::toRecord)
.aggregate()
.handle(service, "storeBatch")
.get();
}
4.4 Messaging gateway
@MessagingGateway
interface PricingGateway {
@Gateway(requestChannel = "pricingInputChannel", replyChannel = "pricingReplyChannel")
PriceQuote calculate(PriceRequest request);
}
5. Trade-offok / Trade-offs
Előnyök:
- explicit flow modellezés;
- adapter gazdag ökoszisztéma;
- EIP minták elsőrangú támogatása;
- jól szeparálható integrációs logika.
Hátrányok:
- új absztrakciós réteg, tanulási görbével;
- túlhasználva „varázslatos” lehet a fejlesztőknek;
- egyszerű use case-eknél overengineering.
Mikor használd?
- ha többféle protokoll és endpoint között kell közvetíteni;
- ha egy integrációs folyamat több transzformációból és routingból áll;
- ha EIP gondolkodással akarsz tervezni.
Mikor ne?
- ha csak egy sima Kafka consumer kell;
- ha csak két service között van egyszerű REST hívás;
- ha a csapat nem fogja érteni a flow-k absztrakcióját.
6. Gyakori hibák / Common Mistakes
- Mindenre Spring Integrationt erőltetni. Nem kell minden metódushívásból channel.
- Threading modell félreértése.
DirectChannelsynchronous, míg más elemeknél már poller vagy executor viselkedés jöhet. - Header-ek elvesztése transzformációnál. Sok routing és correlation ezekre épül.
- Aggregator korreláció nélkül. Ebből könnyen memory leak vagy beragadt csoport lesz.
- Túl hosszú, egybefüggő flow. Jobb kisebb, jól elnevezett részfolyamatokra bontani.
- Monitoring hiánya. Integrációs hibák csendben torlódhatnak.
7. Senior szintű meglátások / Senior-level Insights
A Spring Integration akkor ad nagy értéket, ha az integráció önálló problématér. Ha az appodban a valódi komplexitás a „mit csinálunk az adattal”, nem pedig a „hogyan jut el A-ból B-be”, akkor lehet, hogy fölösleges.
Senior szinten a kulcskérdés az explicit boundary. Jó flow-kban világos, hol jön be külső adat, hol validálsz, hol route-olsz, hol végzel side effectet, és hol kezeled a hibát. Ez segít tesztelhetőségben és incidenseknél is.
Fontos különbség a broker-alapú eventinghez képest: Spring Integration sokszor process orchestration az alkalmazáson belül vagy közvetlen adapterek között. Spring Cloud Stream inkább broker-first szemlélet. Ha a cél egy belső integrációs pipeline, a Spring Integration lehet a tisztább választás. Ha a cél event stream publikálás bindereken keresztül, lehet, hogy nem ez lesz a legjobb fit.
Az EIP minták csak akkor hasznosak, ha a csapat közös nyelvként használja őket. A splitter, aggregator, router nem díszszavak: ezek konkrét viselkedési szerződések. Productionben ezek állapota, timeoutja, korrelációja és hibakezelése a nehéz rész.
Nagyon fontos még az is, hogy az integrációs flow ne legyen fekete doboz. Érdemes külön mérni, melyik channelen mennyi message megy át, hol nő a várakozás, milyen gyakori a retry, és melyik endpoint a szűk keresztmetszet. Egy rosszul méretezett poller vagy egy túl lassú outbound adapter alattomosabban tud teljesítményproblémát okozni, mint egy sima REST controller, mert a torlódás nem mindig látszik rögtön a user felé.
8. Szószedet / Glossary
- Message: payload és header együtt.
- Channel: csatorna endpointok között.
- Adapter: külső rendszer csatlakozója.
- Gateway: programozói belépési pont message flow-hoz.
- Router: üzenet irányítása szabály alapján.
- Splitter: egy üzenet több részre bontása.
- Aggregator: részüzenetek összegyűjtése és egyesítése.
- Poller: polling alapú endpoint futtatási mechanizmusa.
- EIP: Enterprise Integration Patterns gyűjteménye.
9. Gyorsreferencia / Cheatsheet
| Elem | Mire jó? | Tipikus buktató |
|---|---|---|
DirectChannel |
sync átadás | blokkolsz észrevétlenül |
QueueChannel |
buffer | polling és backpressure |
PublishSubscribeChannel |
fan-out | mellékhatások szétcsúszása |
Transformer |
adatátalakítás | header-vesztés |
Router |
útvonalválasztás | hiányzó default ág |
Splitter |
feldarabolás | túl sok rész üzenet |
Aggregator |
összefűzés | rossz correlation |
@MessagingGateway |
kényelmes API | rejtett async komplexitás |
🎮 Játékok
8 kérdés