From 056b17aaa7e3bd50de44cad5384ceacbbc0f63ef Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Fri, 20 Mar 2015 19:49:13 +0200 Subject: [PATCH] INT-3197: Docs to AsciiDoc from DocBook JIRA: https://jira.spring.io/browse/INT-3197 Polishing Various glitches. Fix Table of Contents Polishing - Various Glitches More Polishing - Fixes for issues found by side-by-side comparison of htmlsingle output. Fix Table Formats for PDF More Polishing - PR Comments More Polishing - Bad Titles More Polishing Work-Around for AsciiDoctor Problem https://github.com/asciidoctor/asciidoctor/issues/1297 Use a blank line between includes rather than a comment at the end of include files that end with a callout. Remove Unresolved qName Entries Fix Overview PDF Image Sizes Highlight Schema Imports More Image Fixes INT-3197: Port DocBook Changes Since Conversion Remove DocBook Files --- build.gradle | 37 +- src/reference/asciidoc/aggregator.adoc | 764 ++++++ src/reference/asciidoc/amqp.adoc | 662 ++++++ src/reference/asciidoc/bridge.adoc | 52 + src/reference/asciidoc/chain.adoc | 161 ++ src/reference/asciidoc/changes-1.0-2.0.adoc | 178 ++ src/reference/asciidoc/changes-2.0-2.1.adoc | 220 ++ src/reference/asciidoc/changes-2.1-2.2.adoc | 175 ++ src/reference/asciidoc/changes-2.2-3.0.adoc | 421 ++++ src/reference/asciidoc/changes-3.0-4.0.adoc | 262 +++ src/reference/asciidoc/changes-4.0-4.1.adoc | 225 ++ src/reference/asciidoc/changes-4.1-4.2.adoc | 4 + src/reference/asciidoc/channel-adapter.adoc | 142 ++ src/reference/asciidoc/channel.adoc | 788 +++++++ src/reference/asciidoc/claim-check.adoc | 214 ++ src/reference/asciidoc/configuration.adoc | 745 ++++++ .../asciidoc/content-enrichment.adoc | 386 +++ src/reference/asciidoc/control-bus.adoc | 33 + src/reference/asciidoc/delayer.adoc | 131 ++ src/reference/asciidoc/endpoint-summary.adoc | 594 +++++ src/reference/asciidoc/endpoint.adoc | 566 +++++ src/reference/asciidoc/event.adoc | 67 + src/reference/asciidoc/feed.adoc | 57 + src/reference/asciidoc/file.adoc | 436 ++++ src/reference/asciidoc/filter.adoc | 163 ++ src/reference/asciidoc/ftp.adoc | 480 ++++ src/reference/asciidoc/gateway.adoc | 581 +++++ src/reference/asciidoc/gemfire.adoc | 223 ++ src/reference/asciidoc/groovy.adoc | 96 + src/reference/asciidoc/handler-advice.adoc | 620 +++++ src/reference/asciidoc/history.adoc | 17 + src/reference/asciidoc/http.adoc | 759 ++++++ .../images/bank-router.jpg | Bin .../{docbook => asciidoc}/images/cafe-eip.png | Bin .../{docbook => asciidoc}/images/chain.png | Bin .../{docbook => asciidoc}/images/channel.jpg | Bin .../{docbook => asciidoc}/images/gateway.jpg | Bin .../images/handler-endpoint.jpg | Bin .../images/http-inbound-gateway-pdf.png | Bin .../images/http-inbound-gateway.png | Bin .../images/http-outbound-gateway-pdf.png | Bin .../images/http-outbound-gateway.png | Bin .../images/loan-broker-eip.png | Bin .../{docbook => asciidoc}/images/message.jpg | Bin .../images/quotes-aggregator.jpg | Bin .../{docbook => asciidoc}/images/router.jpg | Bin .../images/source-endpoint.jpg | Bin .../spring-integration-amqp-sample-graph.png | Bin .../images/target-endpoint.jpg | Bin .../{docbook => asciidoc}/images/tickmark.png | Bin src/reference/asciidoc/index-docinfo.xml | 62 + src/reference/asciidoc/index.adoc | 130 ++ src/reference/asciidoc/ip.adoc | 1360 +++++++++++ src/reference/asciidoc/jdbc.adoc | 925 ++++++++ src/reference/asciidoc/jms.adoc | 540 +++++ src/reference/asciidoc/jmx.adoc | 578 +++++ src/reference/asciidoc/jpa.adoc | 1016 ++++++++ src/reference/asciidoc/logging-adapter.adoc | 42 + src/reference/asciidoc/mail.adoc | 345 +++ .../asciidoc/message-construction.adoc | 4 + src/reference/asciidoc/message-history.adoc | 82 + .../asciidoc/message-publishing.adoc | 341 +++ src/reference/asciidoc/message-routing.adoc | 18 + src/reference/asciidoc/message-store.adoc | 85 + .../asciidoc/message-transformation.adoc | 9 + src/reference/asciidoc/message.adoc | 463 ++++ .../asciidoc/messaging-channels.adoc | 11 + .../asciidoc/messaging-endpoints.adoc | 20 + src/reference/asciidoc/meta-data-store.adoc | 58 + src/reference/asciidoc/mongodb.adoc | 260 +++ src/reference/asciidoc/mqtt.adoc | 160 ++ src/reference/asciidoc/overview.adoc | 249 ++ src/reference/asciidoc/polling-consumer.adoc | 106 + src/reference/asciidoc/preface.adoc | 60 + src/reference/asciidoc/redis.adoc | 744 ++++++ src/reference/asciidoc/resequencer.adoc | 167 ++ src/reference/asciidoc/resource.adoc | 78 + src/reference/asciidoc/resources.adoc | 8 + src/reference/asciidoc/rmi.adoc | 77 + src/reference/asciidoc/router.adoc | 1376 +++++++++++ src/reference/asciidoc/samples.adoc | 546 +++++ src/reference/asciidoc/scatter-gather.adoc | 184 ++ src/reference/asciidoc/scripting.adoc | 146 ++ src/reference/asciidoc/security.adoc | 85 + src/reference/asciidoc/service-activator.adoc | 108 + src/reference/asciidoc/sftp.adoc | 511 ++++ src/reference/asciidoc/shutdown.adoc | 38 + src/reference/asciidoc/spel.adoc | 164 ++ src/reference/asciidoc/splitter.adoc | 128 + src/reference/asciidoc/stream.adoc | 95 + src/reference/asciidoc/stylesheets/golo.css | 677 ++++++ src/reference/asciidoc/syslog.adoc | 123 + src/reference/asciidoc/system-management.adoc | 16 + src/reference/asciidoc/transactions.adoc | 222 ++ src/reference/asciidoc/transformer.adoc | 384 +++ src/reference/asciidoc/twitter.adoc | 330 +++ src/reference/asciidoc/web-sockets.adoc | 408 ++++ src/reference/asciidoc/whats-new.adoc | 89 + src/reference/asciidoc/ws.adoc | 149 ++ src/reference/asciidoc/xml.adoc | 1054 +++++++++ src/reference/asciidoc/xmpp.adoc | 221 ++ src/reference/docbook/aggregator.xml | 1027 -------- src/reference/docbook/amqp.xml | 830 ------- src/reference/docbook/bridge.xml | 59 - src/reference/docbook/chain.xml | 215 -- src/reference/docbook/changes-1.0-2.0.xml | 247 -- src/reference/docbook/changes-2.0-2.1.xml | 325 --- src/reference/docbook/changes-2.1-2.2.xml | 237 -- src/reference/docbook/changes-2.2-3.0.xml | 676 ------ src/reference/docbook/changes-3.0-4.0.xml | 376 --- src/reference/docbook/changes-4.0-4.1.xml | 312 --- src/reference/docbook/changes-4.1-4.2.xml | 9 - src/reference/docbook/channel-adapter.xml | 172 -- src/reference/docbook/channel.xml | 918 -------- src/reference/docbook/claim-check.xml | 265 --- src/reference/docbook/configuration.xml | 735 ------ src/reference/docbook/content-enrichment.xml | 596 ----- src/reference/docbook/control-bus.xml | 48 - src/reference/docbook/delayer.xml | 159 -- src/reference/docbook/endpoint-summary.xml | 241 -- src/reference/docbook/endpoint.xml | 742 ------ src/reference/docbook/event.xml | 77 - src/reference/docbook/feed.xml | 73 - src/reference/docbook/file.xml | 571 ----- src/reference/docbook/filter.xml | 173 -- src/reference/docbook/ftp.xml | 658 ------ src/reference/docbook/gateway.xml | 728 ------ src/reference/docbook/gemfire.xml | 243 -- src/reference/docbook/groovy.xml | 125 - src/reference/docbook/handler-advice.xml | 758 ------ src/reference/docbook/history.xml | 15 - src/reference/docbook/http.xml | 986 -------- src/reference/docbook/index.xml | 167 -- src/reference/docbook/ip.xml | 2079 ----------------- src/reference/docbook/jdbc.xml | 1341 ----------- src/reference/docbook/jms.xml | 782 ------- src/reference/docbook/jmx.xml | 891 ------- src/reference/docbook/jpa.xml | 1432 ------------ src/reference/docbook/logging-adapter.xml | 70 - src/reference/docbook/mail.xml | 374 --- .../docbook/message-construction.xml | 9 - src/reference/docbook/message-history.xml | 84 - src/reference/docbook/message-publishing.xml | 384 --- src/reference/docbook/message-routing.xml | 15 - src/reference/docbook/message-store.xml | 128 - .../docbook/message-transformation.xml | 10 - src/reference/docbook/message.xml | 335 --- src/reference/docbook/messaging-channels.xml | 12 - src/reference/docbook/messaging-endpoints.xml | 16 - src/reference/docbook/meta-data-store.xml | 78 - src/reference/docbook/mongodb.xml | 357 --- src/reference/docbook/mqtt.xml | 210 -- src/reference/docbook/overview.xml | 410 ---- src/reference/docbook/polling-consumer.xml | 148 -- src/reference/docbook/preface.xml | 87 - src/reference/docbook/redis.xml | 967 -------- src/reference/docbook/resequencer.xml | 216 -- src/reference/docbook/resource.xml | 95 - src/reference/docbook/resources.xml | 17 - src/reference/docbook/rmi.xml | 71 - src/reference/docbook/router.xml | 1241 ---------- src/reference/docbook/samples.xml | 713 ------ src/reference/docbook/scatter-gather.xml | 239 -- src/reference/docbook/scripting.xml | 156 -- src/reference/docbook/security.xml | 96 - src/reference/docbook/service-activator.xml | 121 - src/reference/docbook/sftp.xml | 706 ------ src/reference/docbook/shutdown.xml | 70 - src/reference/docbook/spel.xml | 239 -- src/reference/docbook/splitter.xml | 192 -- src/reference/docbook/stream.xml | 93 - src/reference/docbook/syslog.xml | 148 -- src/reference/docbook/system-management.xml | 14 - src/reference/docbook/transactions.xml | 301 --- src/reference/docbook/transformer.xml | 431 ---- src/reference/docbook/twitter.xml | 403 ---- src/reference/docbook/web-sockets.xml | 621 ----- src/reference/docbook/whats-new.xml | 131 -- src/reference/docbook/ws.xml | 179 -- src/reference/docbook/xml.xml | 1396 ----------- src/reference/docbook/xmpp.xml | 259 -- 181 files changed, 25308 insertions(+), 31133 deletions(-) create mode 100644 src/reference/asciidoc/aggregator.adoc create mode 100644 src/reference/asciidoc/amqp.adoc create mode 100644 src/reference/asciidoc/bridge.adoc create mode 100644 src/reference/asciidoc/chain.adoc create mode 100644 src/reference/asciidoc/changes-1.0-2.0.adoc create mode 100644 src/reference/asciidoc/changes-2.0-2.1.adoc create mode 100644 src/reference/asciidoc/changes-2.1-2.2.adoc create mode 100644 src/reference/asciidoc/changes-2.2-3.0.adoc create mode 100644 src/reference/asciidoc/changes-3.0-4.0.adoc create mode 100644 src/reference/asciidoc/changes-4.0-4.1.adoc create mode 100644 src/reference/asciidoc/changes-4.1-4.2.adoc create mode 100644 src/reference/asciidoc/channel-adapter.adoc create mode 100644 src/reference/asciidoc/channel.adoc create mode 100644 src/reference/asciidoc/claim-check.adoc create mode 100644 src/reference/asciidoc/configuration.adoc create mode 100644 src/reference/asciidoc/content-enrichment.adoc create mode 100644 src/reference/asciidoc/control-bus.adoc create mode 100644 src/reference/asciidoc/delayer.adoc create mode 100644 src/reference/asciidoc/endpoint-summary.adoc create mode 100644 src/reference/asciidoc/endpoint.adoc create mode 100644 src/reference/asciidoc/event.adoc create mode 100644 src/reference/asciidoc/feed.adoc create mode 100644 src/reference/asciidoc/file.adoc create mode 100644 src/reference/asciidoc/filter.adoc create mode 100644 src/reference/asciidoc/ftp.adoc create mode 100644 src/reference/asciidoc/gateway.adoc create mode 100644 src/reference/asciidoc/gemfire.adoc create mode 100644 src/reference/asciidoc/groovy.adoc create mode 100644 src/reference/asciidoc/handler-advice.adoc create mode 100644 src/reference/asciidoc/history.adoc create mode 100644 src/reference/asciidoc/http.adoc rename src/reference/{docbook => asciidoc}/images/bank-router.jpg (100%) rename src/reference/{docbook => asciidoc}/images/cafe-eip.png (100%) rename src/reference/{docbook => asciidoc}/images/chain.png (100%) rename src/reference/{docbook => asciidoc}/images/channel.jpg (100%) rename src/reference/{docbook => asciidoc}/images/gateway.jpg (100%) rename src/reference/{docbook => asciidoc}/images/handler-endpoint.jpg (100%) rename src/reference/{docbook => asciidoc}/images/http-inbound-gateway-pdf.png (100%) rename src/reference/{docbook => asciidoc}/images/http-inbound-gateway.png (100%) rename src/reference/{docbook => asciidoc}/images/http-outbound-gateway-pdf.png (100%) rename src/reference/{docbook => asciidoc}/images/http-outbound-gateway.png (100%) rename src/reference/{docbook => asciidoc}/images/loan-broker-eip.png (100%) rename src/reference/{docbook => asciidoc}/images/message.jpg (100%) rename src/reference/{docbook => asciidoc}/images/quotes-aggregator.jpg (100%) rename src/reference/{docbook => asciidoc}/images/router.jpg (100%) rename src/reference/{docbook => asciidoc}/images/source-endpoint.jpg (100%) rename src/reference/{docbook => asciidoc}/images/spring-integration-amqp-sample-graph.png (100%) rename src/reference/{docbook => asciidoc}/images/target-endpoint.jpg (100%) rename src/reference/{docbook => asciidoc}/images/tickmark.png (100%) create mode 100644 src/reference/asciidoc/index-docinfo.xml create mode 100644 src/reference/asciidoc/index.adoc create mode 100644 src/reference/asciidoc/ip.adoc create mode 100644 src/reference/asciidoc/jdbc.adoc create mode 100644 src/reference/asciidoc/jms.adoc create mode 100644 src/reference/asciidoc/jmx.adoc create mode 100644 src/reference/asciidoc/jpa.adoc create mode 100644 src/reference/asciidoc/logging-adapter.adoc create mode 100644 src/reference/asciidoc/mail.adoc create mode 100644 src/reference/asciidoc/message-construction.adoc create mode 100644 src/reference/asciidoc/message-history.adoc create mode 100644 src/reference/asciidoc/message-publishing.adoc create mode 100644 src/reference/asciidoc/message-routing.adoc create mode 100644 src/reference/asciidoc/message-store.adoc create mode 100644 src/reference/asciidoc/message-transformation.adoc create mode 100644 src/reference/asciidoc/message.adoc create mode 100644 src/reference/asciidoc/messaging-channels.adoc create mode 100644 src/reference/asciidoc/messaging-endpoints.adoc create mode 100644 src/reference/asciidoc/meta-data-store.adoc create mode 100644 src/reference/asciidoc/mongodb.adoc create mode 100644 src/reference/asciidoc/mqtt.adoc create mode 100644 src/reference/asciidoc/overview.adoc create mode 100644 src/reference/asciidoc/polling-consumer.adoc create mode 100644 src/reference/asciidoc/preface.adoc create mode 100644 src/reference/asciidoc/redis.adoc create mode 100644 src/reference/asciidoc/resequencer.adoc create mode 100644 src/reference/asciidoc/resource.adoc create mode 100644 src/reference/asciidoc/resources.adoc create mode 100644 src/reference/asciidoc/rmi.adoc create mode 100644 src/reference/asciidoc/router.adoc create mode 100644 src/reference/asciidoc/samples.adoc create mode 100644 src/reference/asciidoc/scatter-gather.adoc create mode 100644 src/reference/asciidoc/scripting.adoc create mode 100644 src/reference/asciidoc/security.adoc create mode 100644 src/reference/asciidoc/service-activator.adoc create mode 100644 src/reference/asciidoc/sftp.adoc create mode 100644 src/reference/asciidoc/shutdown.adoc create mode 100644 src/reference/asciidoc/spel.adoc create mode 100644 src/reference/asciidoc/splitter.adoc create mode 100644 src/reference/asciidoc/stream.adoc create mode 100644 src/reference/asciidoc/stylesheets/golo.css create mode 100644 src/reference/asciidoc/syslog.adoc create mode 100644 src/reference/asciidoc/system-management.adoc create mode 100644 src/reference/asciidoc/transactions.adoc create mode 100644 src/reference/asciidoc/transformer.adoc create mode 100644 src/reference/asciidoc/twitter.adoc create mode 100644 src/reference/asciidoc/web-sockets.adoc create mode 100644 src/reference/asciidoc/whats-new.adoc create mode 100644 src/reference/asciidoc/ws.adoc create mode 100644 src/reference/asciidoc/xml.adoc create mode 100644 src/reference/asciidoc/xmpp.adoc delete mode 100644 src/reference/docbook/aggregator.xml delete mode 100644 src/reference/docbook/amqp.xml delete mode 100644 src/reference/docbook/bridge.xml delete mode 100644 src/reference/docbook/chain.xml delete mode 100644 src/reference/docbook/changes-1.0-2.0.xml delete mode 100644 src/reference/docbook/changes-2.0-2.1.xml delete mode 100644 src/reference/docbook/changes-2.1-2.2.xml delete mode 100644 src/reference/docbook/changes-2.2-3.0.xml delete mode 100644 src/reference/docbook/changes-3.0-4.0.xml delete mode 100644 src/reference/docbook/changes-4.0-4.1.xml delete mode 100644 src/reference/docbook/changes-4.1-4.2.xml delete mode 100644 src/reference/docbook/channel-adapter.xml delete mode 100644 src/reference/docbook/channel.xml delete mode 100644 src/reference/docbook/claim-check.xml delete mode 100644 src/reference/docbook/configuration.xml delete mode 100644 src/reference/docbook/content-enrichment.xml delete mode 100644 src/reference/docbook/control-bus.xml delete mode 100644 src/reference/docbook/delayer.xml delete mode 100644 src/reference/docbook/endpoint-summary.xml delete mode 100644 src/reference/docbook/endpoint.xml delete mode 100644 src/reference/docbook/event.xml delete mode 100644 src/reference/docbook/feed.xml delete mode 100644 src/reference/docbook/file.xml delete mode 100644 src/reference/docbook/filter.xml delete mode 100644 src/reference/docbook/ftp.xml delete mode 100644 src/reference/docbook/gateway.xml delete mode 100644 src/reference/docbook/gemfire.xml delete mode 100644 src/reference/docbook/groovy.xml delete mode 100644 src/reference/docbook/handler-advice.xml delete mode 100644 src/reference/docbook/history.xml delete mode 100644 src/reference/docbook/http.xml delete mode 100644 src/reference/docbook/index.xml delete mode 100644 src/reference/docbook/ip.xml delete mode 100644 src/reference/docbook/jdbc.xml delete mode 100644 src/reference/docbook/jms.xml delete mode 100644 src/reference/docbook/jmx.xml delete mode 100644 src/reference/docbook/jpa.xml delete mode 100644 src/reference/docbook/logging-adapter.xml delete mode 100644 src/reference/docbook/mail.xml delete mode 100644 src/reference/docbook/message-construction.xml delete mode 100644 src/reference/docbook/message-history.xml delete mode 100644 src/reference/docbook/message-publishing.xml delete mode 100644 src/reference/docbook/message-routing.xml delete mode 100644 src/reference/docbook/message-store.xml delete mode 100644 src/reference/docbook/message-transformation.xml delete mode 100644 src/reference/docbook/message.xml delete mode 100644 src/reference/docbook/messaging-channels.xml delete mode 100644 src/reference/docbook/messaging-endpoints.xml delete mode 100644 src/reference/docbook/meta-data-store.xml delete mode 100644 src/reference/docbook/mongodb.xml delete mode 100644 src/reference/docbook/mqtt.xml delete mode 100644 src/reference/docbook/overview.xml delete mode 100644 src/reference/docbook/polling-consumer.xml delete mode 100644 src/reference/docbook/preface.xml delete mode 100644 src/reference/docbook/redis.xml delete mode 100644 src/reference/docbook/resequencer.xml delete mode 100644 src/reference/docbook/resource.xml delete mode 100644 src/reference/docbook/resources.xml delete mode 100644 src/reference/docbook/rmi.xml delete mode 100644 src/reference/docbook/router.xml delete mode 100644 src/reference/docbook/samples.xml delete mode 100644 src/reference/docbook/scatter-gather.xml delete mode 100644 src/reference/docbook/scripting.xml delete mode 100644 src/reference/docbook/security.xml delete mode 100644 src/reference/docbook/service-activator.xml delete mode 100644 src/reference/docbook/sftp.xml delete mode 100644 src/reference/docbook/shutdown.xml delete mode 100644 src/reference/docbook/spel.xml delete mode 100644 src/reference/docbook/splitter.xml delete mode 100644 src/reference/docbook/stream.xml delete mode 100644 src/reference/docbook/syslog.xml delete mode 100644 src/reference/docbook/system-management.xml delete mode 100644 src/reference/docbook/transactions.xml delete mode 100644 src/reference/docbook/transformer.xml delete mode 100644 src/reference/docbook/twitter.xml delete mode 100644 src/reference/docbook/web-sockets.xml delete mode 100644 src/reference/docbook/whats-new.xml delete mode 100644 src/reference/docbook/ws.xml delete mode 100644 src/reference/docbook/xml.xml delete mode 100644 src/reference/docbook/xmpp.xml diff --git a/build.gradle b/build.gradle index ea81e8daf8..b770d7c30f 100644 --- a/build.gradle +++ b/build.gradle @@ -9,10 +9,13 @@ buildscript { } dependencies { classpath 'org.springframework.build.gradle:spring-io-plugin:0.0.3.RELEASE' - classpath 'org.springframework.build.gradle:docbook-reference-plugin:0.2.8' + classpath 'io.spring.gradle:docbook-reference-plugin:0.3.0' + classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.0' } } +def docsDir = 'src/reference/asciidoc' // Will be default with newer asciidoctor plugin + ext { linkHomepage = 'https://projects.spring.io/spring-integration' linkCi = 'https://build.springsource.org/browse/INT' @@ -689,12 +692,40 @@ project("spring-integration-bom") { } } -apply plugin: 'docbook-reference' +apply plugin: org.asciidoctor.gradle.AsciidoctorPlugin + +asciidoctor { + sourceDir file("$docsDir") + sourceDocumentNames = files("$docsDir/index.adoc") // Change in >= 1.5.1 + outputDir file("$buildDir/html") + backends = ['html5', 'docbook'] + logDocuments = true + options = [ + doctype: 'book', + attributes: [ + docinfo: '', + toc2: '', + 'compat-mode': '', + imagesdir: '', + stylesdir: "stylesheets/", + stylesheet: 'golo.css', + 'spring-integration-version': "$version", + 'source-highlighter': 'highlightjs' + ] + ] +} + +apply plugin: DocbookReferencePlugin reference { - sourceDir = file('src/reference/docbook') + sourceFileName = 'index.xml' + sourceDir = file("$buildDir/html") + pdfFilename = 'spring-integration-reference.pdf' + expandPlaceholders = '' } +reference.dependsOn asciidoctor + apply plugin: 'sonar-runner' sonarRunner { diff --git a/src/reference/asciidoc/aggregator.adoc b/src/reference/asciidoc/aggregator.adoc new file mode 100644 index 0000000000..9eb340fd89 --- /dev/null +++ b/src/reference/asciidoc/aggregator.adoc @@ -0,0 +1,764 @@ +[[aggregator]] +=== Aggregator + +[[aggregator-introduction]] +==== Introduction + +Basically a mirror-image of the Splitter, the Aggregator is a type of Message Handler that receives multiple Messages and combines them into a single Message. +In fact, an Aggregator is often a downstream consumer in a pipeline that includes a Splitter. + +Technically, the Aggregator is more complex than a Splitter, because it is stateful as it must hold the Messages to be aggregated and determine when the complete group of Messages is ready to be aggregated. +In order to do this it requires a `MessageStore`. + +[[aggregator-functionality]] +==== Functionality + +The Aggregator combines a group of related messages, by correlating and storing them, until the group is deemed complete. +At that point, the Aggregator will create a single message by processing the whole group, and will send the aggregated message as output. + +Implementing an Aggregator requires providing the logic to perform the aggregation (i.e., the creation of a single message from many). +Two related concepts are correlation and release. + +Correlation determines how messages are grouped for aggregation. +In Spring Integration correlation is done by default based on the `IntegrationMessageHeaderAccessor.CORRELATION_ID` message header. +Messages with the same `IntegrationMessageHeaderAccessor.CORRELATION_ID` will be grouped together. +However, the correlation strategy may be customized to allow other ways of specifying how the messages should be grouped together by implementing a `CorrelationStrategy` (see below). + +To determine the point at which a group of messages is ready to be processed, a `ReleaseStrategy` is consulted. +The default release strategy for the Aggregator will release a group when all messages included in a sequence are present, based on the `IntegrationMessageHeaderAccessor.SEQUENCE_SIZE` header. +This default strategy may be overridden by providing a reference to a custom `ReleaseStrategy` implementation. + +[[aggregator-api]] +==== Programming model + +The Aggregation API consists of a number of classes: + +* The interface `MessageGroupProcessor`, and its subclasses:`MethodInvokingAggregatingMessageGroupProcessor` and `ExpressionEvaluatingMessageGroupProcessor` + +* The `ReleaseStrategy` interface and its default implementation `SequenceSizeReleaseStrategy` + +* The `CorrelationStrategy` interface and its default implementation `HeaderAttributeCorrelationStrategy` + + + +===== AggregatingMessageHandler + +The `AggregatingMessageHandler` (subclass of `AbstractCorrelatingMessageHandler`) is a `MessageHandler` implementation, encapsulating the common functionalities of an Aggregator (and other correlating use cases), which are: + +* correlating messages into a group to be aggregated + +* maintaining those messages in a `MessageStore` until the group can be released + +* deciding when the group can be released + +* aggregating the released group into a single message + +* recognizing and responding to an expired group + + + +The responsibility of deciding how the messages should be grouped together is delegated to a `CorrelationStrategy` instance. +The responsibility of deciding whether the message group can be released is delegated to a `ReleaseStrategy` instance. + +Here is a brief highlight of the base `AbstractAggregatingMessageGroupProcessor` (the responsibility of implementing the `aggregatePayloads` method is left to the developer): + +[source,java] +---- +public abstract class AbstractAggregatingMessageGroupProcessor + implements MessageGroupProcessor { + + protected Map aggregateHeaders(MessageGroup group) { + // default implementation exists + } + + protected abstract Object aggregatePayloads(MessageGroup group, Map defaultHeaders); + +} +---- + +The `CorrelationStrategy` is owned by the `AbstractCorrelatingMessageHandler` and it has a default value based on the `IntegrationMessageHeaderAccessor.CORRELATION_ID` message header: + +[source,java] +---- +public AbstractCorrelatingMessageHandler(MessageGroupProcessor processor, MessageGroupStore store, + CorrelationStrategy correlationStrategy, ReleaseStrategy releaseStrategy) { + ... + this.correlationStrategy = correlationStrategy == null ? + new HeaderAttributeCorrelationStrategy(IntegrationMessageHeaderAccessor.CORRELATION_ID) : correlationStrategy; + this.releaseStrategy = releaseStrategy == null ? new SequenceSizeReleaseStrategy() : releaseStrategy; + ... +} +---- + +As for actual processing of the message group, the default implementation is the `DefaultAggregatingMessageGroupProcessor`. +It creates a single Message whose payload is a List of the payloads received for a given group. +This works well for simple Scatter Gather implementations with either a Splitter, Publish Subscribe Channel, or Recipient List Router upstream. + +NOTE: When using a Publish Subscribe Channel or Recipient List Router in this type of scenario, be sure to enable the flag to `apply-sequence`. +That will add the necessary headers (CORRELATION_ID, SEQUENCE_NUMBER and SEQUENCE_SIZE). +That behavior is enabled by default for Splitters in Spring Integration, but it is not enabled for the Publish Subscribe Channel or Recipient List Router because those components may be used in a variety of contexts in which these headers are not necessary. + +When implementing a specific aggregator strategy for an application, a developer can extend `AbstractAggregatingMessageGroupProcessor` and implement the `aggregatePayloads` method. +However, there are better solutions, less coupled to the API, for implementing the aggregation logic which can be configured easily either through XML or through annotations. + +In general, any POJO can implement the aggregation algorithm if it provides a method that accepts a single `java.util.List` as an argument (parameterized lists are supported as well). +This method will be invoked for aggregating messages as follows: + +* if the argument is a `java.util.List`, and the parameter type T is assignable to `Message`, then the whole list of messages accumulated for aggregation will be sent to the aggregator + +* if the argument is a non-parameterized `java.util.List` or the parameter type is not assignable to `Message`, then the method will receive the payloads of the accumulated messages + +* if the return type is not assignable to `Message`, then it will be treated as the payload for a Message that will be created automatically by the framework. + + + +NOTE: In the interest of code simplicity, and promoting best practices such as low coupling, testability, etc., the preferred way of implementing the aggregation logic is through a POJO, and using the XML or annotation support for configuring it in the application. + +===== ReleaseStrategy + +The `ReleaseStrategy` interface is defined as follows: + +[source,java] +---- +public interface ReleaseStrategy { + + boolean canRelease(MessageGroup group); + +} +---- + +In general, any POJO can implement the completion decision logic if it provides a method that accepts a single `java.util.List` as an argument (parameterized lists are supported as well), and returns a boolean value. +This method will be invoked after the arrival of each new message, to decide whether the group is complete or not, as follows: + +if the argument is a `java.util.List`, and the parameter type T is assignable to `Message`, then the whole list of messages accumulated in the group will be sent to the method + + + +if the argument is a non-parametrized `java.util.List` or the parameter type is not assignable to `Message`, then the method will receive the payloads of the accumulated messages + + + +the method must return true if the message group is ready for aggregation, and false otherwise. + + + +For example: + +[source,java] +---- +public class MyReleaseStrategy { + + @ReleaseStrategy + public boolean canMessagesBeReleased(List>) {...} +} +---- + +[source,java] +---- +public class MyReleaseStrategy { + + @ReleaseStrategy + public boolean canMessagesBeReleased(List) {...} +} +---- + +As you can see based on the above signatures, the POJO-based Release Strategy will be passed a `Collection` of not-yet-released Messages (if you need access to the whole `Message`) or a `Collection` of payload objects (if the type parameter is anything other than `Message`). +Typically this would satisfy the majority of use cases. +However if, for some reason, you need to access the full `MessageGroup` then you should simply provide an implementation of the `ReleaseStrategy` interface. + +[WARNING] +===== +When handling potentially large groups, it is important to understand how these methods are invoked because the release strategy may be invoked multiple times before the group is released. +The most efficient is an implementation of `ReleaseStrategy` because the aggregator can invoke it directly. +The second most efficient is a POJO method with a `Collection>` parameter type. +The least efficient is a POJO method with a `Collection` type - the framework has to copy the payloads from the messages in the group into a new collection (and possibly attempt conversion on the payloads to `Foo`) every time the release strategy is called. +`Collection` avoids the conversion but still requires creating the new `Collection`. + +*For these reasons, for large groups, it is recommended that you implement + `ReleaseStrategy`.* +===== + +When the group is released for aggregation, all its not-yet-released messages are processed and removed from the group. +If the group is also complete (i.e. +if all messages from a sequence have arrived or if there is no sequence defined), then the group is marked as complete. +Any new messages for this group will be sent to the discard channel (if defined). +Setting `expire-groups-upon-completion` to `true` (default is `false`) removes the entire group and any new messages, with the same correlation id as the removed group, will form a new group. +Partial sequences can be released by using a `MessageGroupStoreReaper` together with `send-partial-result-on-expiry` being set to `true`. + +IMPORTANT: To facilitate discarding of late-arriving messages, the aggregator must maintain state about the group after it has been released. +This can eventually cause out of memory conditions. +To avoid such situations, you should consider configuring a `MessageGroupStoreReaper` to remove the group metadata; the expiry parameters should be set to expire groups after it is not expected that late messages will arrive. +For information about configuring a reaper, see<>. + +Spring Integration provides an out-of-the box implementation for `ReleaseStrategy`, the `SequenceSizeReleaseStrategy`. +This implementation consults the SEQUENCE_NUMBER and SEQUENCE_SIZE headers of each arriving message to decide when a message group is complete and ready to be aggregated. +As shown above, it is also the default strategy. + +===== CorrelationStrategy + +The `CorrelationStrategy` interface is defined as follows: + +[source,java] +---- +public interface CorrelationStrategy { + + Object getCorrelationKey(Message message); + +} +---- + +The method returns an Object which represents the correlation key used for associating the message with a message group. +The key must satisfy the criteria used for a key in a Map with respect to the implementation of equals() and hashCode(). + +In general, any POJO can implement the correlation logic, and the rules for mapping a message to a method's argument (or arguments) are the same as for a `ServiceActivator` (including support for @Header annotations). +The method must return a value, and the value must not be `null`. + +Spring Integration provides an out-of-the box implementation for `CorrelationStrategy`, the `HeaderAttributeCorrelationStrategy`. +This implementation returns the value of one of the message headers (whose name is specified by a constructor argument) as the correlation key. +By default, the correlation strategy is a `HeaderAttributeCorrelationStrategy` returning the value of the CORRELATION_ID header attribute. +If you have a custom header name you would like to use for correlation, then simply configure that on an instance of `HeaderAttributeCorrelationStrategy` and provide that as a reference for the Aggregator's correlation-strategy. + +[[aggregator-config]] +==== Configuring an Aggregator + +[[aggregator-xml]] +===== Configuring an Aggregator with XML + +Spring Integration supports the configuration of an aggregator via XML through the `` element. +Below you can see an example of an aggregator. + +[source,xml] +---- + + + + auto-startup="true" <2> + input-channel="inputChannel" <3> + output-channel="outputChannel" <4> + discard-channel="throwAwayChannel" <5> + message-store="persistentMessageStore" <6> + order="1" <7> + send-partial-result-on-expiry="false" <8> + send-timeout="1000" <9> + + correlation-strategy="correlationStrategyBean" <10> + correlation-strategy-method="correlate" <11> + correlation-strategy-expression="headers['foo']" <12> + + ref="aggregatorBean" <13> + method="aggregate" <14> + + release-strategy="releaseStrategyBean" <15> + release-strategy-method="release" <16> + release-strategy-expression="size() == 5" <17> + + expire-groups-upon-completion="false" <18> + empty-group-min-timeout="60000" <19> + + lock-registry="lockRegistry" <20> + + group-timeout="60000" <21> + group-timeout-expression="size() ge 2 ? 100 : -1" <22> + expire-groups-on-timeout="true" <23> + + scheduler="taskScheduler" > <24> + <25> + <26> + + + + + + + + + + + + + + + +---- + +<1> The id of the aggregator is _Optional_. + + + +<2> Lifecycle attribute signaling if aggregator should be started during Application Context startup. +_Optional (default is 'true')_. + + + +<3> The channel from which where aggregator will receive messages. +_Required_. + + + +<4> The channel to which the aggregator will send the aggregation results. +_Optional (because incoming messages can specify a + reply channel themselves via 'replyChannel' Message Header)_. + + + +<5> The channel to which the aggregator will send the messages that timed out (if `send-partial-result-on-expiry` is _false_). +_Optional_. + + + +<6> A reference to a `MessageGroupStore` used to store groups of messages under their correlation key until they are complete. +_Optional_, by default a volatile in-memory store. + + + +<7> Order of this aggregator when more than one handle is subscribed to the same DirectChannel (use for load balancing purposes)._Optional_. + + + +<8> Indicates that expired messages should be aggregated and sent to the 'output-channel' or 'replyChannel' once their containing `MessageGroup` is expired (see `MessageGroupStore.expireMessageGroups(long)`). +One way of expiring `MessageGroup` s is by configuring a `MessageGroupStoreReaper`. +However `MessageGroup` s can alternatively be expired by simply calling `MessageGroupStore.expireMessageGroup(groupId)`. +That could be accomplished via a Control Bus operation or by simply invoking that method if you have a reference to the `MessageGroupStore` instance. +Otherwise by itself this attribute has no behavior. +It only serves as an indicator of what to do (discard or send to the output/reply channel) with Messages that are still in the `MessageGroup` that is about to be expired. +_Optional_. +_Default - 'false'_. +*NOTE:* This attribute is more properly 'send-partial-result-on-timeout' because the group may not actually expire if `expire-groups-on-timeout` is set to `false`. + + + +<9> The timeout interval to wait when sending a reply `Message` to the `output-channel` or `discard-channel`. +By default the send will block for one second. +It is applied only if the output channel has some 'sending' limitations, e.g. +`QueueChannel` with a fixed 'capacity'. +In this case a `MessageDeliveryException` is thrown. +The `send-timeout` is ignored in case of `AbstractSubscribableChannel` implementations. +In case of `group-timeout(-expression)` the `MessageDeliveryException` from the scheduled expire task leads this task to be rescheduled. +_Optional_. + + + +<10> A reference to a bean that implements the message correlation (grouping) algorithm. +The bean can be an implementation of the `CorrelationStrategy` interface or a POJO. +In the latter case the correlation-strategy-method attribute must be defined as well. +_Optional (by default, the aggregator will use + the `IntegrationMessageHeaderAccessor.CORRELATION_ID` header) _. + + + +<11> A method defined on the bean referenced by `correlation-strategy`, that implements the correlation decision algorithm. +_Optional, with + restrictions (requires `correlation-strategy` to be + present)._ + + + +<12> A SpEL expression representing the correlation strategy. +Example: `"headers['foo']"`. +Only one of `correlation-strategy` or `correlation-strategy-expression` is allowed. + + + +<13> A reference to a bean defined in the application context. +The bean must implement the aggregation logic as described above. +_Optional (by default the list of aggregated Messages will become a + payload of the output message)._ + + +<14> A method defined on the bean referenced by `ref`, that implements the message aggregation algorithm. +_Optional, depends on `ref` attribute being defined._ + + + +<15> A reference to a bean that implements the release strategy. +The bean can be an implementation of the `ReleaseStrategy` interface or a POJO. +In the latter case the release-strategy-method attribute must be defined as well. +_Optional (by default, the + aggregator will use the `IntegrationMessageHeaderAccessor.SEQUENCE_SIZE` header attribute)_. + + + +<16> A method defined on the bean referenced by `release-strategy`, that implements the completion decision algorithm. +_Optional, with + restrictions (requires `release-strategy` to be + present)._ + + + +<17> A SpEL expression representing the release strategy; the root object for the expression is a `Collection` of `Message` s. +Example: `"size() == 5"`. +Only one of `release-strategy` or `release-strategy-expression` is allowed. + + + +<18> When set to true (default false), completed groups are removed from the message store, allowing subsequent messages with the same correlation to form a new group. +The default behavior is to send messages with the same correlation as a completed group to the _discard-channel_. + + + +<19> Only applies if a `MessageGroupStoreReaper` is configured for the ``'s `MessageStore`. +By default, when a `MessageGroupStoreReaper` is configured to expire partial groups, empty groups are also removed. +Empty groups exist after a group is released normally. +This is to enable the detection and discarding of late-arriving messages. +If you wish to expire empty groups on a longer schedule than expiring partial groups, set this property. +Empty groups will then not be removed from the `MessageStore` until they have not been modified for at least this number of milliseconds. +Note that the actual time to expire an empty group will also be affected by the reaper's _timeout_ property and it could be as much as this value plus the timeout. + + + +<20> A reference to a `org.springframework.integration.util.LockRegistry` bean; used to obtain a `Lock` based on the `groupId` for concurrent operations on the `MessageGroup`. +By default, an internal `DefaultLockRegistry` is used. +Use of a distributed `LockRegistry`, such as the `RedisLockRegistry`, ensures only one instance of the aggregator will operate on a group concurrently. +See <> for more information. + + + +<21> A timeout in milliseconds to force the `MessageGroup` complete, when the `ReleaseStrategy` doesn't _release_ the group when the current Message arrives. +This attribute provides a built-in _Time-base Release Strategy_ for the aggregator, when there is a need to emit a partial result (or discard the group), if a new Message does not arrive for the `MessageGroup` within the timeout. +When a new Message arrives at the aggregator, any existing `ScheduledFuture` for its `MessageGroup` is canceled. +If the `ReleaseStrategy` returns `false` (don't release) and the `groupTimeout > 0` a new task will be scheduled to expire the group. +Setting this attribute to zero is not advised because it will effectively disable the aggregator because every message group will be immediately completed. +It is possible, however to conditionally set it to zero using an expression; see `group-timeout-expression` for information. +The action taken during the completion depends on the `ReleaseStrategy` and the `send-partial-group-on-expiry` attribute. +See <> for more information. +Mutually exclusive with 'group-timeout-expression' attribute. + + +<22> The SpEL expression that evaluates to a `groupTimeout` with the `MessageGroup` as the `#root` evaluation context object. +Used for scheduling the `MessageGroup` to be forced complete. +If the expression evaluates to null or `< 0`, the completion is not scheduled. +If it evaluates to zero, the group is completed immediately on the current thread. +In effect, this provides a dynamic `group-timeout` property. +See `group-timeout` for more information. +Mutually exclusive with 'group-timeout' attribute. + + +<23> When a group is completed due to a timeout (or by a `MessageGroupStoreReaper`), the group is expired (completely removed) by default. +Late arriving messages will start a new group. +Set this to `false` to complete the group but have its metadata remain so that late arriving messages will be discarded. +Empty groups can be expired later using a `MessageGroupStoreReaper` together with the `empty-group-min-timeout` attribute. +Default: 'true'. + + +<24> A `TaskScheduler` bean reference to schedule the `MessageGroup` to be forced complete if no new message arrives for the `MessageGroup` within the `groupTimeout`. +If not provided, the default scheduler `taskScheduler`, registered in the `ApplicationContext` (`ThreadPoolTaskScheduler`) will be used. +This attribute does not apply if `group-timeout` or `group-timeout-expression` is not specified. + + +<25> Since _version 4.1_. +Allows a transaction to be started for the `forceComplete` operation. +It is initiated from a `group-timeout(-expression)` or by a `MessageGroupStoreReaper` and is not applied to the normal `add/release/discard` operations. +Only this sub-element or `` is allowed. + + +<26> Since _version 4.1_. +Allows the configuration of any `Advice` for the `forceComplete` operation. +It is initiated from a `group-timeout(-expression)` or by a `MessageGroupStoreReaper` and is not applied to the normal `add/release/discard` operations. +Only this sub-element or `` is allowed. +A transaction `Advice` can also be configured here using the Spring `tx` namespace. + + + +[IMPORTANT] +.Expiring Groups +===== +There are two attributes related to expiring (completely removing) groups. +When a group is expired, there is no record of it and if a new message arrives with the same correlation, a new group is started. +When a group is completed (without expiry), the empty group remains and late arriving messages are discarded. +Empty groups can be removed later using a `MessageGroupStoreReaper` in combination with the `empty-group-min-timeout` attribute. + +`expire-groups-upon-completion` relates to "normal" completion - when the `ReleaseStrategy` releases the group. +This defaults to `false`. + +If a group is not completed normally, but is released or discarded because of a timeout, the group is normally expired. +Since _version 4.1_, you can now control this behavior using `expire-groups-upon-timeout`; this defaults to `true` for backwards compatibility. + +NOTE: When a group is timed out, the `ReleaseStrategy` is given one more opportunity to release the group; if it does so, and `expire-groups-upon-timeout` is false, then expiration is controlled by `expire-groups-upon-completion`. +If the group is not released by the release strategy during timeout, then the expiration is controlled by the `expire-groups-upon-timeout`. +Timed-out groups are either discarded, or a partial release occurs (based on `send-partial-result-on-expiry`). +===== + +Using a `ref` attribute is generally recommended if a custom aggregator handler implementation may be referenced in other`` definitions. +However if a custom aggregator implementation is only being used by a single definition of the ``, you can use an inner bean definition (starting with version 1.0.3) to configure the aggregation POJO within the `` element: +[source,xml] +---- + + + +---- + +NOTE: Using both a `ref` attribute and an inner bean definition in the same `` configuration is not allowed, as it creates an ambiguous condition. +In such cases, an Exception will be thrown. + +An example implementation of the aggregator bean looks as follows: + +[source,java] +---- +public class PojoAggregator { + + public Long add(List results) { + long total = 0l; + for (long partialResult: results) { + total += partialResult; + } + return total; + } + +} +---- + +An implementation of the completion strategy bean for the example above may be as follows: + +[source,java] +---- +public class PojoReleaseStrategy { +... + public boolean canRelease(List numbers) { + int sum = 0; + for (long number: numbers) { + sum += number; + } + return sum >= maxValue; + } +} +---- + +NOTE: Wherever it makes sense, the release strategy method and the aggregator method can be combined in a single bean. + +An implementation of the correlation strategy bean for the example above may be as follows: + +[source,java] +---- +public class PojoCorrelationStrategy { +... + public Long groupNumbersByLastDigit(Long number) { + return number % 10; + } +} +---- + +For example, this aggregator would group numbers by some criterion (in our case the remainder after dividing by 10) and will hold the group until the sum of the numbers provided by the payloads exceeds a certain value. + +NOTE: Wherever it makes sense, the release strategy method, correlation strategy method and the aggregator method can be combined in a single bean (all of them or any two). + +_Aggregators and Spring Expression Language (SpEL)_ + +Since Spring Integration 2.0, the various strategies (correlation, release, and aggregation) may be handled with http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/expressions.html[SpEL] which is recommended if the logic behind such _release strategy_ is relatively simple. +Let's say you have a legacy component that was designed to receive an array of objects. +We know that the default release strategy will assemble all aggregated messages in the List. +So now we have two problems. +First we need to extract individual messages from the list, and then we need to extract the payload of each message and assemble the array of objects (see code below). + +[source,java] +---- +public String[] processRelease(List> messages){ + List stringList = new ArrayList(); + for (Message message : messages) { + stringList.add(message.getPayload()); + } + return stringList.toArray(new String[]{}); +} +---- + +However, with SpEL such a requirement could actually be handled relatively easily with a one-line expression, thus sparing you from writing a custom class and configuring it as a bean. + +[source,xml] +---- + +---- + +In the above configuration we are using a http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/expressions.html#d0e12113[Collection Projection] expression to assemble a new collection from the payloads of all messages in the list and then transforming it to an Array, thus achieving the same result as the java code above. + +The same expression-based approach can be applied when dealing with custom _Release_ and _Correlation_ strategies. + +Instead of defining a bean for a custom `CorrelationStrategy` via the `correlation-strategy` attribute, you can implement your simple correlation logic via a SpEL expression and configure it via the `correlation-strategy-expression` attribute. + +For example: +[source,xml] +---- +correlation-strategy-expression="payload.person.id" +---- + +In the above example it is assumed that the payload has an attribute `person` with an `id` which is going to be used to correlate messages. + +Likewise, for the `ReleaseStrategy` you can implement your release logic as a SpEL expression and configure it via the `release-strategy-expression` attribute. +The only difference is that since ReleaseStrategy is passed the List of Messages, the root object in the SpEL evaluation context is the List itself. +That List can be referenced as `#this` within the expression. + +For example: +[source,xml] +---- +release-strategy-expression="#this.size() gt 5" +---- + +In this example the root object of the SpEL Evaluation Context is the `MessageGroup` itself, and you are simply stating that as soon as there are more than 5 messages in this group, it should be released. + +[[agg-and-group-to]] +====== Aggregator and Group Timeout + +Starting with _version 4.0_, two new mutually exclusive attributes have been introduced: `group-timeout` and `group-timeout-expression` (see the description above). +There are some cases where it is needed to emit the aggregator result (or discard the group) after a timeout if the `ReleaseStrategy` doesn't _release_ when the current Message arrives. +For this purpose the `groupTimeout` option allows scheduling the `MessageGroup` to be forced complete: +[source,xml] +---- + +---- + +With this example, the normal _release_ will be possible if the aggregator receives the last message in sequence as defined by the `release-strategy-expression`. +If that specific message does not arrive, the `groupTimeout` will force the group complete after 10 seconds as long as the group contains at least 2 Messages. + +The results of forcing the group complete depends on the `ReleaseStrategy` and the `send-partial-result-on-expiry`. +First, the release strategy is again consulted to see if a _normal_ release is to be made - while the group won't have changed, the `ReleaseStrategy` can decide to release the group at this time. +If the release strategy still does not release the group, it will be expired. +If `send-partial-result-on-expiry` is `true`, existing messages in the (partial) `MessageGroup` will be released as a normal aggregator reply Message to the `output-channel`, otherwise it will be discarded. + +There is a difference between `groupTimeout` behavior and `MessageGroupStoreReaper` (see <>). +The reaper initiates forced completion for all `MessageGroup` s in the `MessageGroupStore` periodically. +The `groupTimeout` does it for each `MessageGroup` individually, if a new Message doesn't arrive during the `groupTimeout`. +Also, the reaper can be used to remove empty groups (empty groups are retained in order to discard late messages, if `expire-groups-upon-completion` is false). + +[[aggregator-annotations]] +===== Configuring an Aggregator with Annotations + +An aggregator configured using annotations would look like this. + +[source,java] +---- +public class Waiter { + ... + + @Aggregator <1> + public Delivery aggregatingMethod(List items) { + ... + } + + @ReleaseStrategy <2> + public boolean releaseChecker(List> messages) { + ... + } + + @CorrelationStrategy <3> + public String correlateBy(OrderItem item) { + ... + } + +} +---- + +<1> An annotation indicating that this method shall be used as an aggregator. +Must be specified if this class will be used as an aggregator. + + + +<2> An annotation indicating that this method shall be used as the release strategy of an aggregator. +If not present on any method, the aggregator will use the SequenceSizeReleaseStrategy. + + + +<3> An annotation indicating that this method shall be used as the correlation strategy of an aggregator. +If no correlation strategy is indicated, the aggregator will use the HeaderAttributeCorrelationStrategy based on CORRELATION_ID. + + +All of the configuration options provided by the xml element are also available for the @Aggregator annotation. + +The aggregator can be either referenced explicitly from XML or, if the @MessageEndpoint is defined on the class, detected automatically through classpath scanning. + +[[reaper]] +==== Managing State in an Aggregator: MessageGroupStore + +Aggregator (and some other patterns in Spring Integration) is a stateful pattern that requires decisions to be made based on a group of messages that have arrived over a period of time, all with the same correlation key. +The design of the interfaces in the stateful patterns (e.g. +`ReleaseStrategy`) is driven by the principle that the components (whether defined by the framework or a user) should be able to remain stateless. +All state is carried by the `MessageGroup` and its management is delegated to the `MessageGroupStore`. + +[source,java] +---- +public interface MessageGroupStore { + int getMessageCountForAllMessageGroups(); + + int getMarkedMessageCountForAllMessageGroups(); + + int getMessageGroupCount(); + + MessageGroup getMessageGroup(Object groupId); + + MessageGroup addMessageToGroup(Object groupId, Message message); + + MessageGroup markMessageGroup(MessageGroup group); + + MessageGroup removeMessageFromGroup(Object key, Message messageToRemove); + + MessageGroup markMessageFromGroup(Object key, Message messageToMark); + + void removeMessageGroup(Object groupId); + + void registerMessageGroupExpiryCallback(MessageGroupCallback callback); + + int expireMessageGroups(long timeout); +} +---- + +For more information please refer to the http://static.springsource.org/spring-integration/api/org/springframework/integration/store/MessageGroupStore.html[JavaDoc]. + +The `MessageGroupStore` accumulates state information in `MessageGroups` while waiting for a release strategy to be triggered, and that event might not ever happen. +So to prevent stale messages from lingering, and for volatile stores to provide a hook for cleaning up when the application shuts down, the `MessageGroupStore` allows the user to register callbacks to apply to its `MessageGroups` when they expire. +The interface is very straightforward: + +[source,java] +---- +public interface MessageGroupCallback { + + void execute(MessageGroupStore messageGroupStore, MessageGroup group); + +} +---- + +The callback has direct access to the store and the message group so it can manage the persistent state (e.g. +by removing the group from the store entirely). + +The `MessageGroupStore` maintains a list of these callbacks which it applies, on demand, to all messages whose timestamp is earlier than a time supplied as a parameter (see the `registerMessageGroupExpiryCallback(..)` and `expireMessageGroups(..)` methods above). + +The `expireMessageGroups` method can be called with a timeout value. +Any message older than the current time minus this value will be expired, and have the callbacks applied. +Thus it is the user of the store that defines what is meant by message group "expiry". + +As a convenience for users, Spring Integration provides a wrapper for the message expiry in the form of a `MessageGroupStoreReaper`: + +[source,xml] +---- + + + + + + + + +---- + +The reaper is a `Runnable`, and all that is happening in the example above is that the message group store's expire method is being called once every 10 seconds. +The timeout itself is 30 seconds. + +NOTE: It is important to understand that the 'timeout' property of the `MessageGroupStoreReaper` is an approximate value and is impacted by the the rate of the task scheduler since this property will only be checked on the next scheduled execution of the `MessageGroupStoreReaper` task. +For example if the timeout is set for 10 min, but the `MessageGroupStoreReaper` task is scheduled to run every 60 min and the last execution of the `MessageGroupStoreReaper` task happened 1 min before the timeout, the `MessageGroup` will not expire for the next 59 min. +So it is recommended to set the rate at least equal to the value of the timeout or shorter. + +In addition to the reaper, the expiry callbacks are invoked when the application shuts down via a lifecycle callback in the `AbstractCorrelatingMessageHandler`. + +The `AbstractCorrelatingMessageHandler` registers its own expiry callback, and this is the link with the boolean flag` send-partial-result-on-expiry` in the XML configuration of the aggregator. +If the flag is set to true, then when the expiry callback is invoked, any unmarked messages in groups that are not yet released can be sent on to the output channel. + +[IMPORTANT] +===== +When using a `MessageGroupStoreReaper`, it is generally recommended to use a separate `MessageStore` for each correlating endpoint. +Otherwise, unexpected results may occur because one endpoint may remove another endpoint's groups. + +Some `MessageStore` implementations allow using the same physical resources, by partitioning the data; for example, the `JdbcMessageStore` has a `region` property; the `MongoDbMessageStore` has a `collectionName` property. + +For more information about `MessageStore` interface and its implementations, please read <>. +===== diff --git a/src/reference/asciidoc/amqp.adoc b/src/reference/asciidoc/amqp.adoc new file mode 100644 index 0000000000..6769ed3298 --- /dev/null +++ b/src/reference/asciidoc/amqp.adoc @@ -0,0 +1,662 @@ +[[amqp]] +== AMQP Support + +[[amqp-introduction]] +=== Introduction + +Spring Integration provides Channel Adapters for receiving and sending messages using the Advanced Message Queuing Protocol (AMQP). +The following adapters are available: + +* Inbound Channel Adapter +* Outbound Channel Adapter +* Inbound Gateway +* Outbound Gateway + +Spring Integration also provides a point-to-point Message Channel as well as a publish/subscribe Message Channel backed by AMQP Exchanges and Queues. + +In order to provide AMQP support, Spring Integration relies on Spring AMQP (http://www.springsource.org/spring-amqp[http://www.springsource.org/spring-amqp]) which "applies core Spring concepts to the development of AMQP-based messaging solutions". +Spring AMQP provides similar semantics as Spring JMS (http://static.springsource.org/spring/docs/current/spring-framework-reference/html/jms.html[http://static.springsource.org/spring/docs/current/spring-framework-reference/html/jms.html]). + +Whereas the provided AMQP Channel Adapters are intended for unidirectional Messaging (send or receive) only, Spring Integration also provides inbound and outbound AMQP Gateways for request/reply operations. + +[TIP] +===== +Please familiarize yourself with the reference documentation of the Spring AMQP project as well. +It provides much more in-depth information regarding Spring's integration with AMQP in general and RabbitMQ in particular. + +You can find the documentation at: http://static.springsource.org/spring-amqp/reference/html/[http://static.springsource.org/spring-amqp/reference/html/] +===== +[[amqp-inbound-channel-adapter]] +=== Inbound Channel Adapter + +A configuration sample for an AMQP Inbound Channel Adapter is shown below. + +[source,xml] +---- + + channel="inboundChannel" <2> + queue-names="si.test.queue" <3> + acknowledge-mode="AUTO" <4> + advice-chain="" <5> + channel-transacted="" <6> + concurrent-consumers="" <7> + connection-factory="" <8> + error-channel="" <9> + expose-listener-channel="" <10> + header-mapper="" <11> + mapped-request-headers="" <12> + listener-container="" <13> + message-converter="" <14> + message-properties-converter="" <15> + phase="" <16> + prefetch-count="" <17> + receive-timeout="" <18> + recovery-interval="" <19> + missing-queues-fatal="" <20> + shutdown-timeout="" <21> + task-executor="" <22> + transaction-attribute="" <23> + transaction-manager="" <24> + tx-size="" /> <25> + +---- + +<1> Unique ID for this adapter. +_Optional_. + + +<2> Message Channel to which converted Messages should be sent. +_Required_. + + +<3> Names of the AMQP Queues from which Messages should be consumed (comma-separated list)._Required_. + + +<4> Acknowledge Mode for the `MessageListenerContainer`. +When set to MANUAL, the delivery tag and channel are provided in message headers `amqp_deliveryTag` and `amqp_channel` respectively; the user application is responsible for acknowledgement. +NONE means no acknowledgements (autoAck); AUTO means the adapter's container will acknowledge when the downstream flow completes._Optional (Defaults to AUTO)_ see <>. + + +<5> Extra AOP Advice(s) to handle cross cutting behavior associated with this Inbound Channel Adapter. +_Optional_. + + +<6> Flag to indicate that channels created by this component will be transactional. +Ff true, tells the framework to use a transactional channel and to end all operations (send or receive) with a commit or rollback depending on the outcome, with an exception signalling a rollback. +_Optional (Defaults to false)_. + + +<7> Specify the number of concurrent consumers to create. +Default is 1. +Raising the number of concurrent consumers is recommended in order to scale the consumption of messages coming in from a queue. +However, note that any ordering guarantees are lost once multiple consumers are registered. +In general, stick with 1 consumer for low-volume queues. +_Optional_. + + +<8> Bean reference to the RabbitMQ ConnectionFactory. +_Optional (Defaults to 'connectionFactory')_. + + +<9> Message Channel to which error Messages should be sent. +_Optional_. + + +<10> Shall the listener channel (com.rabbitmq.client.Channel) be exposed to a registered `ChannelAwareMessageListener`. +_Optional (Defaults to true)_. + + +<11> A reference to an `AmqpHeaderMapper` to use when receiving AMQP Messages. +_Optional_. +By default only standard AMQP properties (e.g. +`contentType`) will be copied to Spring Integration `MessageHeaders`. +Any user-defined headers within the AMQP `MessageProperties` will NOT be copied to the Message by the default `DefaultAmqpHeaderMapper`. +Not allowed if 'request-header-names' is provided. + + +<12> Comma-separated list of names of AMQP Headers to be mapped from the AMQP request into the MessageHeaders. +This can only be provided if the 'header-mapper' reference is not provided. +The values in this list can also be simple patterns to be matched against the header names (e.g. +"\*" or "foo*, bar" or "*foo"). + + +<13> Reference to the `SimpleMessageListenerContainer` to use for receiving AMQP Messages. +If this attribute is provided, then no other attribute related to the listener container configuration should be provided. +In other words, by setting this reference, you must take full responsibility of the listener container configuration. +The only exception is the MessageListener itself. +Since that is actually the core responsibility of this Channel Adapter implementation, the referenced listener container must NOT already have its own MessageListener configured. +_Optional_. + + +<14> The MessageConverter to use when receiving AMQP Messages. +_Optional_. + + +<15> The MessagePropertiesConverter to use when receiving AMQP Messages. +_Optional_. + + +<16> Specify the phase in which the underlying `SimpleMessageListenerContainer` should be started and stopped. +The startup order proceeds from lowest to highest, and the shutdown order is the reverse of that. +By default this value is Integer.MAX_VALUE meaning that this container starts as late as possible and stops as soon as possible. +_Optional_. + + +<17> Tells the AMQP broker how many messages to send to each consumer in a single request. +Often this can be set quite high to improve throughput. +It should be greater than or equal to the transaction size (see attribute "tx-size")._Optional (Defaults to 1)_. + + +<18> Receive timeout in milliseconds. +_Optional (Defaults to 1000)_. + + +<19> Specifies the interval between recovery attempts of the underlying `SimpleMessageListenerContainer` (in milliseconds)._Optional (Defaults to 5000)_. + + +<20> If 'true', and none of the queues are available on the broker, the container will throw a fatal exception during startup and will stop if the queues are deleted when the container is running (after making 3 attempts to passively declare the queues). +If false, the container will not throw an exception and go into recovery mode, attempting to restart according to the `revcovery-interval`. +_Optional (Defaults to `true`)_. + + +<21> The time to wait for workers in milliseconds after the underlying `SimpleMessageListenerContainer` is stopped, and before the AMQP connection is forced closed. +If any workers are active when the shutdown signal comes they will be allowed to finish processing as long as they can finish within this timeout. +Otherwise the connection is closed and messages remain unacked (if the channel is transactional). +Defaults to 5000 milliseconds._Optional (Defaults to 5000)_. + + +<22> By default, the underlying `SimpleMessageListenerContainer` uses a SimpleAsyncTaskExecutor implementation, that fires up a new Thread for each task, executing it asynchronously. +By default, the number of concurrent threads is unlimited. +*NOTE:* This implementation does not reuse threads. +Consider a thread-pooling TaskExecutor implementation as an alternative. +_Optional (Defaults to SimpleAsyncTaskExecutor)_. + + +<23> By default the underlying `SimpleMessageListenerContainer` creates a new instance of the DefaultTransactionAttribute (takes the EJB approach to rolling back on runtime, but not checked exceptions. +_Optional (Defaults to DefaultTransactionAttribute)_. + + +<24> Sets a Bean reference to an external `PlatformTransactionManager` on the underlying SimpleMessageListenerContainer. +The transaction manager works in conjunction with the "channel-transacted" attribute. +If there is already a transaction in progress when the framework is sending or receiving a message, and the channelTransacted flag is true, then the commit or rollback of the messaging transaction will be deferred until the end of the current transaction. +If the channelTransacted flag is false, then no transaction semantics apply to the messaging operation (it is auto-acked). +For further information see chapter 1.9 of the Spring AMQP reference guide: http://static.springsource.org/spring-amqp/docs/1.0.x/reference/html/#d0e525 _Optional_. + + +<25> Tells the `SimpleMessageListenerContainer` how many messages to process in a single transaction (if the channel is transactional). +For best results it should be less than or equal to the set "prefetch-count". +_Optional (Defaults to 1)_. + + +[NOTE] +.container +===== +Note that when configuring an external container, you cannot use the *Spring AMQP* namespace to define the container. +This is because the namespace requires at least one `` element. +In this environment, the listener is internal to the adapter. +For this reason, you must define the container using a normal Spring `` definition, such as: +[source,xml] +---- + + + + + + +---- +===== + +IMPORTANT: Even though the Spring Integration JMS and AMQP support is very similar, important differences exist. +The JMS Inbound Channel Adapter is using a JmsDestinationPollingSource under the covers and expects a configured Poller. +The AMQP Inbound Channel Adapter on the other side uses a`SimpleMessageListenerContainer` and is message driven. +In that regard it is more similar to the JMS Message Driven Channel Adapter. + +[[amqp-inbound-gateway]] +=== Inbound Gateway + +The inbound gateway supports all the attributes on the inbound channel adapter (except 'channel' is replaced by 'request-channel'), plus some additional attributes: + +[source,xml] +---- + + request-channel="myRequestChannel" <2> + header-mapper="" <3> + mapped-request-headers="" <4> + mapped-reply-headers="" <5> + reply-channel="myReplyChannel" <6> + reply-timeout="1000" /> <7> + +---- + +<1> Unique ID for this adapter. +_Optional_. + + +<2> Message Channel to which converted Messages should be sent. +_Required_. + + +<3> A reference to an `AmqpHeaderMapper` to use when receiving AMQP Messages. +_Optional_. +By default only standard AMQP properties (e.g. +`contentType`) will be copied to and from Spring Integration `MessageHeaders`. +Any user-defined headers within the AMQP`MessageProperties` will NOT be copied to or from an AMQP Message by the default `DefaultAmqpHeaderMapper`. +Not allowed if 'request-header-names' or 'reply-header-names' is provided. + + +<4> Comma-separated list of names of AMQP Headers to be mapped from the AMQP request into the `MessageHeaders`. +This can only be provided if the 'header-mapper' reference is not provided. +The values in this list can also be simple patterns to be matched against the header names (e.g. +"\*" or "foo*, bar" or "*foo"). + + +<5> Comma-separated list of names of `MessageHeaders` to be mapped into the AMQP Message Properties of the AMQP reply message. +All standard Headers (e.g., `contentType`) will be mapped to AMQP Message Properties while user-defined headers will be mapped to the 'headers' property. +This can only be provided if the 'header-mapper' reference is not provided. +The values in this list can also be simple patterns to be matched against the header names (e.g. +"\*" or "foo*, bar" or "*foo"). + + +<6> Message Channel where reply Messages will be expected. +_Optional_. + + +<7> Used to set the `receiveTimeout` on the underlying `org.springframework.integration.core.MessagingTemplate` for receiving messages from the reply channel. +If not specified this property will default to "1000" (1 second). +Only applies if the container thread hands off to another thread before the reply is sent. + +See the note in <> about configuring the `listener-container` attribute. + +[[amqp-inbound-ack]] +=== Inbound Endpoint Acknowledge Mode + +By default the inbound endpoints use acknowledge mode `AUTO`, which means the container automatically _acks_ the message when the downstream integration flow completes (or a message is handed off to another thread using a `QueueChannel` or `ExecutorChannel`). +Setting the mode to `NONE` configures the consumer such that acks are not used at all (the broker automatically acks the message as soon as it is sent). +Setting the mode to`MANUAL` allows user code to ack the message at some other point during processing. +To support this, with this mode, the endpoints provide the `Channel` and `deliveryTag` in the `amqp_channel` and `amqp_deliveryTag` headers respectively. + +You can perform any valid rabbit command on the `Channel` but, generally, only `basicAck` and `basicNack` (or `basicReject`) would be used. +In order to not interfere with the operation of the container, you should not retain a reference to the channel and just use it in the context of the current message. + +NOTE: Since the `Channel` is a reference to a "live" object, it cannot be serialized and will be lost if a message is persisted. + +This is an example of how you might use `MANUAL` acknowledgement: + +[source,java] +---- +@ServiceActivator(inputChannel = "foo", outputChannel = "bar") +public Object handle(@Payload String payload, @Header(AmqpHeaders.CHANNEL) Channel channel, + @Header(AmqpHeaders.DELIVERY_TAG) Long deliveryTag) throws Exception { + + // Do some processing + + if (allOK) { + channel.basicAck(deliveryTag, false); + + // perhaps do some more processing + + } + else { + channel.basicNack(deliveryTag, false, true); + } + return someResultForDownStreamProcessing; +} +---- + +[[amqp-outbound-channel-adapter]] +=== Outbound Channel Adapter + +A configuration sample for an AMQP Outbound Channel Adapter is shown below. + +[source,xml] +---- + + channel="outboundChannel" <2> + amqp-template="myAmqpTemplate" <3> + exchange-name="" <4> + exchange-name-expression="" <5> + order="1" <6> + routing-key="" <7> + routing-key-expression="" <8> + default-delivery-mode"" <9> + confirm-correlation-expression="" <10> + confirm-ack-channel="" <11> + confirm-nack-channel="" <12> + return-channel="" <13> + header-mapper="" <14> + mapped-request-headers="" <15> + lazy-connect="true" /> <16> + +---- + +<1> Unique ID for this adapter. +_Optional_. + + +<2> Message Channel to which Messages should be sent in order to have them converted and published to an AMQP Exchange. +_Required_. + + +<3> Bean Reference to the configured AMQP Template _Optional (Defaults to "amqpTemplate")_. + + +<4> The name of the AMQP Exchange to which Messages should be sent. +If not provided, Messages will be sent to the default, no-name Exchange. +Mutually exclusive with 'exchange-name-expression'. +_Optional_. + + +<5> A SpEL expression that is evaluated to determine the name of the AMQP Exchange to which Messages should be sent, with the message as the root object. +If not provided, Messages will be sent to the default, no-name Exchange. +Mutually exclusive with 'exchange-name'. +_Optional_. + + +<6> The order for this consumer when multiple consumers are registered thereby enabling load- balancing and/or failover. +_Optional (Defaults to Ordered.LOWEST_PRECEDENCE [=Integer.MAX_VALUE])_. + + +<7> The fixed routing-key to use when sending Messages. +By default, this will be an empty String. +Mutually exclusive with 'routing-key-expression'._Optional_. + + +<8> A SpEL expression that is evaluated to determine the routing-key to use when sending Messages, with the message as the root object (e.g. +'payload.key'). +By default, this will be an empty String. +Mutually exclusive with 'routing-key'. +_Optional_. + + +<9> The default delivery mode for messages; 'PERSISTENT' or 'NON_PERSISTENT'. +Overridden if the 'header-mapper' sets the delivery mode. +The 'DefaultHeaderMapper' sets the value if the Spring Integration message header `amqp_deliveryMode` is present. +If this attribute is not supplied and the header mapper doesn't set it, the default depends on the underlying spring-amqp 'MessagePropertiesConverter' used by the 'RabbitTemplate'. +If that is not customized at all, the default is 'PERSISTENT'. +_Optional_. + + +<10> An expression defining correlation data. +When provided, this configures the underlying amqp template to receive publisher confirms. +Requires a dedicated`RabbitTemplate` and a `CachingConnectionFactory` with the `publisherConfirms` property set to `true`. +When a publisher confirm is received, and correlation data is supplied, it is written to either the confirm-ack-channel, or the confirm-nack-channel, depending on the confirmation type. +The payload of the confirm is the correlation data as defined by this expression and the message will have a header 'amqp_publishConfirm' set to true (ack) or false (nack). +Examples: "headers['myCorrelationData']", "payload". +_Optional_. +Starting with _version 4.1_ the `amqp_publishConfirmNackCause` message header has been added. +It contains the `cause` of a 'nack' for publisher confirms. + + +<11> The channel to which positive (ack) publisher confirms are sent; payload is the correlation data defined by the _confirm-correlation-expression_. +_Optional, default=nullChannel_. + + +<12> The channel to which negative (nack) publisher confirms are sent; payload is the correlation data defined by the _confirm-correlation-expression_. +_Optional, default=nullChannel_. + + +<13> The channel to which returned messages are sent. +When provided, the underlying amqp template is configured to return undeliverable messages to the adapter. +The message will be constructed from the data received from amqp, with the following additional headers: _amqp_returnReplyCode, + amqp_returnReplyText, amqp_returnExchange, amqp_returnRoutingKey_. +_Optional_. + + +<14> A reference to an `AmqpHeaderMapper` to use when sending AMQP Messages. +_Optional_. +By default only standard AMQP properties (e.g. +`contentType`) will be copied to the Spring Integration `MessageHeaders`. +Any user-defined headers will NOT be copied to the Message by the default`DefaultAmqpHeaderMapper`. +Not allowed if 'request-header-names' is provided. + + +<15> Comma-separated list of names of AMQP Headers to be mapped from the `MessageHeaders` to the AMQP Message. +Not allowed if the 'header-mapper' reference is provided. +The values in this list can also be simple patterns to be matched against the header names (e.g. +"\*" or "foo*, bar" or "*foo"). + + +<16> When set to `false`, the endpoint will attempt to connect to the broker during application context initialization. +This allows "fail fast" detection of bad configuration, but will also cause initialization to fail if the broker is down. +When true (default), the connection is established (if it doesn't already exist because some other component established it) when the first message is sent. + + +[IMPORTANT] +.return-channel +===== +Using a `return-channel` requires a `RabbitTemplate` with the `mandatory` property set to `true`, and a `CachingConnectionFactory` with the `publisherReturns` property set to `true`. +When using multiple outbound endpoints with returns, a separate `RabbitTemplate` is needed for each endpoint. +===== + +[[amqp-outbound-gateway]] +=== Outbound Gateway + +A configuration sample for an AMQP Outbound Gateway is shown below. + +[source,xml] +---- + + request-channel="myRequestChannel" <2> + amqp-template="" <3> + exchange-name="" <4> + exchange-name-expression="" <5> + order="1" <6> + reply-channel="" <7> + reply-channel="" <8> + requires-reply="" <9> + routing-key="" <10> + routing-key-expression="" <11> + default-delivery-mode"" <12> + return-channel="" <13> + lazy-connect="true" /> <14> + +---- + +<1> Unique ID for this adapter. +_Optional_. + + +<2> Message Channel to which Messages should be sent in order to have them converted and published to an AMQP Exchange. +_Required_. + + +<3> Bean Reference to the configured AMQP Template _Optional (Defaults to "amqpTemplate")_. + + +<4> The name of the AMQP Exchange to which Messages should be sent. +If not provided, Messages will be sent to the default, no-name Exchange. +Mutually exclusive with 'exchange-name-expression'. +_Optional_. + + +<5> A SpEL expression that is evaluated to determine the name of the AMQP Exchange to which Messages should be sent, with the message as the root object. +If not provided, Messages will be sent to the default, no-name Exchange. +Mutually exclusive with 'exchange-name'. +_Optional_. + + +<6> The order for this consumer when multiple consumers are registered thereby enabling load- balancing and/or failover. +_Optional (Defaults to Ordered.LOWEST_PRECEDENCE [=Integer.MAX_VALUE])_. + + +<7> Message Channel to which replies should be sent after being received from an AQMP Queue and converted._Optional_. + + +<8> The time the gateway will wait when sending the reply message to the `reply-channel`. +This only applies if the `reply-channel` can block - such as a `QueueChannel` with a capacity limit that is currently full. +Default: infinity. + + +<9> When `true`, the gateway will throw an exception if no reply message is received within the `AmqpTemplate`'s `replyTimeout` property. +Default: `true`. + + +<10> The routing-key to use when sending Messages. +By default, this will be an empty String. +Mutually exclusive with 'routing-key-expression'_Optional_. + + +<11> A SpEL expression that is evaluated to determine the routing-key to use when sending Messages, with the message as the root object (e.g. +'payload.key'). +By default, this will be an empty String. +Mutually exclusive with 'routing-key'. +_Optional_. + + +<12> The default delivery mode for messages; 'PERSISTENT' or 'NON_PERSISTENT'. +Overridden if the 'header-mapper' sets the delivery mode. +The 'DefaultHeaderMapper' sets the value if the Spring Integration message header `amqp_deliveryMode` is present. +If this attribute is not supplied and the header mapper doesn't set it, the default depends on the underlying spring-amqp 'MessagePropertiesConverter' used by the 'RabbitTemplate'. +If that is not customized at all, the default is 'PERSISTENT'._Optional_. + + +<13> The channel to which returned messages are sent. +When provided, the underlying amqp template is configured to return undeliverable messages to the gateway. +The message will be constructed from the data received from amqp, with the following additional headers: _amqp_returnReplyCode, + amqp_returnReplyText, amqp_returnExchange, amqp_returnRoutingKey_. +_Optional_. + + +<14> When set to `false`, the endpoint will attempt to connect to the broker during application context initialization. +This allows "fail fast" detection of bad configuration, but will also cause initialization to fail if the broker is down. +When true (default), the connection is established (if it doesn't already exist because some other component established it) when the first message is sent. + + +[IMPORTANT] +.return-channel +===== +Using a `return-channel` requires a `RabbitTemplate` with the `mandatory` property set to `true`, and a `CachingConnectionFactory` with the `publisherReturns` property set to `true`. +When using multiple outbound endpoints with returns, a separate `RabbitTemplate` is needed for each endpoint. +===== + +IMPORTANT: The underlying `AmqpTemplate` has a default `replyTimeout` of 5 seconds. +If you require a longer timeout, it must be configured on the `template`. + +[[amqp-channels]] +=== AMQP Backed Message Channels + +There are two Message Channel implementations available. +One is point-to-point, and the other is publish/subscribe. +Both of these channels provide a wide range of configuration attributes for the underlying AmqpTemplate and SimpleMessageListenerContainer as you have seen on the Channel Adapters and Gateways. +However, the examples we'll show here are going to have minimal configuration. +Explore the XML schema to view the available attributes. + +A point-to-point channel would look like this: +[source,xml] +---- + +---- + +Under the covers a Queue named "si.p2pChannel" would be declared, and this channel will send to that Queue (technically by sending to the no-name Direct Exchange with a routing key that matches this Queue's name). +This channel will also register a consumer on that Queue. +If for some reason, you want the Queue to be "pollable" instead of message-driven, then simply provide the "message-driven" flag with a value of false: +[source,xml] +---- + +---- + +A publish/subscribe channel would look like this: +[source,xml] +---- + +---- + +Under the covers a Fanout Exchange named "si.fanout.pubSubChannel" would be declared, and this channel will send to that Fanout Exchange. +This channel will also declare a server-named exclusive, autodelete, non-durable Queue and bind that to the Fanout Exchange while registering a consumer on that Queue to receive Messages. +There is no "pollable" option for a publish-subscribe-channel; it must be message-driven. + +Starting with _version 4.1_ AMQP Backed Message Channels, alongside with `channel-transacted`, support `template-channel-transacted` to separate `transactional` configuration for the `AbstractMessageListenerContainer` and for the `RabbitTemplate`. +Note, previously, the `channel-transacted` was `true` by default, now it changed to `false` as standard default value for the `AbstractMessageListenerContainer`. + +[[amqp-message-headers]] +=== AMQP Message Headers + +The Spring Integration AMPQ Adapters will map standard AMQP properties automatically. +These properties will be copied by default to and from Spring Integration `MessageHeaders` using the http://static.springsource.org/spring-integration/api/org/springframework/integration/amqp/support/DefaultAmqpHeaderMapper.html[DefaultAmqpHeaderMapper]. + +Of course, you can pass in your own implementation of AMQP specific header mappers, as the adapters have respective properties to support that. + +Any user-defined headers within the AMQP http://static.springsource.org/spring-amqp/api/org/springframework/amqp/core/MessageProperties.html[MessageProperties] will NOT be copied to or from an AMQP Message, unless explicitly specified by the _requestHeaderNames_ and/or _replyHeaderNames_ properties of the `DefaultAmqpHeaderMapper`. + +TIP: When mapping user-defined headers, the values can also contain simple wildcard patterns (e.g. "foo*" or "*foo") to be matched. +For example, if you need to copy all user-defined headers simply use the wild-card character `*`. + +Starting with _version 4.1_, the `AbstractHeaderMapper` (a `DefaultAmqpHeaderMapper` superclass) allows the `NON_STANDARD_HEADERS` token to be configured for the _requestHeaderNames_ and/or _replyHeaderNames_ properties (in addition to existing `STANDARD_REQUEST_HEADERS` and `STANDARD_REPLY_HEADERS`) to map all user-defined headers. +Note, it is recommended to use the combination like this `STANDARD_REPLY_HEADERS, NON_STANDARD_HEADERS` instead of generic `*`, to avoid mapping of _request_ headers to the reply. + +Class `org.springframework.amqp.support.AmqpHeaders` identifies the default headers that will be used by the `DefaultAmqpHeaderMapper`: + +* amqp_appId + +* amqp_clusterId + +* amqp_contentEncoding + +* amqp_contentLength + +* content-type + +* amqp_correlationId + +* amqp_deliveryMode + +* amqp_deliveryTag + +* amqp_expiration + +* amqp_messageCount + +* amqp_messageId + +* amqp_receivedExchange + +* amqp_receivedRoutingKey + +* amqp_redelivered + +* amqp_replyTo + +* amqp_timestamp + +* amqp_type + +* amqp_userId + +* amqp_publishConfirm + +* amqp_publishConfirmNackCause + +* amqp_returnReplyCode + +* amqp_returnReplyText + +* amqp_returnExchange + +* amqp_returnRoutingKey + +=== AMQP Samples + +To experiment with the AMQP adapters, check out the samples available in the Spring Integration Samples Git repository at: + +* https://github.com/SpringSource/spring-integration-samples[https://github.com/SpringSource/spring-integration-samples] + + + +Currently there is one sample available that demonstrates the basic functionality of the Spring Integration AMQP Adapter using an Outbound Channel Adapter and an Inbound Channel Adapter. +As AMQP Broker implementation the sample uses RabbitMQ (http://www.rabbitmq.com/[http://www.rabbitmq.com/]). + +NOTE: In order to run the example you will need a running instance of RabbitMQ. +A local installation with just the basic defaults will be sufficient. +For detailed RabbitMQ installation procedures please visit: http://www.rabbitmq.com/install.html[http://www.rabbitmq.com/install.html] + +Once the sample application is started, you enter some text on the command prompt and a message containing that entered text is dispatched to the AMQP queue. +In return that message is retrieved via Spring Integration and then printed to the console. + +The image belows illustrates the basic set of Spring Integration components used in this sample. + +.The Spring Integration graph of the AMQP sample + +image::images/spring-integration-amqp-sample-graph.png[] diff --git a/src/reference/asciidoc/bridge.adoc b/src/reference/asciidoc/bridge.adoc new file mode 100644 index 0000000000..00999c7fb2 --- /dev/null +++ b/src/reference/asciidoc/bridge.adoc @@ -0,0 +1,52 @@ +[[bridge]] +=== Messaging Bridge + +[[bridge-introduction]] +==== Introduction + +A Messaging Bridge is a relatively trivial endpoint that simply connects two Message Channels or Channel Adapters. +For example, you may want to connect a `PollableChannel` to a `SubscribableChannel` so that the subscribing endpoints do not have to worry about any polling configuration. +Instead, the Messaging Bridge provides the polling configuration. + +By providing an intermediary poller between two channels, a Messaging Bridge can be used to throttle inbound Messages. +The poller's trigger will determine the rate at which messages arrive on the second channel, and the poller's "maxMessagesPerPoll" property will enforce a limit on the throughput. + +Another valid use for a Messaging Bridge is to connect two different systems. +In such a scenario, Spring Integration's role would be limited to making the connection between these systems and managing a poller if necessary. +It is probably more common to have at least a _Transformer_ between the two systems to translate between their formats, and in that case, the channels would be provided as the 'input-channel' and 'output-channel' of a Transformer endpoint. +If data format translation is not required, the Messaging Bridge may indeed be sufficient. + +[[bridge-namespace]] +==== Configuring Bridge + +The element is used to create a Messaging Bridge between two Message Channels or Channel Adapters. +Simply provide the "input-channel" and "output-channel" attributes: +[source,xml] +---- + +---- + +As mentioned above, a common use case for the Messaging Bridge is to connect a `PollableChannel` to a `SubscribableChannel`, and when performing this role, the Messaging Bridge may also serve as a throttler: +[source,xml] +---- + + + +---- + +Connecting Channel Adapters is just as easy. +Here is a simple echo example between the "stdin" and "stdout" adapters from Spring Integration's "stream" namespace. +[source,xml] +---- + + + + + +---- + +Of course, the configuration would be similar for other (potentially more useful) Channel Adapter bridges, such as File to JMS, or Mail to File. +The various Channel Adapters will be discussed in upcoming chapters. + +NOTE: If no 'output-channel' is defined on a bridge, the reply channel provided by the inbound Message will be used, if available. +If neither output or reply channel is available, an Exception will be thrown. diff --git a/src/reference/asciidoc/chain.adoc b/src/reference/asciidoc/chain.adoc new file mode 100644 index 0000000000..153d241a31 --- /dev/null +++ b/src/reference/asciidoc/chain.adoc @@ -0,0 +1,161 @@ +[[chain]] +=== Message Handler Chain + +[[chain-introduction]] +==== Introduction + +The `MessageHandlerChain` is an implementation of `MessageHandler` that can be configured as a single Message Endpoint while actually delegating to a chain of other handlers, such as Filters, Transformers, Splitters, and so on. +This can lead to a much simpler configuration when several handlers need to be connected in a fixed, linear progression. +For example, it is fairly common to provide a Transformer before other components. +Similarly, when providing a _Filter_ before some other component in a chain, you are essentially creating a http://www.eaipatterns.com/MessageSelector.html[Selective Consumer]. +In either case, the chain only requires a single `input-channel` and a single `output-channel` eliminating the need to define channels for each individual component. + +TIP: Spring Integration's `Filter` provides a boolean property `throwExceptionOnRejection`. +When providing multiple Selective Consumers on the same point-to-point channel with different acceptance criteria, this value should be set to 'true' (the default is false) so that the dispatcher will know that the Message was rejected and as a result will attempt to pass the Message on to other subscribers. +If the Exception were not thrown, then it would appear to the dispatcher as if the Message had been passed on successfully even though the Filter had _dropped_ the Message to prevent further processing. +If you do indeed want to "drop" the Messages, then the Filter's 'discard-channel' might be useful since it does give you a chance to perform some operation with the dropped message (e.g. +send to a JMS queue or simply write to a log). + +The handler chain simplifies configuration while internally maintaining the same degree of loose coupling between components, and it is trivial to modify the configuration if at some point a non-linear arrangement is required. + +Internally, the chain will be expanded into a linear setup of the listed endpoints, separated by anonymous channels. +The reply channel header will not be taken into account within the chain: only after the last handler is invoked will the resulting message be forwarded on to the reply channel or the chain's output channel. +Because of this setup all handlers except the last required to implement the MessageProducer interface (which provides a 'setOutputChannel()' method). +The last handler only needs an output channel if the outputChannel on the MessageHandlerChain is set. + +NOTE: As with other endpoints, the `output-channel` is optional. +If there is a reply Message at the end of the chain, the output-channel takes precedence, but if not available, the chain handler will check for a reply channel header on the inbound Message as a fallback. + +In most cases there is no need to implement MessageHandlers yourself. +The next section will focus on namespace support for the chain element. +Most Spring Integration endpoints, like Service Activators and Transformers, are suitable for use within a `MessageHandlerChain`. + +[[chain-namespace]] +==== Configuring a Chain + +The element provides an `input-channel` attribute, and if the last element in the chain is capable of producing reply messages (optional), it also supports an `output-channel` attribute. +The sub-elements are then filters, transformers, splitters, and service-activators. +The last element may also be a router or an outbound-channel-adapter. +[source,xml] +---- + + + + + + + +---- + +The element used in the above example will set a message header named "foo" with a value of "bar" on the message. +A header enricher is a specialization of `Transformer` that touches only header values. +You could obtain the same result by implementing a MessageHandler that did the header modifications and wiring that as a bean, but the header-enricher is obviously a simpler option. + +The can be configured as the last 'black-box' consumer of the message flow. +For this solution it is enough to put at the end of the some : +[source,xml] +---- + + + + + + + + +---- + +_Disallowed Attributes and Elements_ + +It is important to note that certain attributes, such as *order* and *input-channel* are not allowed to be specified on components used within a _chain_. +The same is true for the *poller* sub-element. + +[IMPORTANT] +===== +For the _Spring Integration_ core components, the XML Schema itself will enforce some of these constraints. +However, for non-core components or your own custom components, these constraints are enforced by the XML namespace parser, not by the XML Schema. + +These XML namespace parser constraints were added with _Spring Integration 2.2_. +The XML namespace parser will throw an `BeanDefinitionParsingException` if you try to use disallowed attributes and elements. +===== + +_'id' Attribute_ + +Beginning with Spring Integration 3.0, if a chain element is given an _id_, the bean name for the element is a combination of the chain's _id_ and the _id_ of the element itself. +Elements without an _id_ are not registered as beans, but they are given `componentName` s that include the chain id. +For example: +[source,xml] +---- + + + + +---- + + + +* The `` root element has an _id_ 'fooChain'. +So, the `AbstractEndpoint` implementation (`PollingConsumer` or `EventDrivenConsumer`, depending on the _input-channel_ type) bean takes this value as it's bean name. + +* The `MessageHandlerChain` bean acquires a bean alias 'fooChain.handler', which allows direct access to this bean from the `BeanFactory`. + +* The `` is not a fully-fledged Messaging Endpoint (`PollingConsumer` or `EventDrivenConsumer`) - it is simply a `MessageHandler` within the ``. +In this case, the bean name registered with the `BeanFactory` is 'fooChain$child.fooService.handler'. + +* The _componentName_ of this `ServiceActivatingHandler` takes the same value, but without the '.handler' suffix - 'fooChain$child.fooService'. + +* The last `` sub-component, ``, doesn't have an _id_ attribute. +Its _componentName_ is based on its position in the ``. +In this case, it is 'fooChain$child#1'. +(The final element of the name is the order within the chain, beginning with '#0'). +Note, this transformer isn't registered as a bean within the application context, so, it doesn't get a _beanName_, however its _componentName_ has a value which is useful for logging etc. + +The _id_ attribute for `` elements allows them to be eligible for <> and they are trackable via <>. +They can also be accessed from the `BeanFactory` using the appropriate bean name as discussed above. + +TIP: It is useful to provide an explicit _id_ attribute on `` s to simplify the identification of sub-components in logs, and to provide access to them from the `BeanFactory` etc. + +_Calling a Chain from within a Chain_ + +Sometimes you need to make a nested call to another chain from within a chain and then come back and continue execution within the original chain. +To accomplish this you can utilize a Messaging Gateway by including a element. +For example: + +[source,xml] +---- + + + + + + + +   + + + + + + +   + + + + + + + + + + + + + +---- + +In the above example the _nested-chain-a_ will be called at the end of _main-chain_ processing by the 'gateway' element configured there. +While in _nested-chain-a_ a call to a _nested-chain-b_ will be made after header enrichment and then it will come back to finish execution in _nested-chain-b_. +Finally the flow returns to the _main-chain_. +When the nested version of a element is defined in the chain, it does not require the `service-interface` attribute. +Instead, it simple takes the message in its current state and places it on the channel defined via the `request-channel` attribute. +When the downstream flow initiated by that gateway completes, a `Message` will be returned to the gateway and continue its journey within the current chain. diff --git a/src/reference/asciidoc/changes-1.0-2.0.adoc b/src/reference/asciidoc/changes-1.0-2.0.adoc new file mode 100644 index 0000000000..670da6ec7a --- /dev/null +++ b/src/reference/asciidoc/changes-1.0-2.0.adoc @@ -0,0 +1,178 @@ +[[migration-1.0-2.0]] +=== Changes between 1.0 and 2.0 + +For a detailed migration guide in regards to upgrading an existing application that uses Spring Integration older than version 2.0, please see: + +null + +[[migration-spring-30-support]] +==== Spring 3 support + +Spring Integration 2.0 is built on top of Spring 3.0.5 and makes many of its features available to our users. + +[[spel-support]] +===== Support for the Spring Expression Language (SpEL) + +You can now use SpEL expressions within the _transformer, router, filter, + splitter, aggregator, service-activator, header-enricher_, and many more elements of the Spring Integration core namespace as well as various adapters. +There are many samples provided throughout this manual. + +[[conversion-support]] +===== ConversionService and Converter + +You can now benefit from _Conversion Service_ support provided with Spring while configuring many Spring Integration components such as http://www.eaipatterns.com/DatatypeChannel.html[Datatype Channel]. +See <> as well <>. +Also, the SpEL support mentioned in the previous point also relies upon the ConversionService. +Therefore, you can register Converters once, and take advantage of them anywhere you are using SpEL expressions. + +[[task-scheduler-poller-support]] +===== TaskScheduler and Trigger + +Spring 3.0 defines two new strategies related to scheduling: _TaskScheduler and Trigger_ Spring Integration (which uses a lot of scheduling) now builds upon these. +In fact, Spring Integration 1.0 had originally defined some of the components (e.g. +CronTrigger) that have now been migrated into Spring 3.0's core API. +Now, you can benefit from reusing the same components within the entire Application Context (not just Spring Integration configuration). +Configuration of Spring Integration Pollers has been greatly simplified as well by providing attributes for directly configuring rates, delays, cron expressions, and trigger references. +See <> for sample configurations. + +[[rest-support]] +===== RestTemplate and HttpMessageConverter + +Our outbound HTTP adapters now delegate to Spring's RestTemplate for executing the HTTP request and handling its response. +This also means that you can reuse any custom HttpMessageConverter implementations. +See <> for more details. + +[[new-eip]] +==== Enterprise Integration Pattern Additions + +Also in 2.0 we have added support for even more of the patterns described in Hohpe and Woolf's http://www.eaipatterns.com/[Enterprise Integration Patterns] book. + +[[new-message-history]] +===== Message History + +We now provide support for the http://www.eaipatterns.com/MessageHistory.html[Message History] pattern allowing you to keep track of all traversed components, including the name of each channel and endpoint as well as the timestamp of that traversal. +See <> for more details. + +[[new-message-store]] +===== Message Store + +We now provide support for the http://www.eaipatterns.com/MessageStore.html[Message Store] pattern. +The Message Store provides a strategy for persisting messages on behalf of any process whose scope extends beyond a single transaction, such as the Aggregator and Resequencer. +Many sections of this document provide samples on how to use a Message Store as it affects several areas of Spring Integration. +See <>, <>, <>, <>, <>, and <> for more details + +[[new-claim-check]] +===== Claim Check + +We have added an implementation of the http://www.eaipatterns.com/StoreInLibrary.html[Claim Check] pattern. +The idea behind the Claim Check pattern is that you can exchange a Message payload for a "claim ticket" and vice-versa. +This allows you to reduce bandwidth and/or avoid potential security issues when sending Messages across channels. +See <> for more details. + +[[new-control-bus]] +===== Control Bus + +We have provided implementations of the http://www.eaipatterns.com/ControlBus.html[Control Bus] pattern which allows you to use messaging to manage and monitor endpoints and channels. +The implementations include both a SpEL-based approach and one that executes Groovy scripts. +See <> and <> for more details. + +[[new-adapters]] +==== New Channel Adapters and Gateways + +We have added several new Channel Adapters and Messaging Gateways in Spring Integration 2.0. + +[[new-ip]] +===== TCP/UDP Adapters + +We have added Channel Adapters for receiving and sending messages over the TCP and UDP internet protocols. +See <> for more details. +Also, you can checkout the following blog: http://blog.springsource.com/2010/03/29/using-udp-and-tcp-adapters-in-spring-integration-2-0-m3/[TCP/UDP support] + +[[new-twitter]] +===== Twitter Adapters + +Twitter adapters provides support for sending and receiving Twitter Status updates as well as Direct Messages. +You can also perform Twitter Searches with an inbound Channel Adapter. +See <> for more details. + +[[new-xmpp]] +===== XMPP Adapters + +The new XMPP adapters support both Chat Messages and Presence events. +See <> for more details. + +[[new-ftp]] +===== FTP/FTPS Adapters + +Inbound and outbound File transfer support over FTP/FTPS is now available. +See <> for more details. + +[[new-sftp]] +===== SFTP Adapters + +Inbound and outbound File transfer support over SFTP is now available. +See <> for more details. + +[[new-feed]] +===== Feed Adapters + +We have also added Channel Adapters for receiving news feeds (ATOM/RSS). +See <> for more details. + +[[new-other]] +==== Other Additions + +[[new-groovy]] +===== Groovy Support + +With Spring Integration 2.0 we've added Groovy support allowing you to use Groovy scripting language to provide integration and/or business logic. +See <> for more details. + +[[new-map-transformer]] +===== Map Transformers + +These symmetrical transformers convert payload objects to and from a Map. +See <> for more details. + +[[new-json-transformer]] +===== JSON Transformers + +These symmetrical transformers convert payload objects to and from JSON. +See <> for more details. + +[[new-serialize-transformer]] +===== Serialization Transformers + +These symmetrical transformers convert payload objects to and from byte arrays. +They also support the Serializer and Deserializer strategy interfaces that have been added as of Spring 3.0.5. +See <> for more details. + +[[new-refactoring]] +==== Framework Refactoring + +The core API went through some significant refactoring to make it simpler and more usable. +Although we anticipate that the impact to the end user should be minimal, please read through this document to find what was changed. +Especially, visit <> , <>, <>, <>, and <> for more details. +If you are depending directly on some of the core components (Message, MessageHeaders, MessageChannel, MessageBuilder, etc.), you will notice that you need to update any import statements. +We restructured some packaging to provide the flexibility we needed for extending the domain model while avoiding any cyclical dependencies (it is a policy of the framework to avoid such "tangles"). + +[[new-infrastructure]] +==== New Source Control Management and Build Infrastructure + +With Spring Integration 2.0 we have switched our build environment to use Git for source control. +To access our repository simply follow this URL: http://git.springsource.org/spring-integration[http://git.springsource.org/spring-integration]. +We have also switched our build system to http://gradle.org/[Gradle]. + +[[new-samples]] +==== New Spring Integration Samples + +With Spring Integration 2.0 we have decoupled the samples from our main release distribution. +Please read this blog to get more info http://blog.springsource.com/2010/09/29/new-spring-integration-samples/[New Spring Integration Samples] We have also created many new samples, including samples for every new Adapter. + +[[new-sts]] +==== Spring Tool Suite Visual Editor for Spring Integration + +There is an amazing new visual editor for Spring Integration included within the latest version of SpringSource Tool Suite. +If you are not already using STS, please download it here: + +https://spring.io/tools/sts[Spring Tool Suite] diff --git a/src/reference/asciidoc/changes-2.0-2.1.adoc b/src/reference/asciidoc/changes-2.0-2.1.adoc new file mode 100644 index 0000000000..a49802b779 --- /dev/null +++ b/src/reference/asciidoc/changes-2.0-2.1.adoc @@ -0,0 +1,220 @@ +[[migration-2.0-2.1]] +=== Changes between 2.0 and 2.1 + +[[x2.1-new-components]] +==== New Components + +[[x2.1-new-scripting-support]] +===== JSR-223 Scripting Support + +In Spring Integration 2.0, support for http://groovy.codehaus.org/[Groovy] was added. +With Spring Integration 2.1 we expanded support for additional languages substantially by implementing support for http://www.jcp.org/en/jsr/detail?id=223[JSR-223] (Scripting for the Java™ Platform). +Now you have the ability to use any scripting language that supports JSR-223 including: + +* Javascript +* Ruby/JRuby +* Python/Jython +* Groovy + + + +For further details please see <>. + +[[x2.1-new-gemfire-support]] +===== GemFire Support + +Spring Integration provides support for http://www.vmware.com/products/application-platform/vfabric-gemfire/overview.html[GemFire] by providing inbound adapters for entry and continuous query events, an outbound adapter to write entries to the cache, and http://static.springsource.org/spring-integration/api/org/springframework/integration/store/MessageStore.html[`MessageStore`] and http://static.springsource.org/spring-integration/api/org/springframework/integration/store/MessageGroupStore.html[`MessageGroupStore`] implementations. +Spring integration leverages the http://www.springsource.org/spring-gemfire[_Spring Gemfire_] project, providing a thin wrapper over its components. + +For further details please see <>. + +[[x2.1-new-amqp-support]] +===== AMQP Support + +Spring Integration 2.1 adds several Channel Adapters for receiving and sending messages using thehttp://www.amqp.org/[_Advanced Message Queuing Protocol_] (AMQP). +Furthermore, Spring Integration also provides a point-to-point Message Channel, as well as a publish/subscribe Message Channel that are backed by AMQP Exchanges and Queues. + +For further details please see <>. + +[[x2.1-new-mongodb-support]] +===== MongoDB Support + +As of version 2.1 Spring Integration provides support for http://www.mongodb.org/[MongoDB] by providing a MongoDB-based MessageStore. + +For further details please see <>. + +[[x2.1-new-redis-support]] +===== Redis Support + +As of version 2.1 Spring Integration supports http://redis.io/[Redis], an advanced key-value store, by providing a Redis-based MessageStore as well as Publish-Subscribe Messaging adapters. + +For further details please see <>. + +[[x2.1-new-resource-support]] +===== Support for Spring's Resource abstraction + +As of version 2.1, we've introduced a new _Resource Inbound Channel Adapter_ that builds upon Spring's Resource abstraction to support greater flexibility across a variety of actual types of underlying resources, such as a file, a URL, or a class path resource. +Therefore, it's similar to but more generic than the _File Inbound Channel Adapter_. + +For further details please see <>. + +[[x2.1-new-stored-proc-support]] +===== Stored Procedure Components + +With Spring Integration 2.1, the `JDBC` Module also provides Stored Procedure support by adding several new components, including inbound/outbound channel adapters and an Outbound Gateway. +The Stored Procedure support leverages Spring'shttp://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/jdbc/core/simple/SimpleJdbcCall.html[`SimpleJdbcCall`] class and consequently supports stored procedures for: + +* Apache Derby +* DB2 +* MySQL +* Microsoft SQL Server +* Oracle +* PostgreSQL +* Sybase + + + +The Stored Procedure components also support Sql Functions for the following databases: + +* MySQL +* Microsoft SQL Server +* Oracle +* PostgreSQL + + + +For further details please see <>. + +[[x2.1-new-xpath-filter-support]] +===== XPath and XML Validating Filter + +Spring Integration 2.1 provides a new XPath-based Message Filter, that is part of the `XML` module. +The XPath Filter allows you to filter messages using provided XPath Expressions. +Furthermore, documentation was added for the XML Validating Filter. + +For more details please see <> and <>. + +[[x2.1-new-payload-enricher-support]] +===== Payload Enricher + +Since Spring Integration 2.1, the Payload Enricher is provided. +A Payload Enricher defines an endpoint that typically passes ahttp://static.springsource.org/spring-integration/api/org/springframework/integration/Message.html[`Message`] to the exposed request channel and then expects a reply message. +The reply message then becomes the root object for evaluation of expressions to enrich the target payload. + +For further details please see <>. + +[[x2.1-new-ftp-outbound-gateway]] +===== FTP and SFTP Outbound Gateways + +Spring Integration 2.1 provides two new Outbound Gateways in order to interact with remote File Transfer Protocol (FTP) or Secure File Transfer Protocol (SFT) servers. +These two gateways allow you to directly execute a limited set of remote commands. + +For instance, you can use these Outbound Gateways to list, retrieve and delete remote files and have the Spring Integration message flow continue with the remote server's response. + +For further details please see <> and <>. + +[[x2.1-new-ftp-session-caching]] +===== FTP Session Caching + +As of version 2.1, we have exposed more flexibility with regards to session management for remote file adapters (e.g., FTP, SFTP etc). + +Specifically, the `cache-sessions` attribute, which is available via the XML namespace support, is now_deprecated_. +Alternatively, we added the `sessionCacheSize` and `sessionWaitTimeout` attributes on the `CachingSessionFactory`. + +For further details please see <> and <>. + +[[x2.1-framework-refactorings]] +==== Framework Refactoring + +[[x2.1-router-standardization]] +===== Standardizing Router Configuration + +Router parameters have been standardized across all router implementations with Spring Integration 2.1 providing a more consistent user experience. + +With Spring Integration 2.1 the `ignore-channel-name-resolution-failures` attribute has been removed in favor of consolidating its behavior with the `resolution-required` attribute. +Also, the `resolution-required` attribute now defaults to `true`. + +Starting with Spring Integration 2.1, routers will no longer silently drop any messages, if no default output channel was defined. +This means, that by default routers now require at least one resolved channel (if no `default-output-channel` was set) and by default will throw a `MessageDeliveryException` if no channel was determined (or an attempt to send was not successful). + +If, however, you do desire to drop messages silently, simply set `default-output-channel="nullChannel"`. + +IMPORTANT: With the standardization of Router parameters and the consolidation of the parameters described above, there is the possibility of breaking older Spring Integration based applications. + +For further details please see <> + +[[x2.1-schema-updated]] +===== XML Schemas updated to 2.1 + +Spring Integration 2.1 ships with an updated XML Schema (version 2.1), providing many improvements, e.g. +the Router standardizations discussed above. + +From now on, users _must_ always declare the latest XML schema (currently version 2.1). +Alternatively, they can use the version-less schema. +Generally, the best option is to use version-less namespaces, as these will automatically use the latest available version of Spring Integration. + +Declaring a version-less Spring Integration namespace: + +[source,xml] +---- + + +... + +---- + +Declaring a Spring Integration namespace using an explicit version: + +[source,xml] +---- + + +... + +---- + +The old 1.0 and 2.0 schemas are still there, but if an Application Context still references one of those deprecated schemas, the validator will fail on initialization. + +[[x2.1-source-control-infrastructure]] +==== Source Control Management and Build Infrastructure + +[[x2.1-move-to-github]] +===== Source Code now hosted on Github + +Since version 2.0, the Spring Integration project uses http://git-scm.com/[Git] for version control. +In order to increase community visibility even further, the project was moved from SpringSource hosted Git repositories to http://www.github.com/[Github]. +The Spring Integration Git repository is located at:null + +For the project we also improved the process of providing code contributions and we ensure that every commit is peer-reviewed. +In fact, core committers now follow the same process as contributors. +For more details please see: + +null + +[[x2.1-sonar]] +===== Improved Source Code Visibility with Sonar + +In an effort to provide better source code visibility and consequently to monitor the quality of Spring Integration's source code, an instance of http://www.sonarsource.org/[Sonar] was setup and metrics are gathered nightly and made avaiblable at: + +null + +[[x2.1-new-samples]] +==== New Samples + +For the 2.1 release of Spring Integration we also expanded the Spring Integration Samples project and added many new samples, e.g. +samples covering AMQP support, the new payload enricher, a sample illustrating techniques for testing Spring Integration flow fragments, as well as an example for executing Stored Procedures against Oracle. +For details please visit: + +null diff --git a/src/reference/asciidoc/changes-2.1-2.2.adoc b/src/reference/asciidoc/changes-2.1-2.2.adoc new file mode 100644 index 0000000000..78e98cb721 --- /dev/null +++ b/src/reference/asciidoc/changes-2.1-2.2.adoc @@ -0,0 +1,175 @@ +[[migration-2.1-2.2]] +=== Changes between 2.1 and 2.2 + +[[x2.2-new-components]] +==== New Components + +[[x2.2-redis-store-adapters]] +===== RedisStore Inbound and Outbound Channel Adapters + +Spring Integration now has RedisStore Inbound and Outbound Channel Adapters allowing you to write and read Message payloads to/from Redis collection(s). +For more information please see <> and <>. + +[[x2.2-mongo-adapters]] +===== MongoDB Inbound and Outbound Channel Adapters + +Spring Integration now has MongoDB Inbound and Outbound Channel Adapters allowing you to write and read Message payloads to/from a MongoDB document store. +For more information please see <> and <>. + +[[x2.2-jpa]] +===== JPA Endpoints + +Spring Integration now includes components for the Java Persistence API (JPA) for retrieving and persisting JPA entity objects. +The JPA Adapter includes the following components: + +* _<>_ +* _<>_ +* _<>_ +* _<>_ + + + +For more information please see <> + +[[x2.2-general]] +==== General Changes + +[[x2.2-spring-31]] +===== Spring 3.1 Used by Default + +Spring Integration now uses Spring 3.1. + +[[x2.2-handler-advice]] +===== Adding Behavior to Endpoints + +The ability to add an to a poller has been available for some time. +However, the behavior added by this affects the entire integration flow. +It did not address the ability to add, say, retry, to an individual endpoint. +The 2.2. +release introduces the to many endpoints. + +In addition, 3 standard Advice classes have been provided for this purpose: + +* MessageHandlerRetryAdvice +* MessageHandlerCircuitBreakerAdvice +* ExpressionEvaluatingMessageHandlerAdvice + + + +For more information, see <>. + +[[x2.2-transaction-sync]] +===== Transaction Synchronization and Pseudo Transactions + +Pollers can now participate in Spring's _Transaction Synchronization_ feature. +This allows for synchronizing such operations as renaming files by an inbound channel adapter depending on whether the transaction commits, or rolls back. + +In addition, these features can be enabled when there is not a 'real' transaction present, by means of a `PseudoTransactionManager`. + +For more information see <>. + +[[x2.2-file-adapter]] +===== File Adapter - Improved File Overwrite/Append Handling + +When using the _File Oubound Channel Adapter_ or the _File Outbound Gateway_, a new _mode_ property was added. +Prior to _Spring Integration 2.2_, target files were replaced when they existed. +Now you can specify the following options: + +* REPLACE (Default) +* APPEND +* FAIL +* IGNORE + + + +For more information please see <>. + +[[x2.2-outbound-gateways]] +===== Reply-Timeout added to more Outbound Gateways + +The XML Namespace support adds the _reply-timeout_ attribute to the following _Outbound Gateways_: + +* Amqp Outbound Gateway +* File Outbound Gateway +* Ftp Outbound Gateway +* Sftp Outbound Gateway +* Ws Outbound Gateway + + + +[[x2.2-amqp-11]] +===== Spring-AMQP 1.1 + +Spring Integration now uses Spring AMQP 1.1. +This enables several features to be used within a Spring Integration application, including... + +* A fixed reply queue for the outbound gateway +* HA (mirrored) queues +* Publisher Confirms +* Returned Messages +* Support for Dead Letter Exchanges/Dead Letter Queues + + + +[[x2.2-jdbc-11]] +===== JDBC Support - Stored Procedures Components + +_SpEL Support_ + +When using the Stored Procedure components of the Spring Integration JDBC Adapter, you can now provide Stored Procedure Names or Stored Function Names using Spring Expression Language (SpEL). + +This allows you to specify the Stored Procedures to be invoked at runtime. +For example, you can provide Stored Procedure names that you would like to execute via Message Headers. +For more information please see <>. + +_JMX Support_ + +The Stored Procedure components now provide basic JMX support, exposing some of their properties as MBeans: + +* Stored Procedure Name +* Stored Procedure Name Expression +* JdbcCallOperations Cache Statistics + + + +[[x2.2-jdbc-gateway-update-optional]] +===== JDBC Support - Outbound Gateway + +When using the JDBC Outbound Gateway, the update query is no longer mandatory. +You can now provide solely a select query using the request message as a source of parameters. + +[[x2.2-jdbc-message-store-channels]] +===== JDBC Support - Channel-specific Message Store Implementation + +A new _Message Channel_-specific Message Store Implementation has been added, providing a more scalable solution using database-specific SQL queries. +For more information please see: <>. + +[[x2.2-shutdown]] +===== Orderly Shutdown + +A method `stopActiveComponents()` has been added to the IntegrationMBeanExporter. +This allows a Spring Integration application to be shut down in an orderly manner, disallowing new inbound messages to certain adapters and waiting for some time to allow in-flight messages to complete. + +[[x2.2-jms-og]] +===== JMS Oubound Gateway Improvements + +The JMS Outbound Gateway can now be configured to use a`MessageListener` container to receive replies. +This can improve performance of the gateway. + +[[x2.2-o-t-j-t]] +===== object-to-json-transformer + +The `ObjectToJsonTransformer` now sets the _content-type_ header to _application/json_ by default. +For more information see <>. + +[[httpChanges]] +===== HTTP Support + +Java serialization over HTTP is no longer enabled by default. +Previously, when setting a `expected-response-type` to a `Serializable` object, the `Accept` header was not properly set up. +The `SerializingHttpMessageConverter` has now been updated to set the Accept header to `application/x-java-serialized-object`. +However, because this could cause incompatibility with existing applications, it was decided to no longer automatically add this converter to the HTTP endpoints. + +If you wish to use Java serialization, you will need to add the `SerializingHttpMessageConverter` to the appropriate endpoints, using the `message-converters` attribute, when using XML configuration, or using the `setMessageConverters()` method. + +Alternatively, you may wish to consider using JSON instead which is enabled by simply having `Jackson` on the classpath. diff --git a/src/reference/asciidoc/changes-2.2-3.0.adoc b/src/reference/asciidoc/changes-2.2-3.0.adoc new file mode 100644 index 0000000000..a01f524c24 --- /dev/null +++ b/src/reference/asciidoc/changes-2.2-3.0.adoc @@ -0,0 +1,421 @@ +[[migration-2.2-3.0]] +=== Changes Between 2.2 and 3.0 + +[[x3.0-new-components]] +==== New Components + +[[x3.0-request-mapping]] +===== HTTP Request Mapping + +The HTTP module now provides powerful Request Mapping support for Inbound Endpoints. +Class `UriPathHandlerMapping` was replaced by `IntegrationRequestMappingHandlerMapping`, which is registered under the bean name `integrationRequestMappingHandlerMapping` in the application context. +Upon parsing of the HTTP Inbound Endpoint, a new `IntegrationRequestMappingHandlerMapping` bean is either registered or an existing bean is being reused. +To achieve flexible Request Mapping configuration, Spring Integration provides the `` sub-element for the `` and the ``. +Both HTTP Inbound Endpoints are now fully based on the Request Mapping infrastructure that was introduced with Spring MVC 3.1. +For example, multiple paths are supported on a single inbound endpoint. +For more information see <>. + +[[x3.0-spel-customization]] +===== Spring Expression Language (SpEL) Configuration + +A new `IntegrationEvaluationContextFactoryBean` is provided to allow configuration of custom `PropertyAccessor` s and functions for use in SpEL expressions throughout the framework. +For more information see <>. + +[[x3.0-spel-functions]] +===== SpEL Functions Support + +To customize the SpEL `EvaluationContext` with static `Method` functions, the new `` component is introduced. +Two built-in functions are also provided (`#jsonPath` and `#xpath`). +For more information see <>. + +[[x3.0-spel-property-accessors]] +===== SpEL PropertyAccessors Support + +To customize the SpEL `EvaluationContext` with `PropertyAccessor` implementations the new `` component is introduced. +For more information see <>. + +[[x3.0-redis-new-components]] +===== Redis: New Components + +A new Redis-based http://docs.spring.io/spring-integration/docs/latest-ga/api/org/springframework/integration/store/MetadataStore.html[MetadataStore] implementation has been added. +The `RedisMetadataStore` can be used to maintain state of a `MetadataStore` across application restarts. +This new `MetadataStore` implementation can be used with adapters such as: + +* Twitter Inbound Adapters +* Feed Inbound Channel Adapter + + + +New queue-based components have been added. +The `` and the `` components are provided to perform 'right pop' and 'left push' operations on a Redis List, respectively. + +For more information see <>. + +[[x3.0-hcr]] +===== Header Channel Registry + +It is now possible to instruct the framework to store reply and error channels in a registry for later resolution. +This is useful for cases where the `replyChannel` or `errorChannel` might be lost; for example when serializing a message. +See <> for more information. + +[[x3.0-configurable-mongo-MS]] +===== MongoDB support: New ConfigurableMongoDbMessageStore + +In addition to the existing `eMongoDbMessageStore`, a new `ConfigurableMongoDbMessageStore` has been introduced. +This provides a more robust and flexible implementation of `MessageStore` for MongoDB. +It does not have backward compatibility, with the existing store, but it is recommended to use it for new applications. +Existing applications can use it, but messages in the old store will not be available. +See <> for more information. + +[[x3.0-syslog]] +===== Syslog Support + +Building on the 2.2 `SyslogToMapTransformer` Spring Integration 3.0 now introduces `UDP` and `TCP` inbound channel adapters especially tailored for receiving SYSLOG messages. +For more information, see<>. + +[[x3.0-tail]] +===== 'Tail' Support + +File 'tail'ing inbound channel adapters are now provided to generate messages when lines are added to the end of text files; see <>. + +[[x3.0-jmx]] +===== JMX Support + +* A new `` is provided; this adapter queries the JMX MBean tree and sends a message with a payload that is the graph of objects that matches the query. +By default the MBeans are mapped to primitives and simple Objects like Map, List and arrays - permitting simple transformation, for example, to JSON. + +* The `IntegrationMBeanExporter` now allows the configuration of a custom `ObjectNamingStrategy` using the `naming-strategy` attribute. + +For more information, see <>. + +[[x3.0-tcp-events]] +===== TCP/IP Connection Events and Connection Management + +`TcpConnection` s now emit `ApplicationEvent` s (specifically `TcpConnectionEvent` s) when connections are opened, closed, or an exception occurs. +This allows applications to be informed of changes to TCP connections using the normal Spring `ApplicationListener` mechanism. + +`AbstractTcpConnection` has been renamed `TcpConnectionSupport`; custom connections that are subclasses of this class, can use its methods to publish events. +Similarly, `AbstractTcpConnectionInterceptor` has been renamed to `TcpConnectionInterceptorSupport`. + +In addition, a new `` is provided; by default, this adapter sends all `TcpConnectionEvent` s to a `Channel`. + +Further, the TCP Connection Factories, now provide a new method `getOpenConnectionIds()`, which returns a list of identifiers for all open connections; this allows applications, for example, to broadcast to all open connections. + +Finally, the connection factories also provide a new method `closeConnection(String connectionId)` which allows applications to explicitly close a connection using its ID. + +For more information see <>. + +[[x3.0-inbound-script]] +===== Inbound Channel Adapter Script Support + +The `` now supports `` and `