Migrate to Antora Documentation

* Use `providers.provider` for `modifiedFiles`.
This defers the looking up of `modifiedFiles` until it is used. It
also allows other tasks to be ran from the non-primary work tree.
Working in another work tree is essential for Antora which will clone
each branch/tag into a new work tree to process it.

* Migrate Structure

* Insert explicit ids for headers

* Fix image::image

* Copy default antora files

* Fix indentation for all pages

* Split files

* Generate a default navigation

* Remove includes

* Fix cross references

* Enable Section Summary TOC for small pages

* Polish nav.adoc

* Fix duplicate ids

* Escape {firstname} and {lastname}

* Remove links to htmlsingle and pdf Formats

* Fix broken links

* Disable attributes for ${debezium-version}

* Migrate to Asciidoctor Tabs

* Move to src/reference/antora

* Remove Asciidoctor Build

* deploy-docs only spring-projects
This commit is contained in:
Rob Winch
2023-08-10 14:10:47 -05:00
committed by GitHub
parent f9dc75c739
commit eb6ddfe429
319 changed files with 21512 additions and 22487 deletions

32
.github/workflows/deploy-docs.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: Deploy Docs
on:
push:
branches-ignore: [ gh-pages ]
tags: '**'
repository_dispatch:
types: request-build-reference # legacy
#schedule:
#- cron: '0 10 * * *' # Once per day at 10am UTC
workflow_dispatch:
permissions:
actions: write
jobs:
build:
runs-on: ubuntu-latest
if: github.repository_owner == 'spring-projects'
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: docs-build
fetch-depth: 1
- name: Dispatch (partial build)
if: github.ref_type == 'branch'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD) -f build-refname=${{ github.ref_name }}
- name: Dispatch (full build)
if: github.ref_type == 'tag'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD)

View File

@@ -36,7 +36,7 @@ jobs:
debug: false
concurrent: true
gradle-build-scan-report: false
arguments: checkAsciidocLinks check
arguments: check
- name: Capture Test Results
if: failure()

View File

@@ -96,10 +96,10 @@ To build api Javadoc (results will be in `build/api`):
./gradlew api
----
To build the reference documentation (results will be in `build/docs/asciidoc` and `build/docs/asciidocPdf`):
To build the reference documentation (results will be in `build/site`):
----
./gradlew reference
./gradlew antora
----
To build complete distribution including `-dist`, `-docs`, and `-schema` zip files (results will be in `build/distributions`):

View File

@@ -58,7 +58,7 @@ Please see our [Security policy](https://github.com/spring-projects/spring-integ
# Documentation
The Spring Integration maintains reference documentation ([published](https://docs.spring.io/spring-integration/docs/current/reference/html/) and [source](src/reference/asciidoc)), GitHub [wiki pages](https://github.com/spring-projects/spring-integration/wiki), and an [API reference](https://docs.spring.io/spring-integration/docs/current/api/).
The Spring Integration maintains reference documentation ([published](https://docs.spring.io/spring-integration/reference/) and [source](src/reference/antora)), GitHub [wiki pages](https://github.com/spring-projects/spring-integration/wiki), and an [API reference](https://docs.spring.io/spring-integration/docs/current/api/).
There are also [guides and tutorials](https://spring.io/guides) across Spring projects.
@@ -90,9 +90,9 @@ To build api Javadoc (results will be in `build/api`):
./gradlew api
To build the reference documentation (results will be in `build/docs/asciidoc` and `build/docs/asciidocPdf`):
To build the reference documentation (results will be in `build/site`):
./gradlew reference
./gradlew antora
To build complete distribution including `-dist`, `-docs`, and `-schema` zip files (results will be in `build/distributions`):

View File

@@ -15,14 +15,15 @@ buildscript {
}
plugins {
id 'base'
id 'org.sonarqube' version '4.3.0.3225'
id 'io.spring.nohttp' version '0.0.11' apply false
id 'org.ajoberstar.grgit' version '4.1.1'
id 'io.spring.dependency-management' version '1.1.2'
id 'com.jfrog.artifactory' version '4.33.1' apply false
id 'org.jetbrains.dokka' version "1.8.20"
id 'org.asciidoctor.jvm.pdf' version '3.3.2'
id 'org.asciidoctor.jvm.convert' version '3.3.2'
id 'org.antora' version '1.0.0'
id 'io.spring.antora.generate-antora-yml' version '0.0.1'
}
if (isCI) {
@@ -44,8 +45,8 @@ ext {
linkScmConnection = 'scm:git:git://github.com/spring-projects/spring-integration.git'
linkScmDevConnection = 'scm:git:ssh://git@github.com:spring-projects/spring-integration.git'
modifiedFiles =
files(grgit.status().unstaged.modified).filter { f -> f.name.endsWith('.java') || f.name.endsWith('.kt') }
modifiedFiles = providers.provider {
files(grgit.status().unstaged.modified).filter { f -> f.name.endsWith('.java') || f.name.endsWith('.kt') } }
apacheSshdVersion = '2.10.0'
artemisVersion = '2.29.0'
@@ -289,7 +290,7 @@ configure(javaProjects) { subproject ->
task updateCopyrights {
onlyIf { !isCI }
inputs.files(modifiedFiles.filter { f -> f.path.contains(subproject.name) })
inputs.files(modifiedFiles.map(files -> files.filter { f -> f.path.contains(subproject.name) }))
outputs.dir('build/classes')
doLast {
@@ -337,7 +338,7 @@ configure(javaProjects) { subproject ->
}
}
task testAll(type: Test, dependsOn: [':checkAsciidocLinks', 'check'])
task testAll(type: Test, dependsOn: ['check'])
gradle.taskGraph.whenReady { graph ->
if (graph.hasTask(testAll)) {
@@ -1237,7 +1238,7 @@ task schemaZip(type: Zip) {
}
}
task docsZip(type: Zip, dependsOn: [reference, dokkaHtmlMultiModule]) {
task docsZip(type: Zip, dependsOn: [dokkaHtmlMultiModule]) {
group = 'Distribution'
archiveClassifier = 'docs'
description = "Builds -${archiveClassifier} archive containing api and reference " +
@@ -1251,16 +1252,6 @@ task docsZip(type: Zip, dependsOn: [reference, dokkaHtmlMultiModule]) {
into 'api'
}
from('build/docs/asciidoc') {
into 'reference/html'
}
from('build/docs/asciidocPdf') {
include 'index-single.pdf'
rename 'index-single.pdf', 'spring-integration-reference.pdf'
into 'reference/pdf'
}
from(dokkaHtmlMultiModule.outputDirectory) {
into 'kdoc-api'
}

View File

@@ -1,56 +1,46 @@
ext {
backendVersion = '0.0.5'
micrometerDocsVersion='1.0.1'
}
antora {
version = '3.2.0-alpha.2'
playbook = file('src/reference/antora/antora-playbook.yml')
options = ['to-dir' : project.layout.buildDirectory.dir('site').get().toString(), clean: true, fetch: !project.gradle.startParameter.offline, stacktrace: true]
dependencies = [
'@antora/atlas-extension': '1.0.0-alpha.1',
'@antora/collector-extension': '1.0.0-alpha.3',
'@asciidoctor/tabs': '1.0.0-beta.3',
'@springio/antora-extensions': '1.4.2',
'@springio/asciidoctor-extensions': '1.0.0-alpha.8',
]
}
tasks.named("generateAntoraYml") {
asciidocAttributes = project.provider( {
return ['project-version' : project.version ]
} )
baseAntoraYmlFile = file('src/reference/antora/antora.yml')
}
tasks.create(name: 'createAntoraPartials', type: Sync) {
from { tasks.filterMetricsDocsContent.outputs }
into layout.buildDirectory.dir('generated-antora-resources/modules/ROOT/partials')
}
tasks.create('generateAntoraResources') {
dependsOn 'createAntoraPartials'
dependsOn 'generateAntoraYml'
}
configurations {
asciidoctorExtensions
micrometerDocs
}
dependencies {
asciidoctorExtensions "io.spring.asciidoctor.backends:spring-asciidoctor-backends:$backendVersion"
micrometerDocs "io.micrometer:micrometer-docs-generator:$micrometerDocsVersion"
}
task checkAsciidocLinks {
inputs.dir('src/reference/asciidoc')
doLast {
def errors = new ArrayList<>();
errors.add('*** Anchor reference errors found:')
inputs.files.filter{ f -> f.path.endsWith('.adoc') }.each { file ->
def doc = file.text
def anchors = new HashSet<>()
def matcher = (doc =~ /\[\[([^]]+)]]/)
while (matcher.find()) {
anchors.add(matcher.group(1))
}
matcher = (doc =~ /<<([^>]+)>>/)
while (matcher.find()) {
def anchor = matcher.group(1);
def hasComma = anchor.contains(',')
if (!anchor.startsWith('./')) {
if (hasComma) {
anchor = anchor.substring(0, anchor.indexOf(","));
}
if (!anchors.contains(anchor)) {
errors.add("\nAnchor '$anchor' not found in '${file.name}', " +
"if in another file, it needs to be qualified with './fileName.adoc#'")
}
}
else {
if (!hasComma) {
errors.add("\nExternal anchor '$anchor' in '${file.name}' should have a textual description (,...)")
}
}
}
}
if (errors.size() > 1) {
throw new InvalidUserDataException(errors.toString())
}
}
}
def observationInputDir = file('spring-integration-core/src/main/java/org/springframework/integration/support/management/observation').absolutePath
def generatedDocsDir = file("$buildDir/reference/generated").absolutePath
@@ -69,82 +59,4 @@ task filterMetricsDocsContent(type: Copy) {
into generatedDocsDir
rename { filename -> filename.replace '_', '' }
filter { line -> line.replaceAll('org.springframework.integration', 'o.s.i') }
}
task prepareDocs(type: Copy) {
dependsOn checkAsciidocLinks, filterMetricsDocsContent
from 'src/reference/asciidoc'
into "$buildDir/reference"
}
asciidoctorPdf {
dependsOn prepareDocs
forkOptions {
jvmArgs '--add-opens', 'java.base/sun.nio.ch=ALL-UNNAMED', '--add-opens', 'java.base/java.io=ALL-UNNAMED'
}
baseDirFollowsSourceFile()
asciidoctorj {
sourceDir "$buildDir/reference"
sources {
include 'index-single.adoc'
}
options doctype: 'book'
attributes 'icons': 'font',
'sectanchors': '',
'sectnums': '',
'toc': '',
'source-highlighter' : 'coderay',
revnumber: project.version,
'project-version': project.version
}
}
asciidoctor {
dependsOn asciidoctorPdf
forkOptions {
jvmArgs '--add-opens', 'java.base/sun.nio.ch=ALL-UNNAMED', '--add-opens', 'java.base/java.io=ALL-UNNAMED'
}
baseDirFollowsSourceFile()
configurations 'asciidoctorExtensions'
sourceDir "$buildDir/reference"
outputOptions {
backends 'spring-html'
}
resources {
from(sourceDir) {
include 'images/*', 'css/**', 'js/**'
}
}
options doctype: 'book', eruby: 'erubis'
attributes 'docinfo': 'shared',
stylesdir: 'css/',
stylesheet: 'stylesheet.css',
'linkcss': true,
'copycss': false,
'icons': 'font',
'sectanchors': '',
'source-highlighter': 'highlight.js',
'highlightjsdir': 'js/highlight',
'highlightjs-theme': 'github',
'idprefix': '',
'idseparator': '-',
'allow-uri-read': '',
'toc': 'left',
'toclevels': '4',
revnumber: project.version,
'project-version': project.version
}
task reference(dependsOn: asciidoctor) {
group = 'Documentation'
description = 'Generate the reference documentation'
}
reference.onlyIf { 'true' != System.env['NO_REFERENCE_TASK'] || project.hasProperty('ignoreEnvToStopReference') }
}

View File

@@ -0,0 +1,41 @@
# PACKAGES antora@3.2.0-alpha.2 @antora/atlas-extension:1.0.0-alpha.1 @antora/collector-extension@1.0.0-alpha.3 @springio/antora-extensions@1.1.0-alpha.2 @asciidoctor/tabs@1.0.0-alpha.12 @opendevise/antora-release-line-extension@1.0.0-alpha.2
#
# The purpose of this Antora playbook is to build the docs in the current branch.
antora:
extensions:
- '@springio/antora-extensions/partial-build-extension'
- require: '@springio/antora-extensions/latest-version-extension'
- require: '@springio/antora-extensions/inject-collector-cache-config-extension'
- '@antora/collector-extension'
- '@antora/atlas-extension'
- require: '@springio/antora-extensions/root-component-extension'
root_component_name: 'integration'
site:
title: Spring Integration
url: https://docs.spring.io/spring-integration/reference/
content:
sources:
- url: ./../../..
branches: HEAD
worktrees: true
start_path: src/reference/antora
asciidoc:
attributes:
page-stackoverflow-url: https://stackoverflow.com/tags/spring-integration
page-pagination: ''
hide-uri-scheme: '@'
tabs-sync-option: '@'
chomp: 'all'
extensions:
- '@asciidoctor/tabs'
- '@springio/asciidoctor-extensions'
sourcemap: true
urls:
latest_version_segment: ''
runtime:
log:
failure_level: warn
format: pretty
ui:
bundle:
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.3.4/ui-bundle.zip

View File

@@ -0,0 +1,20 @@
name: integration
version: true
title: Spring Integration
nav:
- modules/ROOT/nav.adoc
ext:
collector:
run:
command: gradlew -q "-Dorg.gradle.jvmargs=-Xmx3g -XX:+HeapDumpOnOutOfMemoryError" :generateAntoraResources
local: true
scan:
dir: build/generated-antora-resources
asciidoc:
attributes:
attribute-missing: 'warn'
# FIXME: the copyright is not removed
# FIXME: The package is not renamed
chomp: 'all'
snippets: example$docs-src/test/java/org/springframework/integration/docs

View File

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 112 KiB

View File

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

View File

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@@ -0,0 +1,271 @@
* xref:index.adoc[Home]
* xref:preface.adoc[]
* xref:whats-new.adoc[]
* xref:overview.adoc[Overview]
* xref:core.adoc[]
** xref:channel.adoc[]
*** xref:channel/interfaces.adoc[]
*** xref:channel/implementations.adoc[]
*** xref:channel/interceptors.adoc[]
*** xref:channel/template.adoc[]
*** xref:channel/configuration.adoc[]
*** xref:channel/special-channels.adoc[]
** xref:polling-consumer.adoc[]
** xref:channel-adapter.adoc[]
** xref:bridge.adoc[]
* xref:message.adoc[]
* xref:message-routing.adoc[]
** xref:router.adoc[]
*** xref:router/overview.adoc[]
*** xref:router/common-parameters.adoc[]
*** xref:router/implementations.adoc[]
*** xref:router/namespace.adoc[]
*** xref:router/spel.adoc[]
*** xref:router/annotation.adoc[]
*** xref:router/dynamic-routers.adoc[]
*** xref:router/routing-slip.adoc[]
*** xref:router/process-manager.adoc[]
** xref:filter.adoc[]
** xref:splitter.adoc[]
** xref:aggregator.adoc[]
** xref:resequencer.adoc[]
** xref:chain.adoc[]
** xref:scatter-gather.adoc[]
** xref:barrier.adoc[]
* xref:message-transformation.adoc[]
** xref:transformer.adoc[]
** xref:content-enrichment.adoc[]
** xref:claim-check.adoc[]
** xref:codec.adoc[]
* xref:messaging-endpoints.adoc[]
** xref:endpoint.adoc[]
** xref:endpoint-roles.adoc[]
** xref:leadership-event-handling.adoc[]
** xref:gateway.adoc[]
** xref:service-activator.adoc[]
** xref:delayer.adoc[]
** xref:scripting.adoc[]
** xref:groovy.adoc[]
** xref:handler-advice.adoc[]
*** xref:handler-advice/classes.adoc[]
*** xref:handler-advice/reactive.adoc[]
*** xref:handler-advice/context-holder.adoc[]
*** xref:handler-advice/custom.adoc[]
*** xref:handler-advice/other.adoc[]
*** xref:handler-advice/handle-message.adoc[]
*** xref:handler-advice/tx-handle-message.adoc[]
*** xref:handler-advice/advising-filters.adoc[]
*** xref:handler-advice/advising-with-annotations.adoc[]
*** xref:handler-advice/order.adoc[]
*** xref:handler-advice/advised-properties.adoc[]
*** xref:handler-advice/idempotent-receiver.adoc[]
** xref:logging-adapter.adoc[]
*** xref:functions-support.adoc[]
** xref:kotlin-functions.adoc[]
* xref:dsl.adoc[]
** xref:dsl/java-basics.adoc[]
** xref:dsl/java-channels.adoc[]
** xref:dsl/java-pollers.adoc[]
** xref:dsl/java-reactive.adoc[]
** xref:dsl/java-endpoints.adoc[]
** xref:dsl/java-transformers.adoc[]
** xref:dsl/java-inbound-adapters.adoc[]
** xref:dsl/java-routers.adoc[]
** xref:dsl/java-splitters.adoc[]
** xref:dsl/java-aggregators.adoc[]
** xref:dsl/java-handle.adoc[]
** xref:dsl/java-gateway.adoc[]
** xref:dsl/java-log.adoc[]
** xref:dsl/java-intercept.adoc[]
** xref:dsl/java-wiretap.adoc[]
** xref:dsl/java-flows.adoc[]
** xref:dsl/java-function-expression.adoc[]
** xref:dsl/java-subflows.adoc[]
** xref:dsl/java-protocol-adapters.adoc[]
** xref:dsl/java-flow-adapter.adoc[]
** xref:dsl/java-runtime-flows.adoc[]
** xref:dsl/integration-flow-as-gateway.adoc[]
** xref:dsl/java-extensions.adoc[]
** xref:dsl/integration-flows-composition.adoc[]
* xref:groovy-dsl.adoc[]
* xref:kotlin-dsl.adoc[]
* xref:system-management.adoc[]
** xref:metrics.adoc[]
** xref:message-history.adoc[]
** xref:message-store.adoc[]
** xref:meta-data-store.adoc[]
** xref:control-bus.adoc[]
** xref:shutdown.adoc[]
** xref:graph.adoc[]
** xref:integration-graph-controller.adoc[]
* xref:reactive-streams.adoc[]
* xref:native-aot.adoc[]
* xref:endpoint-summary.adoc[]
* xref:amqp.adoc[AMQP Support]
** xref:amqp/inbound-channel-adapter.adoc[]
** xref:amqp/polled-inbound-channel-adapter.adoc[]
** xref:amqp/inbound-gateway.adoc[]
** xref:amqp/inbound-ack.adoc[]
** xref:amqp/outbound-endpoints.adoc[]
** xref:amqp/outbound-channel-adapter.adoc[]
** xref:amqp/outbound-gateway.adoc[]
** xref:amqp/async-outbound-gateway.adoc[]
** xref:amqp/alternative-confirms-returns.adoc[]
** xref:amqp/conversion-inbound.adoc[]
** xref:amqp/content-type-conversion-outbound.adoc[]
** xref:amqp/user-id.adoc[]
** xref:amqp/delay.adoc[]
** xref:amqp/channels.adoc[]
** xref:amqp/message-headers.adoc[]
** xref:amqp/strict-ordering.adoc[]
** xref:amqp/samples.adoc[]
** xref:amqp/rmq-streams.adoc[]
* xref:camel.adoc[]
* xref:cassandra.adoc[]
* xref:debezium.adoc[]
* xref:event.adoc[]
* xref:feed.adoc[]
* xref:file.adoc[]
** xref:file/reading.adoc[]
** xref:file/writing.adoc[]
** xref:file/transforming.adoc[]
** xref:file/splitter.adoc[]
** xref:file/aggregator.adoc[]
** xref:file/remote-persistent-flf.adoc[]
* xref:ftp.adoc[]
** xref:ftp/session-factory.adoc[]
** xref:ftp/advanced-configuration.adoc[]
** xref:ftp/dsf.adoc[]
** xref:ftp/inbound.adoc[]
** xref:ftp/streaming.adoc[]
** xref:ftp/rotating-server-advice.adoc[]
** xref:ftp/max-fetch.adoc[]
** xref:ftp/outbound.adoc[]
** xref:ftp/outbound-gateway.adoc[]
** xref:ftp/session-caching.adoc[]
** xref:ftp/rft.adoc[]
** xref:ftp/session-callback.adoc[]
** xref:ftp/server-events.adoc[]
** xref:ftp/remote-file-info.adoc[]
* xref:graphql.adoc[]
* xref:hazelcast.adoc[]
* xref:http.adoc[]
** xref:http/inbound.adoc[]
** xref:http/outbound.adoc[]
** xref:http/namespace.adoc[]
** xref:http/java-config.adoc[]
** xref:http/timeout.adoc[]
** xref:http/proxy.adoc[]
** xref:http/header-mapping.adoc[]
** xref:http/int-graph-controller.adoc[]
** xref:http/samples.adoc[]
* xref:jdbc.adoc[]
** xref:jdbc/inbound-channel-adapter.adoc[]
** xref:jdbc/outbound-channel-adapter.adoc[]
** xref:jdbc/outbound-gateway.adoc[]
** xref:jdbc/message-store.adoc[]
** xref:jdbc/stored-procedures.adoc[]
** xref:jdbc/lock-registry.adoc[]
** xref:jdbc/metadata-store.adoc[]
* xref:jpa.adoc[]
** xref:jpa/functionality.adoc[]
** xref:jpa/supported-persistence-providers.adoc[]
** xref:jpa/java-implementation.adoc[]
** xref:jpa/namespace-support.adoc[]
** xref:jpa/inbound-channel-adapter.adoc[]
** xref:jpa/outbound-channel-adapter.adoc[]
** xref:jpa/outbound-gateways.adoc[]
* xref:jms.adoc[]
* xref:jmx.adoc[]
* xref:kafka.adoc[]
* xref:mail.adoc[]
* xref:mongodb.adoc[]
* xref:mqtt.adoc[]
* xref:r2dbc.adoc[]
* xref:redis.adoc[]
* xref:resource.adoc[]
* xref:rsocket.adoc[]
* xref:sftp.adoc[]
** xref:sftp/session-factory.adoc[]
** xref:sftp/dsf.adoc[]
** xref:sftp/session-caching.adoc[]
** xref:sftp/rft.adoc[]
** xref:sftp/inbound.adoc[]
** xref:sftp/streaming.adoc[]
** xref:sftp/rotating-server-advice.adoc[]
** xref:sftp/max-fetch.adoc[]
** xref:sftp/outbound.adoc[]
** xref:sftp/outbound-gateway.adoc[]
** xref:sftp/session-callback.adoc[]
** xref:sftp/server-events.adoc[]
** xref:sftp/remote-file-info.adoc[]
* xref:smb.adoc[]
* xref:stomp.adoc[]
* xref:stream.adoc[]
* xref:syslog.adoc[]
* xref:ip.adoc[]
** xref:ip/intro.adoc[]
** xref:ip/udp-adapters.adoc[]
** xref:ip/tcp-connection-factories.adoc[]
** xref:ip/testing-connections.adoc[]
** xref:ip/interceptors.adoc[]
** xref:ip/tcp-events.adoc[]
** xref:ip/tcp-adapters.adoc[]
** xref:ip/tcp-gateways.adoc[]
** xref:ip/correlation.adoc[]
** xref:ip/note-nio.adoc[]
** xref:ip/ssl-tls.adoc[]
** xref:ip/tcp-advanced-techniques.adoc[]
** xref:ip/endpoint-reference.adoc[]
** xref:ip/msg-headers.adoc[]
** xref:ip/annotation.adoc[]
** xref:ip/dsl.adoc[]
* xref:webflux.adoc[]
* xref:web-sockets.adoc[]
* xref:ws.adoc[]
* xref:xml.adoc[]
** xref:xml/xpath-namespace-support.adoc[]
** xref:xml/transformation.adoc[]
** xref:xml/xpath-transformer.adoc[]
** xref:xml/xpath-splitting.adoc[]
** xref:xml/xpath-routing.adoc[]
** xref:xml/xpath-header-enricher.adoc[]
** xref:xml/xpath-filter.adoc[]
** xref:xml/xpath-spel-function.adoc[]
** xref:xml/validating-filter.adoc[]
* xref:xmpp.adoc[]
* xref:zeromq.adoc[]
* xref:zookeeper.adoc[]
* xref:error-handling.adoc[]
* xref:spel.adoc[]
* xref:message-publishing.adoc[]
* xref:transactions.adoc[]
* xref:security.adoc[]
* xref:configuration.adoc[]
** xref:configuration/namespace.adoc[]
** xref:configuration/namespace-taskscheduler.adoc[]
** xref:configuration/global-properties.adoc[]
** xref:configuration/annotations.adoc[]
** xref:configuration/meta-annotations.adoc[]
** xref:configuration/message-mapping-rules.adoc[]
* xref:testing.adoc[]
* xref:samples.adoc[]
* xref:resources.adoc[]
* xref:history.adoc[]
** xref:changes-6.0-6.1.adoc[]
** xref:changes-5.5-6.0.adoc[]
** xref:changes-5.4-5.5.adoc[]
** xref:changes-5.3-5.4.adoc[]
** xref:changes-5.2-5.3.adoc[]
** xref:changes-5.1-5.2.adoc[]
** xref:changes-5.0-5.1.adoc[]
** xref:changes-4.3-5.0.adoc[]
** xref:changes-4.2-4.3.adoc[]
** xref:changes-4.1-4.2.adoc[]
** xref:changes-4.0-4.1.adoc[]
** xref:changes-3.0-4.0.adoc[]
** xref:changes-2.2-3.0.adoc[]
** xref:changes-2.1-2.2.adoc[]
** xref:changes-2.0-2.1.adoc[]
** xref:changes-1.0-2.0.adoc[]
* xref:zip.adoc[]

View File

@@ -1,5 +1,5 @@
[[aggregator]]
=== Aggregator
= Aggregator
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.
@@ -9,7 +9,7 @@ It must hold the messages to be aggregated and determine when the complete group
In order to do so, it requires a `MessageStore`.
[[aggregator-functionality]]
==== Functionality
== Functionality
The Aggregator combines a group of related messages, by correlating and storing them, until the group is deemed to be complete.
At that point, the aggregator creates a single message by processing the whole group and sends the aggregated message as output.
@@ -28,7 +28,7 @@ The default release strategy for the aggregator releases a group when all messag
You can override this default strategy by providing a reference to a custom `ReleaseStrategy` implementation.
[[aggregator-api]]
==== Programming Model
== Programming Model
The Aggregation API consists of a number of classes:
@@ -36,7 +36,8 @@ The Aggregation API consists of a number of classes:
* The `ReleaseStrategy` interface and its default implementation: `SimpleSequenceSizeReleaseStrategy`
* The `CorrelationStrategy` interface and its default implementation: `HeaderAttributeCorrelationStrategy`
===== `AggregatingMessageHandler`
[[aggregatingmessagehandler]]
=== `AggregatingMessageHandler`
The `AggregatingMessageHandler` (a subclass of `AbstractCorrelatingMessageHandler`) is a `MessageHandler` implementation, encapsulating the common functionality of an aggregator (and other correlating use cases), which are as follows:
@@ -51,7 +52,6 @@ The responsibility for deciding whether the message group can be released is del
The following listing shows a brief highlight of the base `AbstractAggregatingMessageGroupProcessor` (the responsibility for implementing the `aggregatePayloads` method is left to the developer):
====
[source,java]
----
public abstract class AbstractAggregatingMessageGroupProcessor
@@ -65,7 +65,6 @@ public abstract class AbstractAggregatingMessageGroupProcessor
}
----
====
See `DefaultAggregatingMessageGroupProcessor`, `ExpressionEvaluatingMessageGroupProcessor` and `MethodInvokingMessageGroupProcessor` as out-of-the-box implementations of the `AbstractAggregatingMessageGroupProcessor`.
@@ -80,7 +79,6 @@ The `Function<MessageGroup, Map<String, Object>>` strategy is available as the `
The `CorrelationStrategy` is owned by the `AbstractCorrelatingMessageHandler` and has a default value based on the `IntegrationMessageHeaderAccessor.CORRELATION_ID` message header, as the following example shows:
====
[source,java]
----
public AbstractCorrelatingMessageHandler(MessageGroupProcessor processor, MessageGroupStore store,
@@ -92,7 +90,6 @@ public AbstractCorrelatingMessageHandler(MessageGroupProcessor processor, Messag
...
}
----
====
As for the 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.
@@ -123,7 +120,7 @@ If the `MessageGroupProcessor` returns a `Message`, a `MessageBuilder.popSequenc
This functionality can be controlled by a new `popSequence` `boolean` property, so the `MessageBuilder.popSequenceDetails()` can be disabled in some scenarios when correlation details have not been populated by the standard splitter.
This property, essentially, undoes what has been done by the nearest upstream `applySequence = true` in the `AbstractMessageSplitter`.
See <<./splitter.adoc#splitter,Splitter>> for more information.
See xref:splitter.adoc[Splitter] for more information.
[[agg-message-collection]]
IMPORTANT: The `SimpleMessageGroup.getMessages()` method returns an `unmodifiableCollection`.
@@ -147,11 +144,11 @@ Starting with version 6.0, the splitting behaviour, described above, works only
Otherwise, with any other `MessageGroupProcessor` implementation that returns a `Collection<Message>`, only a single reply message is emitted with the whole collection of messages as its payload.
Such logic is dictated by the canonical purpose of an aggregator - collect request messages by some key and produce a single grouped message.
===== `ReleaseStrategy`
[[releasestrategy]]
=== `ReleaseStrategy`
The `ReleaseStrategy` interface is defined as follows:
====
[source,java]
----
public interface ReleaseStrategy {
@@ -160,7 +157,6 @@ public interface ReleaseStrategy {
}
----
====
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 is invoked after the arrival of each new message, to decide whether the group is complete or not, as follows:
@@ -171,7 +167,6 @@ This method is invoked after the arrival of each new message, to decide whether
The following example shows how to use the `@ReleaseStrategy` annotation for a `List` of type `Message`:
====
[source,java]
----
public class MyReleaseStrategy {
@@ -180,11 +175,9 @@ public class MyReleaseStrategy {
public boolean canMessagesBeReleased(List<Message<?>>) {...}
}
----
====
The following example shows how to use the `@ReleaseStrategy` annotation for a `List` of type `String`:
====
[source,java]
----
public class MyReleaseStrategy {
@@ -193,7 +186,6 @@ public class MyReleaseStrategy {
public boolean canMessagesBeReleased(List<String>) {...}
}
----
====
Based on the signatures in the preceding two examples, the POJO-based release strategy is 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`).
This satisfies the majority of use cases.
@@ -221,7 +213,7 @@ IMPORTANT: To facilitate discarding of late-arriving messages, the aggregator mu
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 once a point has been reach after which late messages are not expected to arrive.
For information about configuring a reaper, see <<reaper>>.
For information about configuring a reaper, see xref:aggregator.adoc#reaper[Managing State in an Aggregator: `MessageGroupStore`].
Spring Integration provides an implementation for `ReleaseStrategy`: `SimpleSequenceSizeReleaseStrategy`.
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.
@@ -233,18 +225,18 @@ This operation can be expensive.
If you are aggregating large groups, you don't need to release partial groups, and you don't need to detect/reject duplicate sequences, consider using the `SimpleSequenceSizeReleaseStrategy` instead - it is much more efficient for these use cases, and is the default since _version 5.0_ when partial group release is not specified.
===== Aggregating Large Groups
[[aggregating-large-groups]]
=== Aggregating Large Groups
The 4.3 release changed the default `Collection` for messages in a `SimpleMessageGroup` to `HashSet` (it was previously a `BlockingQueue`).
This was expensive when removing individual messages from large groups (an O(n) linear scan was required).
Although the hash set is generally much faster to remove, it can be expensive for large messages, because the hash has to be calculated on both inserts and removes.
If you have messages that are expensive to hash, consider using some other collection type.
As discussed in <<./message-store.adoc#message-group-factory,Using `MessageGroupFactory`>>, a `SimpleMessageGroupFactory` is provided so that you can select the `Collection` that best suits your needs.
As discussed in xref:message-store.adoc#message-group-factory[Using `MessageGroupFactory`], a `SimpleMessageGroupFactory` is provided so that you can select the `Collection` that best suits your needs.
You can also provide your own factory implementation to create some other `Collection<Message<?>>`.
The following example shows how to configure an aggregator with the previous implementation and a `SimpleSequenceSizeReleaseStrategy`:
====
[source, xml]
----
<int:aggregator input-channel="aggregate"
@@ -260,17 +252,16 @@ The following example shows how to configure an aggregator with the previous imp
<bean id="releaser" class="SimpleSequenceSizeReleaseStrategy" />
----
====
NOTE: If the filter endpoint is involved in the flow upstream of an aggregator, the sequence size release strategy (fixed or based on the `sequenceSize` header) is not going to serve its purpose because some messages from a sequence may be discarded by the filter.
In this case it is recommended to choose another `ReleaseStrategy`, or use compensation messages sent from a discard sub-flow carrying some information in their content to be skipped in a custom complete group function.
See <<./filter.adoc#filter,Filter>> for more information.
See xref:filter.adoc[Filter] for more information.
===== Correlation Strategy
[[correlation-strategy]]
=== Correlation Strategy
The `CorrelationStrategy` interface is defined as follows:
====
[source,java]
----
public interface CorrelationStrategy {
@@ -279,7 +270,6 @@ public interface CorrelationStrategy {
}
----
====
The method returns an `Object` that 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()`.
@@ -292,7 +282,8 @@ This implementation returns the value of one of the message headers (whose name
By default, the correlation strategy is a `HeaderAttributeCorrelationStrategy` that returns the value of the `CORRELATION_ID` header attribute.
If you have a custom header name you would like to use for correlation, you can configure it on an instance of `HeaderAttributeCorrelationStrategy` and provide that as a reference for the aggregator's correlation strategy.
===== Lock Registry
[[lock-registry]]
=== Lock Registry
Changes to groups are thread safe.
So, when you send messages for the same correlation ID concurrently, only one of them will be processed in the aggregator, making it effectively as a *single-threaded per message group*.
@@ -301,23 +292,20 @@ A `DefaultLockRegistry` is used by default (in-memory).
For synchronizing updates across servers where a shared `MessageGroupStore` is being used, you must configure a shared lock registry.
[[aggregator-deadlocks]]
===== Avoiding Deadlocks
=== Avoiding Deadlocks
As discussed above, when message groups are mutated (messages added or released) a lock is held.
Consider the following flow:
====
[source]
----
...->aggregator1-> ... ->aggregator2-> ...
----
====
If there are multiple threads, **and the aggregators share a common lock registry**, it is possible to get a deadlock.
This will cause hung threads and `jstack <pid>` might present a result such as:
====
[source]
----
Found one Java-level deadlock:
@@ -329,7 +317,6 @@ Found one Java-level deadlock:
waiting for ownable synchronizer 0x000000076c1ccc00, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
which is held by "t2"
----
====
There are several ways to avoid this problem:
@@ -342,17 +329,16 @@ Of course, the first solution above does not apply in this case.
[[aggregator-java-dsl]]
==== Configuring an Aggregator in Java DSL
== Configuring an Aggregator in Java DSL
See <<./dsl.adoc#java-dsl-aggregators,Aggregators and Resequencers>> for how to configure an aggregator in Java DSL.
See xref:dsl/java-aggregators.adoc[Aggregators and Resequencers] for how to configure an aggregator in Java DSL.
[[aggregator-xml]]
===== Configuring an Aggregator with XML
=== Configuring an Aggregator with XML
Spring Integration supports the configuration of an aggregator with XML through the `<aggregator/>` element.
The following example shows an example of an aggregator:
====
[source,xml]
----
<channel id="inputChannel"/>
@@ -419,7 +405,7 @@ Optional.
<6> A reference to a `MessageGroupStore` used to store groups of messages under their correlation key until they are complete.
Optional.
By default, it is a volatile in-memory store.
See <<./message-store.adoc#message-store,Message Store>> for more information.
See xref:message-store.adoc[Message Store] for more information.
<7> The 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 https://docs.spring.io/spring-integration/api/org/springframework/integration/store/MessageGroupStore.html#expireMessageGroups-long[`MessageGroupStore.expireMessageGroups(long)`]).
@@ -477,7 +463,7 @@ Note that the actual time to expire an empty group is also affected by the reape
It 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 `ZookeeperLockRegistry`, ensures only one instance of the aggregator can operate on a group concurrently.
See <<./redis.adoc#redis-lock-registry,Redis Lock Registry>> or <<./zookeeper.adoc#zk-lock-registry,Zookeeper Lock Registry>> for more information.
See xref:redis.adoc#redis-lock-registry[Redis Lock Registry] or xref:zookeeper.adoc#zk-lock-registry[Zookeeper Lock Registry] for more information.
<21> A timeout (in milliseconds) to force the `MessageGroup` complete when the `ReleaseStrategy` does not release the group when the current message arrives.
This attribute provides a built-in time-based 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 which counts from the time the last message arrived.
To set up a timeout which counts from the time the `MessageGroup` was created see `group-timeout-expression` information.
@@ -488,7 +474,7 @@ Doing so effectively disables the aggregator, because every message group is imm
You can, however, conditionally set it to zero (or a negative value) by 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 <<agg-and-group-to>> for more information.
See xref:aggregator.adoc#agg-and-group-to[Aggregator and Group Timeout] for more information.
It is 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.
@@ -516,7 +502,6 @@ It 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`, and `discard` operations.
Only this sub-element or `<expire-transactional/>` is allowed.
A transaction `Advice` can also be configured here by using the Spring `tx` namespace.
====
[[aggregator-expiring-groups]]
[IMPORTANT]
@@ -558,21 +543,18 @@ With the aggregator, groups expired using this technique will either be discarde
We generally recommend using a `ref` attribute if a custom aggregator handler implementation may be referenced in other `<aggregator>` definitions.
However, if a custom aggregator implementation is only being used by a single definition of the `<aggregator>`, you can use an inner bean definition (starting with version 1.0.3) to configure the aggregation POJO within the `<aggregator>` element, as the following example shows:
====
[source,xml]
----
<aggregator input-channel="input" method="sum" output-channel="output">
<beans:bean class="org.foo.PojoAggregator"/>
</aggregator>
----
====
NOTE: Using both a `ref` attribute and an inner bean definition in the same `<aggregator>` configuration is not allowed, as it creates an ambiguous condition.
In such cases, an Exception is thrown.
The following example shows an implementation of the aggregator bean:
====
[source,java]
----
public class PojoAggregator {
@@ -586,11 +568,9 @@ public class PojoAggregator {
}
}
----
====
An implementation of the completion strategy bean for the preceding example might be as follows:
====
[source,java]
----
public class PojoReleaseStrategy {
@@ -604,13 +584,11 @@ public class PojoReleaseStrategy {
}
}
----
====
NOTE: Wherever it makes sense to do so, the release strategy method and the aggregator method can be combined into a single bean.
An implementation of the correlation strategy bean for the example above might be as follows:
====
[source,java]
----
public class PojoCorrelationStrategy {
@@ -620,7 +598,6 @@ public class PojoCorrelationStrategy {
}
}
----
====
The aggregator in the preceding example would group numbers by some criterion (in this case, the remainder after dividing by ten) and hold the group until the sum of the numbers provided by the payloads exceeds a certain value.
@@ -628,7 +605,7 @@ NOTE: Wherever it makes sense to do so, the release strategy method, the correla
(Actually, all of them or any two of them can be combined.)
[[aggregator-spel]]
====== Aggregators and Spring Expression Language (SpEL)
==== Aggregators and Spring Expression Language (SpEL)
Since Spring Integration 2.0, you can handle the various strategies (correlation, release, and aggregation) with https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions[SpEL], which we recommend if the logic behind such a release strategy is relatively simple.
Suppose you have a legacy component that was designed to receive an array of objects.
@@ -638,7 +615,6 @@ First, we need to extract individual messages from the list.
Second, we need to extract the payload of each message and assemble the array of objects.
The following example solves both problems:
====
[source,java]
----
public String[] processRelease(List<Message<String>> messages){
@@ -649,19 +625,16 @@ public String[] processRelease(List<Message<String>> messages){
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.
The following example shows how to do so:
====
[source,xml]
----
<int:aggregator input-channel="aggChannel"
output-channel="replyChannel"
expression="#this.![payload].toArray()"/>
----
====
In the preceding configuration, we use a https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions[collection projection] expression to assemble a new collection from the payloads of all the messages in the list and then transform it to an array, thus achieving the same result as the earlier Java code.
@@ -669,12 +642,10 @@ You can apply the same expression-based approach when dealing with custom releas
Instead of defining a bean for a custom `CorrelationStrategy` in the `correlation-strategy` attribute, you can implement your simple correlation logic as a SpEL expression and configure it in the `correlation-strategy-expression` attribute, as the following example shows:
====
[source,xml]
----
correlation-strategy-expression="payload.person.id"
----
====
In the preceding example, we assume that the payload has a `person` attribute with an `id`, which is going to be used to correlate messages.
@@ -684,24 +655,21 @@ The `List` of messages can be referenced by using the `message` property of the
NOTE: In releases prior to version 5.0, the root object was the collection of `Message<?>`, as the previous example shows:
====
[source,xml]
----
release-strategy-expression="!messages.?[payload==5].empty"
----
====
In the preceding example, the root object of the SpEL evaluation context is the `MessageGroup` itself, and you are stating that, as soon as there is a message with payload of `5` in this group, the group should be released.
[[agg-and-group-to]]
====== Aggregator and Group Timeout
==== Aggregator and Group Timeout
Starting with version 4.0, two new mutually exclusive attributes have been introduced: `group-timeout` and `group-timeout-expression`.
See <<aggregator-xml>>.
See xref:aggregator.adoc#aggregator-xml[Configuring an Aggregator with XML].
In some cases, you may need to emit the aggregator result (or discard the group) after a timeout if the `ReleaseStrategy` does not release when the current message arrives.
For this purpose, the `groupTimeout` option lets scheduling the `MessageGroup` be forced to complete, as the following example shows:
====
[source,xml]
----
<aggregator input-channel="input" output-channel="output"
@@ -709,7 +677,6 @@ For this purpose, the `groupTimeout` option lets scheduling the `MessageGroup` b
group-timeout-expression="size() ge 2 ? 10000 : -1"
release-strategy-expression="messages[0].headers.sequenceNumber == messages[0].headers.sequenceSize"/>
----
====
With this example, the normal release is 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` forces the group to complete after ten seconds, as long as the group contains at least two Messages.
@@ -721,7 +688,7 @@ If the release strategy still does not release the group, it is expired.
If `send-partial-result-on-expiry` is `true`, existing messages in the (partial) `MessageGroup` are released as a normal aggregator reply message to the `output-channel`.
Otherwise, it is discarded.
There is a difference between `groupTimeout` behavior and `MessageGroupStoreReaper` (see <<aggregator-xml>>).
There is a difference between `groupTimeout` behavior and `MessageGroupStoreReaper` (see xref:aggregator.adoc#aggregator-xml[Configuring an Aggregator with XML]).
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 does not 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).
@@ -729,19 +696,16 @@ Also, the reaper can be used to remove empty groups (empty groups are retained i
Starting with version 5.5, the `groupTimeoutExpression` can be evaluated to a `java.util.Date` instance.
This can be useful in cases like determining a scheduled task moment based on the group creation time (`MessageGroup.getTimestamp()`) instead of a current message arrival as it is calculated when `groupTimeoutExpression` is evaluated to `long`:
====
[source,xml]
----
group-timeout-expression="size() ge 2 ? new java.util.Date(timestamp + 200) : null"
----
====
[[aggregator-annotations]]
===== Configuring an Aggregator with Annotations
=== Configuring an Aggregator with Annotations
The following example shows an aggregator configured with annotations:
====
[source,java]
----
public class Waiter {
@@ -770,7 +734,6 @@ It must be specified if this class is used as an aggregator.
If not present on any method, the aggregator uses the `SimpleSequenceSizeReleaseStrategy`.
<3> An annotation indicating that this method should be used as the correlation strategy of an aggregator.
If no correlation strategy is indicated, the aggregator uses the `HeaderAttributeCorrelationStrategy` based on `CORRELATION_ID`.
====
All of the configuration options provided by the XML element are also available for the `@Aggregator` annotation.
@@ -779,7 +742,6 @@ The aggregator can be either referenced explicitly from XML or, if the `@Message
Annotation configuration (`@Aggregator` and others) for the Aggregator component covers only simple use cases, where most default options are sufficient.
If you need more control over those options when using annotation configuration, consider using a `@Bean` definition for the `AggregatingMessageHandler` and mark its `@Bean` method with `@ServiceActivator`, as the following example shows:
====
[source,java]
----
@ServiceActivator(inputChannel = "aggregatorChannel")
@@ -794,21 +756,19 @@ public MessageHandler aggregator(MessageGroupStore jdbcMessageGroupStore) {
return aggregator;
}
----
====
See <<aggregator-api>> and <<./configuration.adoc#annotations_on_beans,Annotations on `@Bean` Methods>> for more information.
See xref:aggregator.adoc#aggregator-api[Programming Model] and xref:configuration/meta-annotations.adoc#annotations_on_beans[Annotations on `@Bean` Methods] for more information.
NOTE: Starting with version 4.2, the `AggregatorFactoryBean` is available to simplify Java configuration for the `AggregatingMessageHandler`.
[[reaper]]
==== Managing State in an Aggregator: `MessageGroupStore`
== 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 (such as `ReleaseStrategy`) is driven by the principle that the components (whether defined by the framework or by a user) should be able to remain stateless.
All state is carried by the `MessageGroup` and its management is delegated to the `MessageGroupStore`.
The `MessageGroupStore` interface is defined as follows:
====
[source,java]
----
public interface MessageGroupStore {
@@ -836,7 +796,6 @@ public interface MessageGroupStore {
int expireMessageGroups(long timeout);
}
----
====
For more information, see the https://docs.spring.io/spring-integration/api/org/springframework/integration/store/MessageGroupStore.html[Javadoc].
@@ -844,7 +803,6 @@ The `MessageGroupStore` accumulates state information in `MessageGroups` while w
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` lets you register callbacks to apply to its `MessageGroups` when they expire.
The interface is very straightforward, as the following listing shows:
====
[source,java]
----
public interface MessageGroupCallback {
@@ -853,7 +811,6 @@ public interface MessageGroupCallback {
}
----
====
The callback has direct access to the store and the message group so that it can manage the persistent state (for example, by entirely removing the group from the store).
@@ -872,7 +829,6 @@ Thus, it is the user of the store that defines what is meant by message group "`
As a convenience for users, Spring Integration provides a wrapper for the message expiry in the form of a `MessageGroupStoreReaper`, as the following example shows:
====
[source,xml]
----
<bean id="reaper" class="org...MessageGroupStoreReaper">
@@ -884,7 +840,6 @@ As a convenience for users, Spring Integration provides a wrapper for the messag
<task:scheduled ref="reaper" method="run" fixed-rate="10000"/>
</task:scheduled-tasks>
----
====
The reaper is a `Runnable`.
In the preceding example, the message group store's expire method is called every ten seconds.
@@ -901,7 +856,7 @@ If the flag is set to `true`, then, when the expiry callback is invoked, any unm
IMPORTANT: Since the `MessageGroupStoreReaper` is called from a scheduled task, and may result in the production of a message (depending on the `sendPartialResultOnExpiry` option) to a downstream integration flow, it is recommended to supply a custom `TaskScheduler` with a `MessagePublishingErrorHandler` to handler exceptions via an `errorChannel`, as it might be expected by the regular aggregator release functionality.
The same logic applies for group timeout functionality which also relies on a `TaskScheduler`.
See <<./error-handling.adoc#error-handling,Error Handling>> for more information.
See xref:scatter-gather.adoc#scatter-gather-error-handling[Error Handling] for more information.
[IMPORTANT]
=====
@@ -912,11 +867,11 @@ Messages with the same correlation key are stored in the same message group.
Some `MessageStore` implementations allow using the same physical resources, by partitioning the data.
For example, the `JdbcMessageStore` has a `region` property, and the `MongoDbMessageStore` has a `collectionName` property.
For more information about the `MessageStore` interface and its implementations, see <<./message-store.adoc#message-store,Message Store>>.
For more information about the `MessageStore` interface and its implementations, see xref:message-store.adoc[Message Store].
=====
[[flux-aggregator]]
==== Flux Aggregator
== Flux Aggregator
In version 5.2, the `FluxAggregatorMessageHandler` component has been introduced.
It is based on the Project Reactor `Flux.groupBy()` and `Flux.window()` operators.
@@ -932,7 +887,6 @@ This `Flux` in the output message payload must be subscribed and processed downs
Such a logic can be customized (or superseded) by the `setCombineFunction(Function<Flux<Message<?>>, Mono<Message<?>>>)` configuration option of the `FluxAggregatorMessageHandler`.
For example, if we would like to have a `List` of payloads in the final message, we can configure a `Flux.collectList()` like this:
====
[source,java]
----
fluxAggregatorMessageHandler.setCombineFunction(
@@ -942,7 +896,6 @@ fluxAggregatorMessageHandler.setCombineFunction(
.collectList()
.map(GenericMessage::new));
----
====
There are several options in the `FluxAggregatorMessageHandler` to select an appropriate window strategy:
@@ -958,7 +911,6 @@ Since this component is a `MessageHandler` implementation it can simply be used
With Java DSL it can be used from the `.handle()` EIP-method.
The sample below demonstrates how we can register an `IntegrationFlow` at runtime and how a `FluxAggregatorMessageHandler` can be correlated with a splitter upstream:
====
[source,java]
----
IntegrationFlow fluxFlow =
@@ -976,14 +928,13 @@ Flux<Message<?>> window =
registration.getMessagingTemplate()
.convertSendAndReceive(new Integer[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, Flux.class);
----
====
[[agg-message-group-condition]]
==== Condition on the Message Group
== Condition on the Message Group
Starting with version 5.5, an `AbstractCorrelatingMessageHandler` (including its Java & XML DSLs) exposes a `groupConditionSupplier` option of the `BiFunction<Message<?>, String, String>` implementation.
This function is used on each message added to the group and a result condition sentence is stored into the group for future consideration.
The `ReleaseStrategy` may consult this condition instead of iterating over all the messages in the group.
See `GroupConditionProvider` JavaDocs and <<./message-store.adoc#message-group-condition, Message Group Condition>> for more information.
See `GroupConditionProvider` JavaDocs and xref:message-store.adoc#message-group-condition[Message Group Condition] for more information.
See also <<./file.adoc#file-aggregator, File Aggregator>>.
See also xref:file/aggregator.adoc[File Aggregator].

View File

@@ -0,0 +1,49 @@
[[amqp]]
= AMQP (RabbitMQ) Support
Spring Integration provides channel adapters for receiving and sending messages by using the Advanced Message Queuing Protocol (AMQP).
You need to include this dependency into your project:
[tabs]
======
Maven::
+
[source, xml, subs="normal", role="primary"]
----
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-amqp</artifactId>
<version>{project-version}</version>
</dependency>
----
Gradle::
+
[source, groovy, subs="normal", role="secondary"]
----
compile "org.springframework.integration:spring-integration-amqp:{project-version}"
----
======
The following adapters are available:
* xref:amqp/inbound-channel-adapter.adoc[Inbound Channel Adapter]
* xref:amqp/inbound-gateway.adoc[Inbound Gateway]
* xref:amqp/outbound-channel-adapter.adoc[Outbound Channel Adapter]
* xref:amqp/outbound-gateway.adoc[Outbound Gateway]
* xref:amqp-async-outbound-gateway[Async Outbound Gateway]
* xref:amqp/rmq-streams.adoc#rmq-stream-inbound-channel-adapter[RabbitMQ Stream Queue Inbound Channel Adapter]
* xref:amqp/rmq-streams.adoc#rmq-stream-outbound-channel-adapter[RabbitMQ Stream Queue Outbound Channel Adapter]
Spring Integration also provides a point-to-point message channel and a publish-subscribe message channel backed by AMQP Exchanges and Queues.
To provide AMQP support, Spring Integration relies on (https://projects.spring.io/spring-amqp[Spring AMQP]), which applies core Spring concepts to the development of AMQP-based messaging solutions.
Spring AMQP provides similar semantics to (https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#jms[Spring JMS]).
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:
You should familiarize yourself with the https://docs.spring.io/spring-amqp/reference/html/[reference documentation of the Spring AMQP project].
It provides much more in-depth information about Spring's integration with AMQP in general and RabbitMQ in particular.

View File

@@ -0,0 +1,31 @@
[[alternative-confirms-returns]]
= Alternative Mechanism for Publisher Confirms and Returns
When the connection factory is configured for publisher confirms and returns, the sections above discuss the configuration of message channels to receive the confirms and returns asynchronously.
Starting with version 5.4, there is an additional mechanism which is generally easier to use.
In this case, do not configure a `confirm-correlation-expression` or the confirm and return channels.
Instead, add a `CorrelationData` instance in the `AmqpHeaders.PUBLISH_CONFIRM_CORRELATION` header; you can then wait for the result(s) later, by checking the state of the future in the `CorrelationData` instances for which you have sent messages.
The `returnedMessage` field will always be populated (if a message is returned) before the future is completed.
[source, java]
----
CorrelationData corr = new CorrelationData("someId"); // <--- Unique "id" is required for returns
someFlow.getInputChannel().send(MessageBuilder.withPayload("test")
.setHeader("rk", "someKeyThatWontRoute")
.setHeader(AmqpHeaders.PUBLISH_CONFIRM_CORRELATION, corr)
.build());
...
try {
Confirm Confirm = corr.getFuture().get(10, TimeUnit.SECONDS);
Message returned = corr.getReturnedMessage();
if (returned !- null) {
// message could not be routed
}
}
catch { ... }
----
To improve performance, you may wish to send multiple messages and wait for the confirmations later, rather than one-at-a-time.
The returned message is the raw message after conversion; you can sub-class a `CorrelationData` with whatever additional data you need.

View File

@@ -0,0 +1,185 @@
[[amqp-async-outbound-gateway]]
= Asynchronous Outbound Gateway
The gateway discussed in the previous section is synchronous, in that the sending thread is suspended until a
reply is received (or a timeout occurs).
Spring Integration version 4.3 added an asynchronous gateway, which uses the `AsyncRabbitTemplate` from Spring AMQP.
When a message is sent, the thread returns immediately after the send operation completes, and, when the message is received, the reply is sent on the template's listener container thread.
This can be useful when the gateway is invoked on a poller thread.
The thread is released and is available for other tasks in the framework.
The following listing shows the possible configuration options for an AMQP asynchronous outbound gateway:
[tabs]
======
Java DSL::
+
[source,java,role="primary"]
----
@Configuration
public class AmqpAsyncApplication {
@Bean
public IntegrationFlow asyncAmqpOutbound(AsyncRabbitTemplate asyncRabbitTemplate) {
return f -> f
.handle(Amqp.asyncOutboundGateway(asyncRabbitTemplate)
.routingKey("queue1")); // default exchange - route to queue 'queue1'
}
@MessagingGateway(defaultRequestChannel = "asyncAmqpOutbound.input")
public interface MyGateway {
String sendToRabbit(String data);
}
}
----
Java::
+
[source,java,role="secondary"]
----
@Configuration
public class AmqpAsyncConfig {
@Bean
@ServiceActivator(inputChannel = "amqpOutboundChannel")
public AsyncAmqpOutboundGateway amqpOutbound(AsyncRabbitTemplate asyncTemplate) {
AsyncAmqpOutboundGateway outbound = new AsyncAmqpOutboundGateway(asyncTemplate);
outbound.setRoutingKey("foo"); // default exchange - route to queue 'foo'
return outbound;
}
@Bean
public AsyncRabbitTemplate asyncTemplate(RabbitTemplate rabbitTemplate,
SimpleMessageListenerContainer replyContainer) {
return new AsyncRabbitTemplate(rabbitTemplate, replyContainer);
}
@Bean
public SimpleMessageListenerContainer replyContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(ccf);
container.setQueueNames("asyncRQ1");
return container;
}
@Bean
public MessageChannel amqpOutboundChannel() {
return new DirectChannel();
}
}
----
XML::
+
[source,xml,role="secondary"]
----
<int-amqp:outbound-async-gateway id="asyncOutboundGateway" <1>
request-channel="myRequestChannel" <2>
async-template="" <3>
exchange-name="" <4>
exchange-name-expression="" <5>
order="1" <6>
reply-channel="" <7>
reply-timeout="" <8>
requires-reply="" <9>
routing-key="" <10>
routing-key-expression="" <11>
default-delivery-mode"" <12>
confirm-correlation-expression="" <13>
confirm-ack-channel="" <14>
confirm-nack-channel="" <15>
confirm-timeout="" <16>
return-channel="" <17>
lazy-connect="true" /> <18>
----
======
<1> The 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 `AsyncRabbitTemplate`.
Optional (it defaults to `asyncRabbitTemplate`).
<4> The name of the AMQP exchange to which messages should be sent.
If not provided, messages are 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 are sent, with the message as the root object.
If not provided, messages are 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 failover.
Optional (it defaults to `Ordered.LOWEST_PRECEDENCE [=Integer.MAX_VALUE]`).
<7> Message channel to which replies should be sent after being received from an AMQP queue and converted.
Optional.
<8> The time the gateway waits 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.
The default is infinity.
<9> When no reply message is received within the `AsyncRabbitTemplate`'s `receiveTimeout` property and this setting is `true`, the gateway sends an error message to the inbound message's `errorChannel` header.
When no reply message is received within the `AsyncRabbitTemplate`'s `receiveTimeout` property and this setting is `false`, the gateway sends an error message to the default `errorChannel` (if available).
It defaults to `true`.
<10> The routing-key to use when sending Messages.
By default, this is 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 (for example, 'payload.key').
By default, this is 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.
If the Spring Integration message header (`amqp_deliveryMode`) is present, the `DefaultHeaderMapper` sets the value.
If this attribute is not supplied and the header mapper does not set it, the default depends on the underlying Spring AMQP `MessagePropertiesConverter` used by the `RabbitTemplate`.
If that is not customized, the default is `PERSISTENT`.
Optional.
<13> An expression that defines correlation data.
When provided, this configures the underlying AMQP template to receive publisher confirmations.
Requires a dedicated `RabbitTemplate` and a `CachingConnectionFactory` with its `publisherConfirms` property set to `true`.
When a publisher confirmation is received and correlation data is supplied, the confirmation is written to either the `confirm-ack-channel` or the `confirm-nack-channel`, depending on the confirmation type.
The payload of the confirmation is the correlation data as defined by this expression, and the message has its 'amqp_publishConfirm' header set to `true` (`ack`) or `false` (`nack`).
For `nack` instances, an additional header (`amqp_publishConfirmNackCause`) is provided.
Examples: `headers['myCorrelationData']`, `payload`.
If the expression resolves to a `Message<?>` instance (such as "`#this`"), the message emitted on the `ack`/`nack` channel is based on that message, with the additional headers added.
Also see xref:amqp/alternative-confirms-returns.adoc[Alternative Mechanism for Publisher Confirms and Returns].
Optional.
<14> The channel to which positive (`ack`) publisher confirmations are sent.
The payload is the correlation data defined by the `confirm-correlation-expression`.
Requires the underlying `AsyncRabbitTemplate` to have its `enableConfirms` property set to `true`.
Also see xref:amqp/alternative-confirms-returns.adoc[Alternative Mechanism for Publisher Confirms and Returns].
Optional (the default is `nullChannel`).
<15> Since version 4.2.
The channel to which negative (`nack`) publisher confirmations are sent.
The payload is the correlation data defined by the `confirm-correlation-expression`.
Requires the underlying `AsyncRabbitTemplate` to have its `enableConfirms` property set to `true`.
Also see xref:amqp/alternative-confirms-returns.adoc[Alternative Mechanism for Publisher Confirms and Returns].
Optional (the default is `nullChannel`).
<16> When set, the gateway will synthesize a negative acknowledgment (nack) if a publisher confirm is not received within this time in milliseconds.
Pending confirms are checked every 50% of this value, so the actual time a nack is sent will be between 1x and 1.5x this value.
Also see xref:amqp/alternative-confirms-returns.adoc[Alternative Mechanism for Publisher Confirms and Returns].
Default none (nacks will not be generated).
<17> 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 is constructed from the data received from AMQP, with the following additional headers: `amqp_returnReplyCode`, `amqp_returnReplyText`, `amqp_returnExchange`, and `amqp_returnRoutingKey`.
Requires the underlying `AsyncRabbitTemplate` to have its `mandatory` property set to `true`.
Also see xref:amqp/alternative-confirms-returns.adoc[Alternative Mechanism for Publisher Confirms and Returns].
Optional.
<18> When set to `false`, the endpoint tries to connect to the broker during application context initialization.
Doing so allows "`fail fast`" detection of bad configuration, by logging an error message if the broker is down.
When `true` (the default), the connection is established (if it does not already exist because some other component established
it) when the first message is sent.
See also xref:service-activator.adoc#async-service-activator[Asynchronous Service Activator] for more information.
[IMPORTANT]
.RabbitTemplate
====
When you use confirmations and returns, we recommend that the `RabbitTemplate` wired into the `AsyncRabbitTemplate` be dedicated.
Otherwise, unexpected side effects may be encountered.
====

View File

@@ -0,0 +1,136 @@
[[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 shown earlier in this chapter for the channel adapters and gateways).
However, the examples we show here have minimal configuration.
Explore the XML schema to view the available attributes.
A point-to-point channel might look like the following example:
[source,xml]
----
<int-amqp:channel id="p2pChannel"/>
----
Under the covers, the preceding example causes a `Queue` named `si.p2pChannel` to be declared, and this channel sends to that `Queue` (technically, by sending to the no-name direct exchange with a routing key that matches the name of this `Queue`).
This channel also registers a consumer on that `Queue`.
If you want the channel to be "`pollable`" instead of message-driven, provide the `message-driven` flag with a value of `false`, as the following example shows:
[source,xml]
----
<int-amqp:channel id="p2pPollableChannel" message-driven="false"/>
----
A publish-subscribe channel might look like the following:
[source,xml]
----
<int-amqp:publish-subscribe-channel id="pubSubChannel"/>
----
Under the covers, the preceding example causes a fanout exchange named `si.fanout.pubSubChannel` to be declared, and this channel sends to that fanout exchange.
This channel also declares a server-named exclusive, auto-delete, non-durable `Queue` and binds 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 (in conjunction with `channel-transacted`) support
`template-channel-transacted` to separate `transactional` configuration for the `AbstractMessageListenerContainer` and
for the `RabbitTemplate`.
Note that, previously, `channel-transacted` was `true` by default.
Now, by default, it is `false` for the `AbstractMessageListenerContainer`.
Prior to version 4.3, AMQP-backed channels only supported messages with `Serializable` payloads and headers.
The entire message was converted (serialized) and sent to RabbitMQ.
Now, you can set the `extract-payload` attribute (or `setExtractPayload()` when using Java configuration) to `true`.
When this flag is `true`, the message payload is converted and the headers are mapped, in a manner similar to when you use channel adapters.
This arrangement lets AMQP-backed channels be used with non-serializable payloads (perhaps with another message converter, such as the `Jackson2JsonMessageConverter`).
See xref:amqp/message-headers.adoc[AMQP Message Headers] for more about the default mapped headers.
You can modify the mapping by providing custom mappers that use the `outbound-header-mapper` and `inbound-header-mapper` attributes.
You can now also specify a `default-delivery-mode`, which is used to set the delivery mode when there is no `amqp_deliveryMode` header.
By default, Spring AMQP `MessageProperties` uses `PERSISTENT` delivery mode.
IMPORTANT: As with other persistence-backed channels, AMQP-backed channels are intended to provide message persistence to avoid message loss.
They are not intended to distribute work to other peer applications.
For that purpose, use channel adapters instead.
IMPORTANT: Starting with version 5.0, the pollable channel now blocks the poller thread for the specified `receiveTimeout` (the default is 1 second).
Previously, unlike other `PollableChannel` implementations, the thread returned immediately to the scheduler if no message was available, regardless of the receive timeout.
Blocking is a little more expensive than using a `basicGet()` to retrieve a message (with no timeout), because a consumer has to be created to receive each message.
To restore the previous behavior, set the poller's `receiveTimeout` to 0.
[[configuring-with-java-configuration]]
== Configuring with Java Configuration
The following example shows how to configure the channels with Java configuration:
[source, java]
----
@Bean
public AmqpChannelFactoryBean pollable(ConnectionFactory connectionFactory) {
AmqpChannelFactoryBean factoryBean = new AmqpChannelFactoryBean();
factoryBean.setConnectionFactory(connectionFactory);
factoryBean.setQueueName("foo");
factoryBean.setPubSub(false);
return factoryBean;
}
@Bean
public AmqpChannelFactoryBean messageDriven(ConnectionFactory connectionFactory) {
AmqpChannelFactoryBean factoryBean = new AmqpChannelFactoryBean(true);
factoryBean.setConnectionFactory(connectionFactory);
factoryBean.setQueueName("bar");
factoryBean.setPubSub(false);
return factoryBean;
}
@Bean
public AmqpChannelFactoryBean pubSub(ConnectionFactory connectionFactory) {
AmqpChannelFactoryBean factoryBean = new AmqpChannelFactoryBean(true);
factoryBean.setConnectionFactory(connectionFactory);
factoryBean.setQueueName("baz");
factoryBean.setPubSub(false);
return factoryBean;
}
----
[[configuring-with-the-java-dsl]]
== Configuring with the Java DSL
The following example shows how to configure the channels with the Java DSL:
[source, java]
----
@Bean
public IntegrationFlow pollableInFlow(ConnectionFactory connectionFactory) {
return IntegrationFlow.from(...)
...
.channel(Amqp.pollableChannel(connectionFactory)
.queueName("foo"))
...
.get();
}
@Bean
public IntegrationFlow messageDrivenInFow(ConnectionFactory connectionFactory) {
return IntegrationFlow.from(...)
...
.channel(Amqp.channel(connectionFactory)
.queueName("bar"))
...
.get();
}
@Bean
public IntegrationFlow pubSubInFlow(ConnectionFactory connectionFactory) {
return IntegrationFlow.from(...)
...
.channel(Amqp.publishSubscribeChannel(connectionFactory)
.queueName("baz"))
...
.get();
}
----

View File

@@ -0,0 +1,57 @@
[[content-type-conversion-outbound]]
= Outbound Message Conversion
Spring AMQP 1.4 introduced the `ContentTypeDelegatingMessageConverter`, where the actual converter is selected based
on the incoming content type message property.
This can be used by inbound endpoints.
As of Spring Integration version 4.3, you can use the `ContentTypeDelegatingMessageConverter` on outbound endpoints as well, with the `contentType` header specifying which converter is used.
The following example configures a `ContentTypeDelegatingMessageConverter`, with the default converter being the `SimpleMessageConverter` (which handles Java serialization and plain text), together with a JSON converter:
[source, xml]
----
<amqp:outbound-channel-adapter id="withContentTypeConverter" channel="ctRequestChannel"
exchange-name="someExchange"
routing-key="someKey"
amqp-template="amqpTemplateContentTypeConverter" />
<int:channel id="ctRequestChannel"/>
<rabbit:template id="amqpTemplateContentTypeConverter"
connection-factory="connectionFactory" message-converter="ctConverter" />
<bean id="ctConverter"
class="o.s.amqp.support.converter.ContentTypeDelegatingMessageConverter">
<property name="delegates">
<map>
<entry key="application/json">
<bean class="o.s.amqp.support.converter.Jackson2JsonMessageConverter" />
</entry>
</map>
</property>
</bean>
----
Sending a message to `ctRequestChannel` with the `contentType` header set to `application/json` causes the JSON converter to be selected.
This applies to both the outbound channel adapter and gateway.
[NOTE]
====
Starting with version 5.0, headers that are added to the `MessageProperties` of the outbound message are never overwritten by mapped headers (by default).
Previously, this was only the case if the message converter was a `ContentTypeDelegatingMessageConverter` (in that case, the header was mapped first so that the proper converter could be selected).
For other converters, such as the `SimpleMessageConverter`, mapped headers overwrote any headers added by the converter.
This caused problems when an outbound message had some leftover `contentType` headers (perhaps from an inbound channel adapter) and the correct outbound `contentType` was incorrectly overwritten.
The work-around was to use a header filter to remove the header before sending the message to the outbound endpoint.
There are, however, cases where the previous behavior is desired -- for example, when a `String` payload that contains JSON, the `SimpleMessageConverter` is not aware of the content and sets the `contentType` message property to `text/plain` but your application would like to override that to `application/json` by setting the `contentType` header of the message sent to the outbound endpoint.
The `ObjectToJsonTransformer` does exactly that (by default).
There is now a property called `headersMappedLast` on the outbound channel adapter and gateway (as well as on AMQP-backed channels).
Setting this to `true` restores the behavior of overwriting the property added by the converter.
Starting with version 5.1.9, a similar `replyHeadersMappedLast` is provided for the `AmqpInboundGateway` when we produce a reply and would like to override headers populated by the converter.
See its JavaDocs for more information.
====

View File

@@ -0,0 +1,15 @@
[[amqp-conversion-inbound]]
= Inbound Message Conversion
:page-section-summary-toc: 1
Inbound messages, arriving at the channel adapter or gateway, are converted to the `spring-messaging` `Message<?>` payload using a message converter.
By default, a `SimpleMessageConverter` is used, which handles java serialization and text.
Headers are mapped using the `DefaultHeaderMapper.inboundMapper()` by default.
If a conversion error occurs, and there is no error channel defined, the exception is thrown to the container and handled by the listener container's error handler.
The default error handler treats conversion errors as fatal and the message will be rejected (and routed to a dead-letter exchange, if the queue is so configured).
If an error channel is defined, the `ErrorMessage` payload is a `ListenerExecutionFailedException` with properties `failedMessage` (the Spring AMQP message that could not be converted) and the `cause`.
If the container `AcknowledgeMode` is `AUTO` (the default) and the error flow consumes the error without throwing an exception, the original message will be acknowledged.
If the error flow throws an exception, the exception type, in conjunction with the container's error handler, will determine whether the message is requeued.
If the container is configured with `AcknowledgeMode.MANUAL`, the payload is a `ManualAckListenerExecutionFailedException` with additional properties `channel` and `deliveryTag`.
This enables the error flow to call `basicAck` or `basicNack` (or `basicReject`) for the message, to control its disposition.

View File

@@ -0,0 +1,10 @@
[[amqp-delay]]
= Delayed Message Exchange
:page-section-summary-toc: 1
Spring AMQP supports the https://docs.spring.io/spring-amqp/reference/html/#delayed-message-exchange[RabbitMQ Delayed Message Exchange Plugin].
For inbound messages, the `x-delay` header is mapped to the `AmqpHeaders.RECEIVED_DELAY` header.
Setting the `AMQPHeaders.DELAY` header causes the corresponding `x-delay` header to be set in outbound messages.
You can also specify the `delay` and `delayExpression` properties on outbound endpoints (`delay-expression` when using XML configuration).
These properties take precedence over the `AmqpHeaders.DELAY` header.

View File

@@ -0,0 +1,36 @@
[[amqp-inbound-ack]]
= Inbound Endpoint Acknowledge Mode
By default, the inbound endpoints use the `AUTO` acknowledge mode, which means the container automatically acknowledges the message when the downstream integration flow completes (or a message is handed off to another thread by using a `QueueChannel` or `ExecutorChannel`).
Setting the mode to `NONE` configures the consumer such that acknowledgments are not used at all (the broker automatically acknowledges the message as soon as it is sent).
Setting the mode to `MANUAL` lets user code acknowledge 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`) are used.
In order to not interfere with the operation of the container, you should not retain a reference to the channel and use it only in the context of the current message.
NOTE: Since the `Channel` is a reference to a "`live`" object, it cannot be serialized and is lost if a message is persisted.
The following example shows 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;
}
----

View File

@@ -0,0 +1,263 @@
[[amqp-inbound-channel-adapter]]
= Inbound Channel Adapter
The following listing shows the possible configuration options for an AMQP Inbound Channel Adapter:
[tabs]
======
Java DSL::
+
[source, java, role="primary"]
----
@Bean
public IntegrationFlow amqpInbound(ConnectionFactory connectionFactory) {
return IntegrationFlow.from(Amqp.inboundAdapter(connectionFactory, "aName"))
.handle(m -> System.out.println(m.getPayload()))
.get();
}
----
Java::
+
[source, java, role="secondary"]
----
@Bean
public MessageChannel amqpInputChannel() {
return new DirectChannel();
}
@Bean
public AmqpInboundChannelAdapter inbound(SimpleMessageListenerContainer listenerContainer,
@Qualifier("amqpInputChannel") MessageChannel channel) {
AmqpInboundChannelAdapter adapter = new AmqpInboundChannelAdapter(listenerContainer);
adapter.setOutputChannel(channel);
return adapter;
}
@Bean
public SimpleMessageListenerContainer container(ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container =
new SimpleMessageListenerContainer(connectionFactory);
container.setQueueNames("aName");
container.setConcurrentConsumers(2);
// ...
return container;
}
@Bean
@ServiceActivator(inputChannel = "amqpInputChannel")
public MessageHandler handler() {
return new MessageHandler() {
@Override
public void handleMessage(Message<?> message) throws MessagingException {
System.out.println(message.getPayload());
}
};
}
----
XML::
+
[source, xml, role="secondary"]
----
<int-amqp:inbound-channel-adapter
id="inboundAmqp" <1>
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>
consumers-per-queue <26>
batch-mode="MESSAGES"/> <27>
<1> The unique ID for this adapter.
Optional.
<2> Message channel to which converted messages should be sent.
Required.
<3> Names of the AMQP queues (comma-separated list) from which messages should be consumed.
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 acknowledges when the downstream flow completes.
Optional (defaults to AUTO).
See xref:amqp/inbound-ack.adoc[Inbound Endpoint Acknowledge Mode].
<5> Extra AOP Advices to handle cross-cutting behavior associated with this inbound channel adapter.
Optional.
<6> Flag to indicate that channels created by this component are transactional.
If true, it 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 that signals a rollback.
Optional (Defaults to false).
<7> Specify the number of concurrent consumers to create.
The default is `1`.
We recommend raising the number of concurrent consumers 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, use one consumer for low-volume queues.
Not allowed when 'consumers-per-queue' is set.
Optional.
<8> Bean reference to the RabbitMQ `ConnectionFactory`.
Optional (defaults to `connectionFactory`).
<9> Message channel to which error messages should be sent.
Optional.
<10> Whether the listener channel (com.rabbitmq.client.Channel) is 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 (such as `contentType`) are copied to Spring Integration `MessageHeaders`.
Any user-defined headers within the AMQP `MessageProperties` are NOT copied to the message by the default `DefaultAmqpHeaderMapper`.
Not allowed if 'request-header-names' is provided.
<12> Comma-separated list of the 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 (such as "\*" or "thing1*, thing2" or "*something").
<13> Reference to the `AbstractMessageListenerContainer` to use for receiving AMQP Messages.
If this attribute is provided, no other attribute related to the listener container configuration should be provided.
In other words, by setting this reference, you must take full responsibility for 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`.
Optional.
<14> The `MessageConverter` to use when receiving AMQP messages.
Optional.
<15> The `MessagePropertiesConverter` to use when receiving AMQP messages.
Optional.
<16> Specifies the phase in which the underlying `AbstractMessageListenerContainer` 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, you can set this value high to improve throughput.
It should be greater than or equal to the transaction size (see the `tx-size` attribute, later in this list).
Optional (defaults to `1`).
<18> Receive timeout in milliseconds.
Optional (defaults to `1000`).
<19> Specifies the interval between recovery attempts of the underlying `AbstractMessageListenerContainer` (in milliseconds).
Optional (defaults to `5000`).
<20> If 'true' and none of the queues are available on the broker, the container throws a fatal exception during startup and stops if the queues are deleted when the container is running (after making three attempts to passively declare the queues).
If `false`, the container does not throw an exception and goes into recovery mode, attempting to restart according to the `recovery-interval`.
Optional (defaults to `true`).
<21> The time to wait for workers (in milliseconds) after the underlying `AbstractMessageListenerContainer` is stopped and before the AMQP connection is forced closed.
If any workers are active when the shutdown signal comes, they are allowed to finish processing as long as they can finish within this timeout.
Otherwise, the connection is closed and messages remain unacknowledged (if the channel is transactional).
Optional (defaults to `5000`).
<22> By default, the underlying `AbstractMessageListenerContainer` uses a `SimpleAsyncTaskExecutor` implementation, that fires up a new thread for each task, running it asynchronously.
By default, the number of concurrent threads is unlimited.
Note that this implementation does not reuse threads.
Consider using a thread-pooling `TaskExecutor` implementation as an alternative.
Optional (defaults to `SimpleAsyncTaskExecutor`).
<23> By default, the underlying `AbstractMessageListenerContainer` creates a new instance of the `DefaultTransactionAttribute` (it 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 `AbstractMessageListenerContainer`.
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`, the commit or rollback of the messaging transaction is deferred until the end of the current transaction.
If the `channelTransacted` flag is `false`, no transaction semantics apply to the messaging operation (it is auto-acked).
For further information, see
https://docs.spring.io/spring-amqp/reference/html/%255Freference.html#%5Ftransactions[Transactions with Spring AMQP].
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 value set in `prefetch-count`.
Not allowed when 'consumers-per-queue' is set.
Optional (defaults to `1`).
<26> Indicates that the underlying listener container should be a `DirectMessageListenerContainer` instead of the default `SimpleMessageListenerContainer`.
See the https://docs.spring.io/spring-amqp/reference/html/[Spring AMQP Reference Manual] for more information.
<27> When the container's `consumerBatchEnabled` is `true`, determines how the adapter presents the batch of messages in the message payload.
When set to `MESSAGES` (default), the payload is a `List<Message<?>>` where each message has headers mapped from the incoming AMQP `Message` and the payload is the converted `body`.
When set to `EXTRACT_PAYLOADS`, the payload is a `List<?>` where the elements are converted from the AMQP `Message` body.
`EXTRACT_PAYLOADS_WITH_HEADERS` is similar to `EXTRACT_PAYLOADS` but, in addition, the headers from each message are mapped from the `MessageProperties` into a `List<Map<String, Object>` at the corresponding index; the header name is `AmqpInboundChannelAdapter.CONSOLIDATED_HEADERS`.
----
======
[NOTE]
.container
====
Note that when configuring an external container with XML, you cannot use the Spring AMQP namespace to define the container.
This is because the namespace requires at least one `<listener/>` element.
In this environment, the listener is internal to the adapter.
For this reason, you must define the container by using a normal Spring `<bean/>` definition, as the following example shows:
[source,xml]
----
<bean id="container"
class="org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="queueNames" value="aName.queue" />
<property name="defaultRequeueRejected" value="false"/>
</bean>
----
====
IMPORTANT: Even though the Spring Integration JMS and AMQP support is 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 uses an `AbstractMessageListenerContainer` and is message driven.
In that regard, it is more similar to the JMS message-driven channel adapter.
Starting with version 5.5, the `AmqpInboundChannelAdapter` can be configured with an `org.springframework.amqp.rabbit.retry.MessageRecoverer` strategy which is used in the `RecoveryCallback` when the retry operation is called internally.
See `setMessageRecoverer()` JavaDocs for more information.
The `@Publisher` annotation also can be used in combination with a `@RabbitListener`:
[source, java]
----
@Configuration
@EnableIntegration
@EnableRabbit
@EnablePublisher
public static class ContextConfiguration {
@Bean
QueueChannel fromRabbitViaPublisher() {
return new QueueChannel();
}
@RabbitListener(queuesToDeclare = @Queue("publisherQueue"))
@Publisher("fromRabbitViaPublisher")
@Payload("#args.payload.toUpperCase()")
public void consumeForPublisher(String payload) {
}
}
----
By default, the `@Publisher` AOP interceptor deals with a return value from a method call.
However, the return value from a `@RabbitListener` method is treated as an AMQP reply message.
Therefore, such an approach cannot be used together with a `@Publisher`, so a `@Payload` annotation with respective SpEL expression against method arguments is a recommended way for this combination.
See more information about the `@Publisher` in the xref:message-publishing.adoc#publisher-annotation[Annotation-driven Configuration] section.
IMPORTANT: When using exclusive or single-active consumers in the listener container, it is recommended that you set the container property `forceStop` to `true`.
This will prevent a race condition where, after stopping the container, another consumer could start consuming messages before this instance has fully stopped.
[[amqp-debatching]]
== Batched Messages
See https://docs.spring.io/spring-amqp/docs/current/reference/html/#template-batching[the Spring AMQP Documentation] for more information about batched messages.
To produce batched messages with Spring Integration, simply configure the outbound endpoint with a `BatchingRabbitTemplate`.
When receiving batched messages, by default, the listener containers extract each fragment message and the adapter will produce a `Message<?>` for each fragment.
Starting with version 5.2, if the container's `deBatchingEnabled` property is set to `false`, the de-batching is performed by the adapter instead, and a single `Message<List<?>>` is produced with the payload being a list of the fragment payloads (after conversion if appropriate).
The default `BatchingStrategy` is the `SimpleBatchingStrategy`, but this can be overridden on the adapter.
NOTE: The `org.springframework.amqp.rabbit.retry.MessageBatchRecoverer` must be used with batches when recovery is required for retry operations.

View File

@@ -0,0 +1,121 @@
[[amqp-inbound-gateway]]
= Inbound Gateway
The inbound gateway supports all the attributes on the inbound channel adapter (except that 'channel' is replaced by 'request-channel'), plus some additional attributes.
The following listing shows the available attributes:
[tabs]
======
Java DSL::
+
[source, java, role="primary"]
----
@Bean // return the upper cased payload
public IntegrationFlow amqpInboundGateway(ConnectionFactory connectionFactory) {
return IntegrationFlow.from(Amqp.inboundGateway(connectionFactory, "foo"))
.transform(String.class, String::toUpperCase)
.get();
}
----
Java::
+
[source, java, role="secondary"]
----
@Bean
public MessageChannel amqpInputChannel() {
return new DirectChannel();
}
@Bean
public AmqpInboundGateway inbound(SimpleMessageListenerContainer listenerContainer,
@Qualifier("amqpInputChannel") MessageChannel channel) {
AmqpInboundGateway gateway = new AmqpInboundGateway(listenerContainer);
gateway.setRequestChannel(channel);
gateway.setDefaultReplyTo("bar");
return gateway;
}
@Bean
public SimpleMessageListenerContainer container(ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container =
new SimpleMessageListenerContainer(connectionFactory);
container.setQueueNames("foo");
container.setConcurrentConsumers(2);
// ...
return container;
}
@Bean
@ServiceActivator(inputChannel = "amqpInputChannel")
public MessageHandler handler() {
return new AbstractReplyProducingMessageHandler() {
@Override
protected Object handleRequestMessage(Message<?> requestMessage) {
return "reply to " + requestMessage.getPayload();
}
};
}
----
XML::
+
[source, xml, role="secondary"]
----
<int-amqp:inbound-gateway
id="inboundGateway" <1>
request-channel="myRequestChannel" <2>
header-mapper="" <3>
mapped-request-headers="" <4>
mapped-reply-headers="" <5>
reply-channel="myReplyChannel" <6>
reply-timeout="1000" <7>
amqp-template="" <8>
default-reply-to="" /> <9>
----
======
<1> The Unique ID for this adapter.
Optional.
<2> Message channel to which converted messages are sent.
Required.
<3> A reference to an `AmqpHeaderMapper` to use when receiving AMQP Messages.
Optional.
By default, only standard AMQP properties (such as `contentType`) are copied to and from Spring Integration `MessageHeaders`.
Any user-defined headers within the AMQP `MessageProperties` are not 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 attribute can be provided only 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 `"thing1*, thing2"` or `"*thing1"`).
<5> Comma-separated list of names of `MessageHeaders` to be mapped into the AMQP message properties of the AMQP reply message.
All standard Headers (such as `contentType`) are mapped to AMQP Message Properties, while user-defined headers are mapped to the 'headers' property.
This attribute 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 (for example, `"\*"` or `"foo*, bar"` or `"*foo"`).
<6> Message Channel where reply Messages are expected.
Optional.
<7> Sets the `receiveTimeout` on the underlying `o.s.i.core.MessagingTemplate` for receiving messages from the reply channel.
If not specified, this property defaults to `1000` (1 second).
Only applies if the container thread hands off to another thread before the reply is sent.
<8> The customized `AmqpTemplate` bean reference (to have more control over the reply messages to send).
You can provide an alternative implementation to the `RabbitTemplate`.
<9> The `replyTo` `o.s.amqp.core.Address` to be used when the `requestMessage` does not have a `replyTo`
property.
If this option is not specified, no `amqp-template` is provided, no `replyTo` property exists in the request message, and
an `IllegalStateException` is thrown because the reply cannot be routed.
If this option is not specified and an external `amqp-template` is provided, no exception is thrown.
You must either specify this option or configure a default `exchange` and `routingKey` on that template,
if you anticipate cases when no `replyTo` property exists in the request message.
See the note in xref:amqp/inbound-channel-adapter.adoc[Inbound Channel Adapter] about configuring the `listener-container` attribute.
Starting with version 5.5, the `AmqpInboundChannelAdapter` can be configured with an `org.springframework.amqp.rabbit.retry.MessageRecoverer` strategy which is used in the `RecoveryCallback` when the retry operation is called internally.
See `setMessageRecoverer()` JavaDocs for more information.
[[amqp-gateway-debatching]]
== Batched Messages
See xref:amqp/inbound-channel-adapter.adoc#amqp-debatching[Batched Messages].

View File

@@ -0,0 +1,97 @@
[[amqp-message-headers]]
= AMQP Message Headers
[[overview]]
== Overview
The Spring Integration AMQP Adapters automatically map all AMQP properties and headers.
(This is a change from 4.3 - previously, only standard headers were mapped).
By default, these properties are copied to and from Spring Integration `MessageHeaders` by using the
https://docs.spring.io/spring-integration/api/org/springframework/integration/amqp/support/DefaultAmqpHeaderMapper.html[`DefaultAmqpHeaderMapper`].
You can pass in your own implementation of AMQP-specific header mappers, as the adapters have properties to support doing so.
Any user-defined headers within the AMQP https://docs.spring.io/spring-amqp/api/org/springframework/amqp/core/MessageProperties.html[`MessageProperties`] are copied to or from an AMQP message, unless explicitly negated by the `requestHeaderNames` or `replyHeaderNames` properties of the `DefaultAmqpHeaderMapper`.
By default, for an outbound mapper, no `x-*` headers are mapped.
See the xref:amqp/message-headers.adoc#header-copy-caution[caution] that appears later in this section for why.
To override the default and revert to the pre-4.3 behavior, use `STANDARD_REQUEST_HEADERS` and
`STANDARD_REPLY_HEADERS` in the properties.
TIP: When mapping user-defined headers, the values can also contain simple wildcard patterns (such as `thing*` or `\*thing`) to be matched.
The `*` matches all headers.
Starting with version 4.1, the `AbstractHeaderMapper` (a `DefaultAmqpHeaderMapper` superclass) lets the `NON_STANDARD_HEADERS` token be configured for the `requestHeaderNames` and `replyHeaderNames` properties (in addition to the existing `STANDARD_REQUEST_HEADERS` and `STANDARD_REPLY_HEADERS`) to map all user-defined headers.
The `org.springframework.amqp.support.AmqpHeaders` class identifies the default headers that are used by the `DefaultAmqpHeaderMapper`:
* `amqp_appId`
* `amqp_clusterId`
* `amqp_contentEncoding`
* `amqp_contentLength`
* `content-type` (see xref:amqp/message-headers.adoc#amqp-content-type[The `contentType` Header])
* `amqp_correlationId`
* `amqp_delay`
* `amqp_deliveryMode`
* `amqp_deliveryTag`
* `amqp_expiration`
* `amqp_messageCount`
* `amqp_messageId`
* `amqp_receivedDelay`
* `amqp_receivedDeliveryMode`
* `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_channel`
* `amqp_consumerTag`
* `amqp_consumerQueue`
[[header-copy-caution]]
CAUTION: As mentioned earlier in this section, using a header mapping pattern of `\*` is a common way to copy all headers.
However, this can have some unexpected side effects, because certain RabbitMQ proprietary properties/headers are also copied.
For example, when you use https://www.rabbitmq.com/federated-exchanges.html[federation], the received message may have a property named `x-received-from`, which contains the node that sent the message.
If you use the wildcard character `*` for the request and reply header mapping on the inbound gateway, this header is copied, which may cause some issues with federation.
This reply message may be federated back to the sending broker, which may think that a message is looping and, as a result, silently drop it.
If you wish to use the convenience of wildcard header mapping, you may need to filter out some headers in the downstream flow.
For example, to avoid copying the `x-received-from` header back to the reply you can use `<int:header-filter ... header-names="x-received-from">` before sending the reply to the AMQP inbound gateway.
Alternatively, you can explicitly list those properties that you actually want mapped, instead of using wildcards.
For these reasons, for inbound messages, the mapper (by default) does not map any `x-*` headers.
It also does not map the `deliveryMode` to the `amqp_deliveryMode` header, to avoid propagation of that header from an inbound message to an outbound message.
Instead, this header is mapped to `amqp_receivedDeliveryMode`, which is not mapped on output.
Starting with version 4.3, patterns in the header mappings can be negated by preceding the pattern with `!`.
Negated patterns get priority, so a list such as `STANDARD_REQUEST_HEADERS,thing1,ba*,!thing2,!thing3,qux,!thing1` does not map `thing1` (nor `thing2` nor `thing3`).
The standard headers plus `bad` and `qux` are mapped.
The negation technique can be useful for example to not map JSON type headers for incoming messages when a JSON deserialization logic is done in the receiver downstream different way.
For this purpose a `!json_*` pattern should be configured for header mapper of the inbound channel adapter/gateway.
IMPORTANT: If you have a user-defined header that begins with `!` that you do wish to map, you need to escape it with `\`, as follows: `STANDARD_REQUEST_HEADERS,\!myBangHeader`.
The header named `!myBangHeader` is now mapped.
NOTE: Starting with version 5.1, the `DefaultAmqpHeaderMapper` will fall back to mapping `MessageHeaders.ID` and `MessageHeaders.TIMESTAMP` to `MessageProperties.messageId` and `MessageProperties.timestamp` respectively, if the corresponding `amqp_messageId` or `amqp_timestamp` headers are not present on outbound messages.
Inbound properties will be mapped to the `amqp_*` headers as before.
It is useful to populate the `messageId` property when message consumers are using stateful retry.
[[amqp-content-type]]
== The `contentType` Header
Unlike other headers, the `AmqpHeaders.CONTENT_TYPE` is not prefixed with `amqp_`; this allows transparent passing of the contentType header across different technologies.
For example an inbound HTTP message sent to a RabbitMQ queue.
The `contentType` header is mapped to Spring AMQP's `MessageProperties.contentType` property and that is subsequently mapped to RabbitMQ's `content_type` property.
Prior to version 5.1, this header was also mapped as an entry in the `MessageProperties.headers` map; this was incorrect and, furthermore, the value could be wrong since the underlying Spring AMQP message converter might have changed the content type.
Such a change would be reflected in the first-class `content_type` property, but not in the RabbitMQ headers map.
Inbound mapping ignored the headers map value.
`contentType` is no longer mapped to an entry in the headers map.

View File

@@ -0,0 +1,159 @@
[[amqp-outbound-channel-adapter]]
= Outbound Channel Adapter
The following example shows the available properties for an AMQP outbound channel adapter:
[tabs]
======
Java DSL::
+
[source,java,role="primary"]
----
@Bean
public IntegrationFlow amqpOutbound(AmqpTemplate amqpTemplate,
MessageChannel amqpOutboundChannel) {
return IntegrationFlow.from(amqpOutboundChannel)
.handle(Amqp.outboundAdapter(amqpTemplate)
.routingKey("queue1")) // default exchange - route to queue 'queue1'
.get();
}
----
Java::
+
[source,java,role="secondary"]
----
@Bean
@ServiceActivator(inputChannel = "amqpOutboundChannel")
public AmqpOutboundEndpoint amqpOutbound(AmqpTemplate amqpTemplate) {
AmqpOutboundEndpoint outbound = new AmqpOutboundEndpoint(amqpTemplate);
outbound.setRoutingKey("queue1"); // default exchange - route to queue 'queue1'
return outbound;
}
@Bean
public MessageChannel amqpOutboundChannel() {
return new DirectChannel();
}
----
XML::
+
[source,xml,role="secondary"]
----
<int-amqp:outbound-channel-adapter id="outboundAmqp" <1>
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>
confirm-timeout="" <13>
wait-for-confirm="" <14>
return-channel="" <15>
error-message-strategy="" <16>
header-mapper="" <17>
mapped-request-headers="" <18>
lazy-connect="true" <19>
multi-send="false"/> <20>
----
======
<1> The unique ID for this adapter.
Optional.
<2> Message channel to which messages should be sent 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 are sent.
If not provided, messages are 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 are sent, with the message as the root object.
If not provided, messages are 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 failover.
Optional (defaults to `Ordered.LOWEST_PRECEDENCE [=Integer.MAX_VALUE]`).
<7> The fixed routing-key to use when sending messages.
By default, this is 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 (for example, 'payload.key').
By default, this is 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.
If the Spring Integration message header `amqp_deliveryMode` is present, the `DefaultHeaderMapper` sets the value.
If this attribute is not supplied and the header mapper does not 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 that defines correlation data.
When provided, this configures the underlying AMQP template to receive publisher confirmations.
Requires a dedicated `RabbitTemplate` and a `CachingConnectionFactory` with the `publisherConfirms` property set to `true`.
When a publisher confirmation 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 confirmation is the correlation data, as defined by this expression.
The message has an 'amqp_publishConfirm' header set to `true` (`ack`) or `false` (`nack`).
Examples: `headers['myCorrelationData']` and `payload`.
Version 4.1 introduced the `amqp_publishConfirmNackCause` message header.
It contains the `cause` of a 'nack' for a publisher confirmation.
Starting with version 4.2, if the expression resolves to a `Message<?>` instance (such as `#this`), the message emitted on the `ack`/`nack` channel is based on that message, with the additional header(s) added.
Previously, a new message was created with the correlation data as its payload, regardless of type.
Also see xref:amqp/alternative-confirms-returns.adoc[Alternative Mechanism for Publisher Confirms and Returns].
Optional.
<11> The channel to which positive (`ack`) publisher confirms are sent.
The payload is the correlation data defined by the `confirm-correlation-expression`.
If the expression is `#root` or `#this`, the message is built from the original message, with the `amqp_publishConfirm` header set to `true`.
Also see xref:amqp/alternative-confirms-returns.adoc[Alternative Mechanism for Publisher Confirms and Returns].
Optional (the default is `nullChannel`).
<12> The channel to which negative (`nack`) publisher confirmations are sent.
The payload is the correlation data defined by the `confirm-correlation-expression` (if there is no `ErrorMessageStrategy` configured).
If the expression is `#root` or `#this`, the message is built from the original message, with the `amqp_publishConfirm` header set to `false`.
When there is an `ErrorMessageStrategy`, the message is an `ErrorMessage` with a `NackedAmqpMessageException` payload.
Also see xref:amqp/alternative-confirms-returns.adoc[Alternative Mechanism for Publisher Confirms and Returns].
Optional (the default is `nullChannel`).
<13> When set, the adapter will synthesize a negative acknowledgment (nack) if a publisher confirm is not received within this time in milliseconds.
Pending confirms are checked every 50% of this value, so the actual time a nack is sent will be between 1x and 1.5x this value.
Also see xref:amqp/alternative-confirms-returns.adoc[Alternative Mechanism for Publisher Confirms and Returns].
Default none (nacks will not be generated).
<14> When set to true, the calling thread will block, waiting for a publisher confirmation.
This requires a `RabbitTemplate` configured for confirms as well as a `confirm-correlation-expression`.
The thread will block for up to `confirm-timeout` (or 5 seconds by default).
If a timeout occurs, a `MessageTimeoutException` will be thrown.
If returns are enabled and a message is returned, or any other exception occurs while awaiting the confirmation, a `MessageHandlingException` will be thrown, with an appropriate message.
<15> The channel to which returned messages are sent.
When provided, the underlying AMQP template is configured to return undeliverable messages to the adapter.
When there is no `ErrorMessageStrategy` configured, the message is constructed from the data received from AMQP, with the following additional headers: `amqp_returnReplyCode`, `amqp_returnReplyText`, `amqp_returnExchange`, `amqp_returnRoutingKey`.
When there is an `ErrorMessageStrategy`, the message is an `ErrorMessage` with a `ReturnedAmqpMessageException` payload.
Also see xref:amqp/alternative-confirms-returns.adoc[Alternative Mechanism for Publisher Confirms and Returns].
Optional.
<16> A reference to an `ErrorMessageStrategy` implementation used to build `ErrorMessage` instances when sending returned or negatively acknowledged messages.
<17> A reference to an `AmqpHeaderMapper` to use when sending AMQP Messages.
By default, only standard AMQP properties (such as `contentType`) are copied to the Spring Integration `MessageHeaders`.
Any user-defined headers is not copied to the message by the default`DefaultAmqpHeaderMapper`.
Not allowed if 'request-header-names' is provided.
Optional.
<18> 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 `"thing1*, thing2"` or `"*thing1"`).
<19> When set to `false`, the endpoint attempts to connect to the broker during application context initialization.
This allows "`fail fast`" detection of bad configuration but also causes initialization to fail if the broker is down.
When `true` (the default), the connection is established (if it does not already exist because some other component established it) when the first message is sent.
<20> When set to `true`, payloads of type `Iterable<Message<?>>` will be sent as discrete messages on the same channel within the scope of a single `RabbitTemplate` invocation.
Requires a `RabbitTemplate`.
When `wait-for-confirms` is true, `RabbitTemplate.waitForConfirmsOrDie()` is invoked after the messages have been sent.
With a transactional template, the sends will be performed in either a new transaction or one that has already been started (if present).
[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.
=====

View File

@@ -0,0 +1,10 @@
[[amqp-outbound-endpoints]]
= Outbound Endpoints
:page-section-summary-toc: 1
The following outbound endpoints have many similar configuration options.
Starting with version 5.2, the `confirm-timeout` has been added.
Normally, when publisher confirms are enabled, the broker will quickly return an ack (or nack) which will be sent to the appropriate channel.
If a channel is closed before the confirm is received, the Spring AMQP framework will synthesize a nack.
"Missing" acks should never occur but, if you set this property, the endpoint will periodically check for them and synthesize a nack if the time elapses without a confirm being received.

View File

@@ -0,0 +1,168 @@
[[amqp-outbound-gateway]]
= Outbound Gateway
The following listing shows the possible properties for an AMQP Outbound Gateway:
[tabs]
======
Java DSL::
+
[source,java,role="primary"]
----
@Bean
public IntegrationFlow amqpOutbound(AmqpTemplate amqpTemplate) {
return f -> f.handle(Amqp.outboundGateway(amqpTemplate)
.routingKey("foo")) // default exchange - route to queue 'foo'
.get();
}
@MessagingGateway(defaultRequestChannel = "amqpOutbound.input")
public interface MyGateway {
String sendToRabbit(String data);
}
----
Java::
+
[source,java,role="secondary"]
----
@Bean
@ServiceActivator(inputChannel = "amqpOutboundChannel")
public AmqpOutboundEndpoint amqpOutbound(AmqpTemplate amqpTemplate) {
AmqpOutboundEndpoint outbound = new AmqpOutboundEndpoint(amqpTemplate);
outbound.setExpectReply(true);
outbound.setRoutingKey("foo"); // default exchange - route to queue 'foo'
return outbound;
}
@Bean
public MessageChannel amqpOutboundChannel() {
return new DirectChannel();
}
@MessagingGateway(defaultRequestChannel = "amqpOutboundChannel")
public interface MyGateway {
String sendToRabbit(String data);
}
----
XML::
+
[source,xml,role="secondary"]
----
<int-amqp:outbound-gateway id="outboundGateway" <1>
request-channel="myRequestChannel" <2>
amqp-template="" <3>
exchange-name="" <4>
exchange-name-expression="" <5>
order="1" <6>
reply-channel="" <7>
reply-timeout="" <8>
requires-reply="" <9>
routing-key="" <10>
routing-key-expression="" <11>
default-delivery-mode"" <12>
confirm-correlation-expression="" <13>
confirm-ack-channel="" <14>
confirm-nack-channel="" <15>
confirm-timeout="" <16>
return-channel="" <17>
error-message-strategy="" <18>
lazy-connect="true" /> <19>
----
======
<1> The unique ID for this adapter.
Optional.
<2> Message channel to which messages are sent 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 are sent to the default, no-name cxchange.
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 are 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 failover.
Optional (defaults to `Ordered.LOWEST_PRECEDENCE [=Integer.MAX_VALUE]`).
<7> Message channel to which replies should be sent after being received from an AMQP queue and converted.
Optional.
<8> The time the gateway waits 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.
Defaults to infinity.
<9> When `true`, the gateway throws an exception if no reply message is received within the `AmqpTemplate`'s `replyTimeout` property.
Defaults to `true`.
<10> The `routing-key` to use when sending messages.
By default, this is 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 (for example, 'payload.key').
By default, this is 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.
If the Spring Integration message header `amqp_deliveryMode` is present, the `DefaultHeaderMapper` sets the value.
If this attribute is not supplied and the header mapper does not 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> Since version 4.2.
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.
The message has a header 'amqp_publishConfirm' set to `true` (`ack`) or `false` (`nack`).
For `nack` confirmations, Spring Integration provides an additional header `amqp_publishConfirmNackCause`.
Examples: `headers['myCorrelationData']` and `payload`.
If the expression resolves to a `Message<?>` instance (such as `#this`), the message
emitted on the `ack`/`nack` channel is based on that message, with the additional headers added.
Previously, a new message was created with the correlation data as its payload, regardless of type.
Also see xref:amqp/alternative-confirms-returns.adoc[Alternative Mechanism for Publisher Confirms and Returns].
Optional.
<14> The channel to which positive (`ack`) publisher confirmations are sent.
The payload is the correlation data defined by `confirm-correlation-expression`.
If the expression is `#root` or `#this`, the message is built from the original message, with the `amqp_publishConfirm` header set to `true`.
Also see xref:amqp/alternative-confirms-returns.adoc[Alternative Mechanism for Publisher Confirms and Returns].
Optional (the default is `nullChannel`).
<15> The channel to which negative (`nack`) publisher confirmations are sent.
The payload is the correlation data defined by `confirm-correlation-expression` (if there is no `ErrorMessageStrategy` configured).
If the expression is `#root` or `#this`, the message is built from the original message, with the `amqp_publishConfirm` header set to `false`.
When there is an `ErrorMessageStrategy`, the message is an `ErrorMessage` with a `NackedAmqpMessageException` payload.
Also see xref:amqp/alternative-confirms-returns.adoc[Alternative Mechanism for Publisher Confirms and Returns].
Optional (the default is `nullChannel`).
<16> When set, the gateway will synthesize a negative acknowledgment (nack) if a publisher confirm is not received within this time in milliseconds.
Pending confirms are checked every 50% of this value, so the actual time a nack is sent will be between 1x and 1.5x this value.
Default none (nacks will not be generated).
<17> The channel to which returned messages are sent.
When provided, the underlying AMQP template is configured to return undeliverable messages to the adapter.
When there is no `ErrorMessageStrategy` configured, the message is constructed from the data received from AMQP, with the following additional headers: `amqp_returnReplyCode`, `amqp_returnReplyText`, `amqp_returnExchange`, and `amqp_returnRoutingKey`.
When there is an `ErrorMessageStrategy`, the message is an `ErrorMessage` with a `ReturnedAmqpMessageException` payload.
Also see xref:amqp/alternative-confirms-returns.adoc[Alternative Mechanism for Publisher Confirms and Returns].
Optional.
<18> A reference to an `ErrorMessageStrategy` implementation used to build `ErrorMessage` instances when sending returned or negatively acknowledged messages.
<19> When set to `false`, the endpoint attempts to connect to the broker during application context initialization.
This allows "`fail fast`" detection of bad configuration by logging an error message if the broker is down.
When `true` (the default), the connection is established (if it does not 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 five seconds.
If you require a longer timeout, you must configure it on the `template`.
Note that the only difference between the outbound adapter and outbound gateway configuration is the setting of the
`expectReply` property.

View File

@@ -0,0 +1,56 @@
[[polled-inbound-channel-adapter]]
= Polled Inbound Channel Adapter
[[overview]]
== Overview
Version 5.0.1 introduced a polled channel adapter, letting you fetch individual messages on demand -- for example, with a `MessageSourcePollingTemplate` or a poller.
See xref:polling-consumer.adoc#deferred-acks-message-source[Deferred Acknowledgment Pollable Message Source] for more information.
It does not currently support XML configuration.
The following example shows how to configure an `AmqpMessageSource`:
[tabs]
======
Java DSL::
+
[source, java, role="primary"]
----
@Bean
public IntegrationFlow flow() {
return IntegrationFlow.from(Amqp.inboundPolledAdapter(connectionFactory(), DSL_QUEUE),
e -> e.poller(Pollers.fixedDelay(1_000)).autoStartup(false))
.handle(p -> {
...
})
.get();
}
----
Java::
+
[source, java, role="secondary"]
----
@Bean
public AmqpMessageSource source(ConnectionFactory connectionFactory) {
return new AmqpMessageSource(connectionFactory, "someQueue");
}
----
======
See the https://docs.spring.io/spring-integration/api/org/springframework/integration/amqp/inbound/AmqpMessageSource.html[Javadoc] for configuration properties.
[source, xml, role="secondary"]
.XML
----
This adapter currently does not have XML configuration support.
----
[[amqp-polled-debatching]]
== Batched Messages
See xref:amqp/inbound-channel-adapter.adoc#amqp-debatching[Batched Messages].
For the polled adapter, there is no listener container, batched messages are always debatched (if the `BatchingStrategy` supports doing so).

View File

@@ -0,0 +1,40 @@
[[rmq-streams]]
= RabbitMQ Stream Queue Support
Version 6.0 introduced support for RabbitMQ Stream Queues.
The DSL factory class for these endpoints is `RabbitStream`.
[[rmq-stream-inbound-channel-adapter]]
== RabbitMQ Stream Inbound Channel Adapter
[source, java]
----
@Bean
IntegrationFlow simpleStream(Environment env) {
return IntegrationFlow.from(RabbitStream.inboundAdapter(env).streamName("my.stream"))
// ...
.get();
}
@Bean
IntegrationFlow superStream(Environment env) {
return IntegrationFlow.from(RabbitStream.inboundAdapter(env).superStream("my.super.stream", "my.consumer"))
// ...
.get();
}
----
[[rmq-stream-outbound-channel-adapter]]
== RabbitMQ Stream Outbound Channel Adapter
[source, java]
----
@Bean
IntegrationFlow outbound(Environment env) {
return f -> f
// ...
.handle(RabbitStream.outboundStreamAdapter(env, "my.stream"));
}
----

View File

@@ -0,0 +1,21 @@
[[amqp-samples]]
= AMQP Samples
:page-section-summary-toc: 1
To experiment with the AMQP adapters, check out the samples available in the Spring Integration samples git repository at https://github.com/spring-projects/spring-integration-samples[https://github.com/SpringSource/spring-integration-samples]
Currently, one sample demonstrates the basic functionality of the Spring Integration AMQP adapter by using an outbound channel adapter and an inbound channel adapter.
As AMQP broker implementation in the sample uses https://www.rabbitmq.com/[RabbitMQ].
NOTE: In order to run the example, you need a running instance of RabbitMQ.
A local installation with just the basic defaults suffices.
For detailed RabbitMQ installation procedures, see https://www.rabbitmq.com/install.html[https://www.rabbitmq.com/install.html]
Once the sample application is started, 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 by Spring Integration and printed to the console.
The following image illustrates the basic set of Spring Integration components used in this sample:
.The Spring Integration graph of the AMQP sample
image::spring-integration-amqp-sample-graph.png[align="center"]

View File

@@ -0,0 +1,59 @@
[[amqp-strict-ordering]]
= Strict Message Ordering
This section describes message ordering for inbound and outbound messages.
[[inbound]]
== Inbound
If you require strict ordering of inbound messages, you must configure the inbound listener container's `prefetchCount` property to `1`.
This is because, if a message fails and is redelivered, it arrives after existing prefetched messages.
Since Spring AMQP version 2.0, the `prefetchCount` defaults to `250` for improved performance.
Strict ordering requirements come at the cost of decreased performance.
[[outbound]]
== Outbound
Consider the following integration flow:
[source, java]
----
@Bean
public IntegrationFlow flow(RabbitTemplate template) {
return IntegrationFlow.from(Gateway.class)
.splitWith(s -> s.delimiters(","))
.<String, String>transform(String::toUpperCase)
.handle(Amqp.outboundAdapter(template).routingKey("rk"))
.get();
}
----
Suppose we send messages `A`, `B` and `C` to the gateway.
While it is likely that messages `A`, `B`, `C` are sent in order, there is no guarantee.
This is because the template "`borrows`" a channel from the cache for each send operation, and there is no guarantee that the same channel is used for each message.
One solution is to start a transaction before the splitter, but transactions are expensive in RabbitMQ and can reduce performance several hundred-fold.
To solve this problem in a more efficient manner, starting with version 5.1, Spring Integration provides the `BoundRabbitChannelAdvice` which is a `HandleMessageAdvice`.
See xref:handler-advice/handle-message.adoc[Handling Message Advice].
When applied before the splitter, it ensures that all downstream operations are performed on the same channel and, optionally, can wait until publisher confirmations for all sent messages are received (if the connection factory is configured for confirmations).
The following example shows how to use `BoundRabbitChannelAdvice`:
[source, java]
----
@Bean
public IntegrationFlow flow(RabbitTemplate template) {
return IntegrationFlow.from(Gateway.class)
.splitWith(s -> s.delimiters(",")
.advice(new BoundRabbitChannelAdvice(template, Duration.ofSeconds(10))))
.<String, String>transform(String::toUpperCase)
.handle(Amqp.outboundAdapter(template).routingKey("rk"))
.get();
}
----
Notice that the same `RabbitTemplate` (which implements `RabbitOperations`) is used in the advice and the outbound adapter.
The advice runs the downstream flow within the template's `invoke` method so that all operations run on the same channel.
If the optional timeout is provided, when the flow completes, the advice calls the `waitForConfirmsOrDie` method, which throws an exception if the confirmations are not received within the specified time.
IMPORTANT: There must be no thread hands-off in the downstream flow (`QueueChannel`, `ExecutorChannel`, and others).

View File

@@ -0,0 +1,14 @@
[[amqp-user-id]]
= Outbound User ID
:page-section-summary-toc: 1
Spring AMQP version 1.6 introduced a mechanism to allow the specification of a default user ID for outbound messages.
It has always been possible to set the `AmqpHeaders.USER_ID` header, which now takes precedence over the default.
This might be useful to message recipients.
For inbound messages, if the message publisher sets the property, it is made available in the `AmqpHeaders.RECEIVED_USER_ID` header.
Note that RabbitMQ https://www.rabbitmq.com/validated-user-id.html[validates that the user ID is the actual user ID for the connection or that the connection allows impersonation].
To configure a default user ID for outbound messages, configure it on a `RabbitTemplate` and configure the outbound adapter or gateway to use that template.
Similarly, to set the user ID property on replies, inject an appropriately configured template into the inbound gateway.
See the https://docs.spring.io/spring-amqp/reference/html/_reference.html#template-user-id[Spring AMQP documentation] for more information.

View File

@@ -1,5 +1,5 @@
[[barrier]]
=== Thread Barrier
= Thread Barrier
Sometimes, we need to suspend a message flow thread until some other asynchronous event occurs.
For example, consider an HTTP request that publishes a message to RabbitMQ.
@@ -35,9 +35,11 @@ An exception is thrown if a second thread arrives with the same correlation.
The following example shows how to use a custom header for correlation:
====
[tabs]
======
Java::
+
[source, java, role="primary"]
.Java
----
@ServiceActivator(inputChannel="in")
@Bean
@@ -54,8 +56,10 @@ public MessageHandler releaser(MessageTriggerAction barrier) {
return barrier::trigger;
}
----
XML::
+
[source, xml, role="secondary"]
.XML
----
<int:barrier id="barrier1" input-channel="in" output-channel="out"
correlation-strategy-expression="headers['myHeader']"
@@ -66,7 +70,7 @@ public MessageHandler releaser(MessageTriggerAction barrier) {
<int:outbound-channel-adapter channel="release" ref="barrier1.handler" method="trigger" />
----
====
======
Depending on which one has a message arrive first, either the thread sending a message to `in` or the thread sending a message to `release` waits for up to ten seconds until the other message arrives.
When the message is released, the `out` channel is sent a message that combines the result of invoking the custom `MessageGroupProcessor` bean, named `myOutputProcessor`.

View File

@@ -1,5 +1,5 @@
[[bridge]]
=== Messaging Bridge
= Messaging Bridge
A messaging bridge is a relatively trivial endpoint that 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.
@@ -15,34 +15,29 @@ In that case, the channels can be provided as the 'input-channel' and 'output-ch
If data format translation is not required, the messaging bridge may indeed be sufficient.
[[bridge-namespace]]
==== Configuring a Bridge with XML
== Configuring a Bridge with XML
You can use the `<bridge>` element is used to create a messaging bridge between two message channels or channel adapters.
To do so, provide the `input-channel` and `output-channel` attributes, as the following example shows:
====
[source,xml]
----
<int:bridge input-channel="input" output-channel="output"/>
----
====
As mentioned above, a common use case for the messaging bridge is to connect a `PollableChannel` to a `SubscribableChannel`.
When performing this role, the messaging bridge may also serve as a throttler:
====
[source,xml]
----
<int:bridge input-channel="pollable" output-channel="subscribable">
<int:poller max-messages-per-poll="10" fixed-rate="5000"/>
</int:bridge>
----
====
You can use a similar mechanism to connecting channel adapters.
The following example shows a simple "`echo`" between the `stdin` and `stdout` adapters from Spring Integration's `stream` namespace:
====
[source,xml]
----
<int-stream:stdin-channel-adapter id="stdin"/>
@@ -51,7 +46,6 @@ The following example shows a simple "`echo`" between the `stdin` and `stdout` a
<int:bridge id="echo" input-channel="stdin" output-channel="stdout"/>
----
====
Similar configurations work for other (potentially more useful) Channel Adapter bridges, such as file-to-JMS or mail-to-file.
Upcoming chapters cover the various channel adapters.
@@ -60,11 +54,10 @@ NOTE: If no 'output-channel' is defined on a bridge, the reply channel provided
If neither an output nor a reply channel is available, an exception is thrown.
[[bridge-annot]]
==== Configuring a Bridge with Java Configuration
== Configuring a Bridge with Java Configuration
The following example shows how to configure a bridge in Java by using the `@BridgeFrom` annotation:
====
[source, java]
----
@Bean
@@ -78,7 +71,6 @@ public SubscribableChannel direct() {
return new DirectChannel();
}
----
====
The following example shows how to configure a bridge in Java by using the `@BridgeTo` annotation:
@@ -111,7 +103,7 @@ public BridgeHandler bridge() {
----
[[bridge-dsl]]
==== Configuring a Bridge with the Java DSL
== Configuring a Bridge with the Java DSL
You can use the Java Domain Specific Language (DSL) to configure a bridge, as the following example shows:

View File

@@ -1,13 +1,15 @@
[[camel]]
== Apache Camel Support
= Apache Camel Support
Spring Integration provides an API and configuration to communicate with https://camel.apache.org[Apache Camel] endpoints declared in the same application context.
You need to include this dependency into your project:
====
[tabs]
======
Maven::
+
[source, xml, subs="normal", role="primary"]
.Maven
----
<dependency>
<groupId>org.springframework.integration</groupId>
@@ -15,12 +17,14 @@ You need to include this dependency into your project:
<version>{project-version}</version>
</dependency>
----
Gradle::
+
[source, groovy, subs="normal", role="secondary"]
.Gradle
----
compile "org.springframework.integration:spring-integration-camel:{project-version}"
----
====
======
Spring Integration and Apache Camel implement Enterprise Integration Patterns and provide a convenient way to compose them, but the projects use a different approach for their API and abstractions implementation.
Spring Integration fully relies on a dependency injection container from Spring Core.
@@ -44,7 +48,7 @@ For a similar developer experience, Spring Integration now provides a channel ad
There is no inbound channel adapter because subscribing to a `MessageChannel` for consuming Apache Camel messages is enough from the Spring Integration API and abstractions perspective.
[[camel-channel-adapter]]
=== Outbound Channel Adapter for Apache Camel
== Outbound Channel Adapter for Apache Camel
The `CamelMessageHandler` is an `AbstractReplyProducingMessageHandler` implementation and can work in both one-way (default) and request-reply modes.
It uses an `org.apache.camel.ProducerTemplate` to send (or send and receive) into an `org.apache.camel.Endpoint`.
@@ -62,7 +66,6 @@ The `exchangeProperties` can be customized via a SpEL expression, which must eva
If a `ProducerTemplate` is not provided, it is created via a `CamelContext` bean resolved from the application context.
====
[source, java]
----
@Bean
@@ -79,11 +82,9 @@ CamelMessageHandler camelService(ProducerTemplate producerTemplate) {
return camelMessageHandler;
}
----
====
For Java DSL flow definitions this channel adapter can be configured with a few variants provided by the `Camel` factory:
====
[source, java]
----
@Bean
@@ -98,4 +99,3 @@ private void camelRoute(RouteBuilder routeBuilder) {
routeBuilder.from("direct:inbound").transform(routeBuilder.simple("${body.toUpperCase()}"));
}
----
====

View File

@@ -1,14 +1,16 @@
[[cassandra]]
== Apache Cassandra Support
= Apache Cassandra Support
Spring Integration provides channel adapters (starting with version 6.0) for performing database operations against an Apache Cassandra cluster.
It is fully based on the https://spring.io/projects/spring-data-cassandra[Spring Data for Apache Cassandra] project.
You need to include this dependency into your project:
====
[tabs]
======
Maven::
+
[source, xml, subs="normal", role="primary"]
.Maven
----
<dependency>
<groupId>org.springframework.integration</groupId>
@@ -16,15 +18,17 @@ You need to include this dependency into your project:
<version>{project-version}</version>
</dependency>
----
Gradle::
+
[source, groovy, subs="normal", role="secondary"]
.Gradle
----
compile "org.springframework.integration:spring-integration-cassandra:{project-version}"
----
====
======
[[cassandra-outbound]]
=== Cassandra Outbound Components
== Cassandra Outbound Components
The `CassandraMessageHandler` is an `AbstractReplyProducingMessageHandler` implementation and can work in both one-way (default) and request-reply modes (a `producesReply` option).
It is asynchronous by default (`setAsync(false)` to reset) and performs reactive `INSERT`, `UPDATE`, `DELETE` or `STATEMENT` operations against the provided `ReactiveCassandraOperations`.
@@ -33,9 +37,11 @@ The `ingestQuery` sets the mode into an `INSERT`; the `query` or `statementExpre
The following code snippets demonstrate various configuration for this channel adapter or gateway:
====
[tabs]
======
Java DSL::
+
[source, java, role="primary"]
.Java DSL
----
@Bean
IntegrationFlow cassandraSelectFlow(ReactiveCassandraOperations cassandraOperations) {
@@ -47,8 +53,10 @@ IntegrationFlow cassandraSelectFlow(ReactiveCassandraOperations cassandraOperati
.channel(c -> c.flux("resultChannel"));
}
----
Kotlin DSL::
+
[source, kotlin, role="secondary"]
.Kotlin DSL
----
@Bean
fun outboundReactive(cassandraOperations: ReactiveCassandraOperations) =
@@ -59,8 +67,10 @@ fun outboundReactive(cassandraOperations: ReactiveCassandraOperations) =
) { async(false) }
}
----
Java::
+
[source, java, role="secondary"]
.Java
----
@ServiceActivator(inputChannel = "cassandraSelectChannel")
@Bean
@@ -79,8 +89,10 @@ public MessageHandler cassandraMessageHandler() {
return cassandraMessageHandler;
}
----
XML::
+
[source, xml, role="secondary"]
.XML
----
<int-cassandra:outbound-channel-adapter id="outboundAdapter"
cassandra-template="cassandraTemplate"
@@ -100,7 +112,7 @@ public MessageHandler cassandraMessageHandler() {
<int-cassandra:parameter-expression name="size" expression="headers.limit"/>
</int-cassandra:outbound-gateway>
----
====
======
If a `CassandraMessageHandler` is used as a gateway in the default async mode, a `Mono<WriteResult>` is produced, which is handled according to the provided `MessageChannel` implementation.
For true reactive processing a `FluxMessageChannel` is recommended for the output channel configuration.
@@ -112,7 +124,6 @@ If the payload is a list of entities, then the respective batch operation is per
The `ingestQuery` mode expects the payload to be present as a matrix of values to insert - `List<List<?>>`.
For example, if the entity is like this:
====
[source,java]
----
@Table("book")
@@ -125,11 +136,9 @@ public record Book(@PrimaryKey String isbn,
}
----
====
And channel adapter has this configuration:
====
[source,java]
----
@Bean
@@ -141,11 +150,9 @@ public MessageHandler cassandraMessageHandler3() {
return cassandraMessageHandler;
}
----
====
The request message payload must be converted like this:
====
[source,java]
----
List<List<Object>> ingestBooks =
@@ -160,7 +167,6 @@ List<List<Object>> ingestBooks =
book.isInStock()))
.toList();
----
====
For more sophisticated use-cases, the payload can be as an instance of `com.datastax.oss.driver.api.core.cql.Statement`.
The `com.datastax.oss.driver.api.querybuilder.QueryBuilder` API is recommended to build various statements to execute against Apache Cassandra.
@@ -168,12 +174,10 @@ For example, to remove all the data from the `Book` table, a message with a payl
Alternatively, for logic based on a request message, a `statementExpression` or `statementProcessor` can be provided for the `CassandraMessageHandler` to build a `Statement` based on that message.
For convenience, a `com.datastax.oss.driver.api.querybuilder` is registered as an `import` into a SpEL evaluation context, so a target expression can be as simple as this:
====
[source,xml]
----
statement-expression="T(QueryBuilder).selectFrom("book").all()"
----
====
The `setParameterExpressions(Map<String, Expression> parameterExpressions)` represents bindable named query parameters and is used only with a `setQuery(String query)` option.
See Java and XML samples mentioned above.

View File

@@ -1,5 +1,5 @@
[[chain]]
=== Message Handler Chain
= Message Handler Chain
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.
When several handlers need to be connected in a fixed, linear progression, this can lead to a much simpler configuration.
@@ -9,7 +9,7 @@ In either case, the chain requires only a single `input-channel` and a single `o
NOTE: The `MessageHandlerChain` is mostly designed for an XML configuration.
For Java DSL, an `IntegrationFlow` definition can be treated as a chain component, but it has nothing to do with concepts and principles described in this chapter below.
See <<./dsl.adoc#java-dsl,Java DSL>> for more information.
See xref:dsl.adoc#java-dsl[Java DSL] for more information.
TIP: Spring Integration's `Filter` provides a boolean property: `throwExceptionOnRejection`.
When you provide multiple selective consumers on the same point-to-point channel with different acceptance criteria, you should set this value 'true' (the default is `false`) so that the dispatcher knows that the message was rejected and, as a result, tries to pass the message on to other subscribers.
@@ -33,7 +33,7 @@ The next section focuses on namespace support for the chain element.
Most Spring Integration endpoints, such as service activators and transformers, are suitable for use within a `MessageHandlerChain`.
[[chain-namespace]]
==== Configuring a Chain
== Configuring a Chain
The `<chain>` element provides an `input-channel` attribute.
If the last element in the chain is capable of producing reply messages (optional), it also supports an `output-channel` attribute.
@@ -41,7 +41,6 @@ The sub-elements are then filters, transformers, splitters, and service-activato
The last element may also be a router or an outbound channel adapter.
The following example shows a chain definition:
====
[source,xml]
----
<int:chain input-channel="input" output-channel="output">
@@ -52,7 +51,6 @@ The following example shows a chain definition:
<int:service-activator ref="someService" method="someMethod"/>
</int:chain>
----
====
The `<header-enricher>` element used in the preceding example sets a message header named `thing1` with a value of `thing2` on the message.
A header enricher is a specialization of `Transformer` that touches only header values.
@@ -61,7 +59,6 @@ You could obtain the same result by implementing a `MessageHandler` that did the
The `<chain>` can be configured as the last "`closed-box`" consumer of the message flow.
For this solution, you can to put it at the end of the <chain> some <outbound-channel-adapter>, as the following example shows:
====
[source,xml]
----
<int:chain input-channel="input">
@@ -73,7 +70,6 @@ For this solution, you can to put it at the end of the <chain> some <outbound-ch
<int:logging-channel-adapter level="INFO" log-full-message="true"/>
</int:chain>
----
====
.Disallowed Attributes and Elements
[IMPORTANT]
@@ -88,13 +84,13 @@ These XML namespace parser constraints were added with Spring Integration 2.2.
If you try to use disallowed attributes and elements, the XML namespace parser throws a `BeanDefinitionParsingException`.
=====
==== Using the 'id' Attribute
[[using-the-id-attribute]]
== Using the 'id' Attribute
Beginning with Spring Integration 3.0, if a chain element is given an `id` attribute, the bean name for the element is a combination of the chain's `id` and the `id` of the element itself.
Elements without `id` attributes are not registered as beans, but each one is given a `componentName` that includes the chain `id`.
Consider the following example:
====
[source,xml]
----
<int:chain id="somethingChain" input-channel="input">
@@ -102,7 +98,6 @@ Consider the following example:
<int:object-to-json-transformer/>
</int:chain>
----
====
In the preceding example:
@@ -125,18 +120,17 @@ In this case, it is 'somethingChain$child#1'.
Note, this transformer is not registered as a bean within the application context, so it does not get a `beanName`.
However, its `componentName` has a value that is useful for logging and other purposes.
The `id` attribute for `<chain>` elements lets them be eligible for <<./jmx.adoc#jmx-mbean-exporter,JMX export>>, and they are trackable in the <<./message-history.adoc#message-history,message history>>.
The `id` attribute for `<chain>` elements lets them be eligible for xref:jmx.adoc#jmx-mbean-exporter[JMX export], and they are trackable in the xref:message-history.adoc[message history].
You can access them from the `BeanFactory` by using the appropriate bean name, as discussed earlier.
TIP: It is useful to provide an explicit `id` attribute on `<chain>` elements to simplify the identification of sub-components in logs and to provide access to them from the `BeanFactory` etc.
[[chain-gateway]]
==== Calling a Chain from within a Chain
== 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 use a messaging gateway by including a <gateway> element, as the following example shows:
====
[source,xml]
----
<int:chain id="main-chain" input-channel="in" output-channel="out">
@@ -168,7 +162,6 @@ To accomplish this, you can use a messaging gateway by including a <gateway> ele
</int:service-activator>
</int:chain>
----
====
In the preceding example, `nested-chain-a` is 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` is made after header enrichment.

View File

@@ -1,176 +1,176 @@
[[migration-1.0-2.0]]
=== Changes between Versions 1.0 and 2.0
= Changes between Versions 1.0 and 2.0
See the https://github.com/spring-projects/spring-integration/wiki/Spring-Integration-1.0-to-2.0-Migration-Guide[Migration Guide] for important changes that might affect your applications.
[[migration-spring-30-support]]
==== Spring 3 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.
[[2.0-spel-support]]
===== Support for the Spring Expression Language (SpEL)
=== 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 within various adapters.
This guide includes many samples.
[[conversion-support]]
===== Conversion Service and Converter
=== Conversion Service and Converter
You can now benefit from the conversion service support provided with Spring while configuring many Spring Integration components, such as a https://www.enterpriseintegrationpatterns.com/DatatypeChannel.html[Datatype channel].
See <<./channel.adoc#channel-implementations,Message Channel Implementations>> and <<./service-activator.adoc#service-activator,Service Activator>>.
See xref:channel/implementations.adoc[Message Channel Implementations] and xref:service-activator.adoc[Service Activator].
Also, the SpEL support mentioned in the previous point also relies upon the conversion service.
Therefore, you can register converters once and take advantage of them anywhere you use SpEL expressions.
[[task-scheduler-poller-support]]
===== `TaskScheduler` and `Trigger`
=== `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 (such as `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).
We also greatly simplified configuration of Spring Integration pollers by providing attributes for directly configuring rates, delays, cron expressions, and trigger references.
See <<./channel-adapter.adoc#channel-adapter,Channel Adapter>> for sample configurations.
See xref:overview.adoc#overview-endpoints-channeladapter[Channel Adapter] for sample configurations.
[[rest-support]]
===== `RestTemplate` and `HttpMessageConverter`
=== `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 <<./http.adoc#http-outbound,HTTP Outbound Components>> for more details.
See xref:http/outbound.adoc[HTTP Outbound Components] for more details.
[[new-eip]]
==== Enterprise Integration Pattern Additions
== Enterprise Integration Pattern Additions
Also in 2.0, we have added support for even more of the patterns described in Hohpe and Woolf's https://www.enterpriseintegrationpatterns.com/[Enterprise Integration Patterns] book.
[[new-message-history]]
===== Message History
=== Message History
We now provide support for the https://www.enterpriseintegrationpatterns.com/MessageHistory.html[message history] pattern, letting you keep track of all traversed components, including the name of each channel and endpoint as well as the timestamp of that traversal.
See <<./message-history.adoc#message-history,Message History>> for more details.
See xref:message-history.adoc[Message History] for more details.
[[new-message-store]]
===== Message Store
=== Message Store
We now provide support for the https://www.enterpriseintegrationpatterns.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 the resequencer.
Many sections of this guide include samples of how to use a message store, as it affects several areas of Spring Integration.
See <<./message-store.adoc#message-store,Message Store>>, <<./claim-check.adoc#claim-check,Claim Check>>, <<./channel.adoc#channel,Message Channels>>, <<./aggregator.adoc#aggregator,Aggregator>>, <<./jdbc.adoc#jdbc,JDBC Support>>`", and <<./resequencer.adoc#resequencer,Resequencer>> for more details.
See xref:message-store.adoc[Message Store], xref:claim-check.adoc[Claim Check], xref:channel.adoc[Message Channels], xref:overview.adoc#overview-endpoints-aggregator[Aggregator], xref:jdbc.adoc[JDBC Support]`", and xref:resequencer.adoc[Resequencer] for more details.
[[new-claim-check]]
===== Claim Check
=== Claim Check
We have added an implementation of the https://www.enterpriseintegrationpatterns.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`".
This lets you reduce bandwidth and avoid potential security issues when sending messages across channels.
See <<./claim-check.adoc#claim-check,Claim Check>> for more details.
See xref:claim-check.adoc[Claim Check] for more details.
[[new-control-bus]]
===== Control Bus
=== Control Bus
We have provided implementations of the https://www.enterpriseintegrationpatterns.com/ControlBus.html[control bus] pattern, which lets you use messaging to manage and monitor endpoints and channels.
The implementations include both a SpEL-based approach and one that runs Groovy scripts.
See <<./control-bus.adoc#control-bus,Control Bus>> and <<./groovy.adoc#groovy-control-bus,Control Bus>> for more details.
See xref:groovy.adoc#groovy-control-bus[Control Bus] and xref:groovy.adoc#groovy-control-bus[Control Bus] for more details.
[[new-adapters]]
==== New Channel Adapters and Gateways
== New Channel Adapters and Gateways
We have added several new channel adapters and messaging gateways in Spring Integration 2.0.
[[new-ip]]
===== TCP and UDP Adapters
=== TCP and UDP Adapters
We have added channel adapters for receiving and sending messages over the TCP and UDP internet protocols.
See <<./ip.adoc#ip,TCP and UDP Support>> for more details.
See xref:ip.adoc[TCP and UDP Support] for more details.
See also the following blog: https://spring.io/blog/2010/03/29/using-udp-and-tcp-adapters-in-spring-integration-2-0-m3/["`Using UDP and TCP Adapters in Spring Integration 2.0 M3`"].
[[new-twitter]]
===== Twitter Adapters
=== 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 https://github.com/spring-projects/spring-integration-extensions/tree/main/spring-integration-social-twitter[Spring Integration Social Twitter] for more details.
[[new-xmpp]]
===== XMPP Adapters
=== XMPP Adapters
The new XMPP adapters support both chat messages and presence events.
See <<./xmpp.adoc#xmpp,XMPP Support>> for more details.
See xref:xmpp.adoc[XMPP Support] for more details.
[[new-ftp]]
===== FTP and FTPS Adapters
=== FTP and FTPS Adapters
Inbound and outbound file transfer support over FTP and FTPS is now available.
See <<./ftp.adoc#ftp,FTP/FTPS Adapters>> for more details.
See xref:ftp.adoc[FTP/FTPS Adapters] for more details.
[[new-sftp]]
===== SFTP Adapters
=== SFTP Adapters
Inbound and outbound file transfer support over SFTP is now available.
See <<./sftp.adoc#sftp,SFTP Adapters>> for more details.
See xref:sftp.adoc[SFTP Adapters] for more details.
[[new-feed]]
===== Feed Adapters
=== Feed Adapters
We have also added channel adapters for receiving news feeds (ATOM and RSS).
See <<./feed.adoc#feed,Feed Adapter>> for more details.
See xref:feed.adoc[Feed Adapter] for more details.
[[new-other]]
==== Other Additions
== Other Additions
Spring Integration adds a number of other features.
This section describes them.
[[new-groovy]]
===== Groovy Support
=== Groovy Support
Spring Integration 2.0 added Groovy support, letting you use the Groovy scripting language to provide integration and business logic.
See <<./groovy.adoc#groovy,Groovy support>> for more details.
See xref:groovy.adoc[Groovy support] for more details.
[[new-map-transformer]]
===== Map Transformers
=== Map Transformers
These symmetrical transformers convert payload objects to and from `Map` objects.
See <<./transformer.adoc#transformer,Transformer>> for more details.
See xref:transformer.adoc[Transformer] for more details.
[[new-json-transformer]]
===== JSON Transformers
=== JSON Transformers
These symmetrical transformers convert payload objects to and from JSON.
See <<./transformer.adoc#transformer,Transformer>> for more details.
See xref:transformer.adoc[Transformer] for more details.
[[new-serialize-transformer]]
===== Serialization Transformers
=== Serialization Transformers
These symmetrical transformers convert payload objects to and from byte arrays.
They also support the serializer and deserializer strategy interfaces that Spring 3.0.5 added.
See <<./transformer.adoc#transformer,Transformer>> for more details.
See xref:transformer.adoc[Transformer] for more details.
[[new-refactoring]]
==== Framework 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 developers should be minimal, you should read through this document to find what was changed.
Specifically, you should read <<./router.adoc#dynamic-routers,Dynamic Routers>>, <<./gateway.adoc#gateway,Messaging Gateways>>, <<./http.adoc#http-outbound,HTTP Outbound Components>>, <<./message.adoc#message,Message>>, and <<./aggregator.adoc#aggregator,Aggregator>>.
Specifically, you should read xref:router/dynamic-routers.adoc[Dynamic Routers], xref:gateway.adoc[Messaging Gateways], xref:http/outbound.adoc[HTTP Outbound Components], xref:overview.adoc#overview-components-message[Message], and xref:overview.adoc#overview-endpoints-aggregator[Aggregator].
If you directly depend on some of the core components (`Message`, `MessageHeaders`, `MessageChannel`, `MessageBuilder`, and others), 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
== New Source Control Management and Build Infrastructure
With Spring Integration 2.0, we switched our build environment to use Git for source control.
To access our repository, visit https://git.springsource.org/spring-integration.
We have also switched our build system to https://gradle.org/[Gradle].
[[new-samples]]
==== New Spring Integration Samples
== New Spring Integration Samples
With Spring Integration 2.0, we have decoupled the samples from our main release distribution.
Please read the following blog to get more information: https://spring.io/blog/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
== 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, you can download it at https://spring.io/tools/sts[Spring Tool Suite].

View File

@@ -1,15 +1,15 @@
[[migration-2.0-2.1]]
=== Changes between 2.0 and 2.1
= Changes between 2.0 and 2.1
See the https://github.com/spring-projects/spring-integration/wiki/Spring-Integration-2.0-to-2.1-Migration-Guide[Migration Guide] for important changes that might affect your applications.
[[x2.1-new-components]]
==== New Components
== New Components
Version 2.1 added a number of new components.
[[x2.1-new-scripting-support]]
===== JSR-223 Scripting Support
=== JSR-223 Scripting Support
In Spring Integration 2.0, we added support for https://groovy.codehaus.org/[Groovy].
With Spring Integration 2.1, we expanded support for additional languages substantially by implementing support for https://www.jcp.org/en/jsr/detail?id=223[JSR-223] ("`Scripting for the Java™ Platform`").
@@ -20,40 +20,40 @@ Now you have the ability to use any scripting language that supports JSR-223 inc
* Python and Jython
* Groovy
For further details, see <<./scripting.adoc#scripting,Scripting Support>>.
For further details, see xref:scripting.adoc[Scripting Support].
[[x2.1-new-amqp-support]]
===== AMQP Support
=== AMQP Support
Spring Integration 2.1 added several channel adapters for receiving and sending messages by using the https://www.amqp.org/[Advanced Message Queuing Protocol] (AMQP).
Furthermore, Spring Integration also provides a point-to-point message channel and a publish-subscribe message channel, both of which are backed by AMQP Exchanges and Queues.
For further details, see <<./amqp.adoc#amqp,AMQP Support>>.
For further details, see xref:amqp.adoc[AMQP Support].
[[x2.1-new-mongodb-support]]
===== MongoDB Support
=== MongoDB Support
As of version 2.1, Spring Integration provides support for https://www.mongodb.org/[MongoDB] by providing a MongoDB-based `MessageStore`.
For further details, see <<./mongodb.adoc#mongodb,MongoDb Support>>.
For further details, see xref:mongodb.adoc[MongoDb Support].
[[x2.1-new-redis-support]]
===== Redis Support
=== Redis Support
As of version 2.1, Spring Integration supports https://redis.io/[Redis], an advanced key-value store, by providing a Redis-based `MessageStore` as well as publish-subscribe messaging adapters.
For further details, see <<./redis.adoc#redis,Redis Support>>.
For further details, see xref:redis.adoc[Redis Support].
[[x2.1-new-resource-support]]
===== Support for Spring's Resource abstraction
=== Support for Spring's Resource abstraction
In version 2.1, we 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 classpath resource.
Therefore, it is similar to but more generic than the file inbound channel adapter.
For further details, see <<./resource.adoc#resource-inbound-channel-adapter,Resource Inbound Channel Adapter>>.
For further details, see xref:resource.adoc#resource-inbound-channel-adapter[Resource Inbound Channel Adapter].
[[x2.1-new-stored-proc-support]]
===== Stored Procedure Components
=== Stored Procedure Components
With Spring Integration 2.1, the `JDBC` Module also provides stored procedure support by adding several new components, including inbound and outbound channel adapters and an outbound gateway.
The stored procedure support leverages Spring's https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/core/simple/SimpleJdbcCall.html[`SimpleJdbcCall`] class and consequently supports stored procedures for:
@@ -73,54 +73,54 @@ The stored procedure components also support SQL functions for the following dat
* Oracle
* PostgreSQL
For further details, see <<./jdbc.adoc#stored-procedures,Stored Procedures>>.
For further details, see xref:jdbc/stored-procedures.adoc[Stored Procedures].
[[x2.1-new-xpath-filter-support]]
===== XPath and XML Validating Filter
=== XPath and XML Validating Filter
Spring Integration 2.1 provides a new XPath-based message filter.
It is part of the `XML` module.
The XPath filter lets you filter messages by using XPath Expressions.
We also added documentation for the XML validating filter.
For more details, see <<./xml.adoc#xml-xpath-filter,Using the XPath Filter>> and <<./xml.adoc#xml-validating-filter,XML Validating Filter>>.
For more details, see xref:xml/xpath-filter.adoc[Using the XPath Filter] and xref:xml/validating-filter.adoc[XML Validating Filter].
[[x2.1-new-payload-enricher-support]]
===== Payload Enricher
=== Payload Enricher
Since Spring Integration 2.1, we added the payload enricher.
A payload enricher defines an endpoint that typically passes a https://docs.spring.io/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, see <<./content-enrichment.adoc#payload-enricher,Payload Enricher>>.
For further details, see xref:content-enrichment.adoc#payload-enricher[Payload Enricher].
[[x2.1-new-ftp-outbound-gateway]]
===== FTP and SFTP Outbound Gateways
=== FTP and SFTP Outbound Gateways
Spring Integration 2.1 provides two new outbound gateways to interact with remote File Transfer Protocol (FTP) or Secure File Transfer Protocol (SFT) servers.
These two gateways let you 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, see <<./ftp.adoc#ftp-outbound-gateway,FTP Outbound Gateway>> and <<./sftp.adoc#sftp-outbound-gateway,SFTP Outbound Gateway>>.
For further details, see xref:ftp/outbound-gateway.adoc[FTP Outbound Gateway] and xref:sftp/outbound-gateway.adoc[SFTP Outbound Gateway].
[[x2.1-new-ftp-session-caching]]
===== 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 (for example, FTP, SFTP, and others).
Specifically, we deprecated the `cache-sessions` attribute (which is available via the XML namespace support).
As an alternative, we added the `sessionCacheSize` and `sessionWaitTimeout` attributes on the `CachingSessionFactory`.
For further details, see <<./ftp.adoc#ftp-session-caching,FTP Session Caching>> and <<./sftp.adoc#sftp-session-caching,SFTP Session Caching>>.
For further details, see xref:ftp/session-caching.adoc[FTP Session Caching] and xref:sftp/session-caching.adoc[SFTP Session Caching].
[[x2.1-framework-refactorings]]
==== Framework Refactoring
== Framework Refactoring
We refactored the Spring Integration framework in a number of ways, all described in this section.
[[x2.1-router-standardization]]
===== Standardizing Router Configuration
=== Standardizing Router Configuration
We standardized router parameters across all router implementations with Spring Integration 2.1 to provide a more consistent user experience.
@@ -134,13 +134,13 @@ If, however, you do want to drop messages silently, you can set `default-output-
IMPORTANT: With the standardization of router parameters and the consolidation of the parameters described earlier, older Spring Integration based applications may break.
For further details, see `<<./router.adoc#router,Routers>>`.
For further details, see `xref:router.adoc[Routers]`.
[[x2.1-schema-updated]]
===== XML Schemas updated to 2.1
=== XML Schemas updated to 2.1
Spring Integration 2.1 ships with an updated XML Schema (version 2.1).
It provides many improvements, such as the Router standardizations <<x2.1-router-standardization,discussed earlier>>.
It provides many improvements, such as the Router standardizations xref:changes-2.0-2.1.adoc#x2.1-router-standardization[discussed earlier].
From now on, developers must always declare the latest XML schema (currently version 2.1).
Alternatively, they can use the version-less schema.
@@ -148,7 +148,6 @@ Generally, the best option is to use version-less namespaces, as these automatic
The following example declares a version-less Spring Integration namespace:
====
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
@@ -162,11 +161,9 @@ The following example declares a version-less Spring Integration namespace:
...
</beans>
----
====
The following example declares a Spring Integration namespace with an explicit version:
====
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
@@ -180,19 +177,18 @@ The following example declares a Spring Integration namespace with an explicit v
...
</beans>
----
====
The old 1.0 and 2.0 schemas are still there.
However, if an application context still references one of those deprecated schemas, the validator fails on initialization.
[[x2.1-source-control-infrastructure]]
==== Source Control Management and Build Infrastructure
== Source Control Management and Build Infrastructure
Version 2.1 introduced a number of changes to source control management and build infrastructure.
This section covers those changes.
[[x2.1-move-to-github]]
===== Source Code Now Hosted on Github
=== Source Code Now Hosted on Github
Since version 2.0, the Spring Integration project uses https://git-scm.com/[Git] for version control.
To increase community visibility even further, the project was moved from SpringSource hosted Git repositories to https://www.github.com/[Github].
@@ -204,13 +200,13 @@ In fact, core committers now follow the same process as contributors.
For more details, see https://github.com/spring-projects/spring-integration/blob/main/CONTRIBUTING.adoc[Contributing].
[[x2.1-sonar]]
===== Improved Source Code Visibility with 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, we set up an instance of https://www.sonarqube.org/[Sonar].
We gather metrics nightly and make them available at https://sonar.spring.io/dashboard?id=org.springframework.integration%3Aspring-integration%3Amain[sonar.spring.io].
[[x2.1-new-samples]]
==== 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, such as samples that cover AMQP support, a sample that showcases the new payload enricher, a sample illustrating techniques for testing Spring Integration flow fragments, and a sample for executing stored procedures against Oracle databases.
For details, visit https://github.com/spring-projects/spring-integration-samples[spring-integration-samples].

View File

@@ -1,51 +1,51 @@
[[migration-2.1-2.2]]
=== Changes between 2.1 and 2.2
= Changes between 2.1 and 2.2
See the https://github.com/spring-projects/spring-integration/wiki/Spring-Integration-2.1-to-2.2-Migration-Guide[Migration Guide] for important changes that might affect your applications.
You can find migration guides for all versions back to 2.1 on the https://github.com/spring-projects/spring-integration/wiki[wiki].
[[x2.2-new-components]]
==== New Components
== New Components
Version 2.2 added a number of new components.
[[x2.2-redis-store-adapters]]
===== `RedisStore` Inbound and Outbound Channel Adapters
=== `RedisStore` Inbound and Outbound Channel Adapters
Spring Integration now has `RedisStore` Inbound and Outbound Channel Adapters, letting you write and read `Message` payloads to and from Redis collections.
For more information, see <<./redis.adoc#redis-store-outbound-channel-adapter,RedisStore Outbound Channel Adapter>> and <<./redis.adoc#redis-store-inbound-channel-adapter,Redis Store Inbound Channel Adapter>>.
For more information, see xref:redis.adoc#redis-store-outbound-channel-adapter[RedisStore Outbound Channel Adapter] and xref:redis.adoc#redis-store-inbound-channel-adapter[Redis Store Inbound Channel Adapter].
[[x2.2-mongo-adapters]]
===== MongoDB Inbound and Outbound Channel Adapters
=== MongoDB Inbound and Outbound Channel Adapters
Spring Integration now has MongoDB inbound and outbound channel adapters, letting you write and read `Message` payloads to and from a MongoDB document store.
For more information, see <<./mongodb.adoc#mongodb-outbound-channel-adapter,MongoDB Outbound Channel Adapter>> and <<./mongodb.adoc#mongodb-inbound-channel-adapter,MongoDB Inbound Channel Adapter>>.
For more information, see xref:mongodb.adoc#mongodb-outbound-channel-adapter[MongoDB Outbound Channel Adapter] and xref:mongodb.adoc#mongodb-inbound-channel-adapter[MongoDB Inbound Channel Adapter].
[[x2.2-jpa]]
===== JPA Endpoints
=== 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:
* <<./jpa.adoc#jpa-inbound-channel-adapter,Inbound channel adapter>>
* <<./jpa.adoc#jpa-outbound-channel-adapter,Outbound channel adapter>>
* <<./jpa.adoc#jpa-updating-outbound-gateway,Updating outbound gateway>>
* <<./jpa.adoc#jpa-retrieving-outbound-gateway,Retrieving outbound gateway>>
* xref:jpa/inbound-channel-adapter.adoc[Inbound channel adapter]
* xref:jpa/outbound-channel-adapter.adoc[Outbound channel adapter]
* xref:jpa/outbound-gateways.adoc#jpa-updating-outbound-gateway[Updating outbound gateway]
* xref:jpa/outbound-gateways.adoc#jpa-retrieving-outbound-gateway[Retrieving outbound gateway]
For more information, see <<./jpa.adoc#jpa,JPA Support>>.
For more information, see xref:jpa.adoc[JPA Support].
[[x2.2-general]]
==== General Changes
== General Changes
This section describes general changes from version 2.1 to version 2.2.
[[x2.2-spring-31]]
===== Spring 3.1 Used by Default
=== Spring 3.1 Used by Default
Spring Integration now uses Spring 3.1.
[[x2.2-handler-advice]]
===== Adding Behavior to Endpoints
=== Adding Behavior to Endpoints
The ability to add an `<advice-chain/>` to a poller has been available for some time.
However, the behavior added by this affects the entire integration flow.
@@ -58,20 +58,20 @@ In addition, we added three standard advice classes for this purpose:
* `MessageHandlerCircuitBreakerAdvice`
* `ExpressionEvaluatingMessageHandlerAdvice`
For more information, see <<./handler-advice.adoc#message-handler-advice-chain,Adding Behavior to Endpoints>>.
For more information, see xref:handler-advice.adoc[Adding Behavior to Endpoints].
[[x2.2-transaction-sync]]
===== Transaction Synchronization and Pseudo Transactions
=== 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, you can enable these features when no "`real`" transaction is present, by means of a `PseudoTransactionManager`.
For more information, see <<./transactions.adoc#transaction-synchronization,Transaction Synchronization>>.
For more information, see xref:transactions.adoc#transaction-synchronization[Transaction Synchronization].
[[x2.2-file-adapter]]
===== File Adapter: Improved File Overwrite and Append Handling
=== File Adapter: Improved File Overwrite and Append Handling
When using the file outbound channel adapter or the file outbound gateway, you can use a new `mode` property.
Prior to Spring Integration 2.2, target files were replaced when they existed.
@@ -82,10 +82,10 @@ Now you can specify the following options:
* `FAIL`
* `IGNORE`
For more information, see <<./file.adoc#file-writing-destination-exists,Dealing with Existing Destination Files>>.
For more information, see xref:file/writing.adoc#file-writing-destination-exists[Dealing with Existing Destination Files].
[[x2.2-outbound-gateways]]
===== Reply-Timeout Added to More Outbound Gateways
=== Reply-Timeout Added to More Outbound Gateways
The XML Namespace support adds the reply-timeout attribute to the following outbound gateways:
@@ -96,7 +96,7 @@ The XML Namespace support adds the reply-timeout attribute to the following outb
* WS Outbound Gateway
[[x2.2-amqp-11]]
===== Spring-AMQP 1.1
=== 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 the following:
@@ -108,17 +108,19 @@ This enables several features to be used within a Spring Integration application
* Support for dead letter exchanges and dead letter queues
[[x2.2-jdbc-11]]
===== JDBC Support - Stored Procedures Components
=== JDBC Support - Stored Procedures Components
====== SpEL Support
[[spel-support]]
==== 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 by using the Spring Expression Language (SpEL).
Doing so lets you specify the stored procedures to be invoked at runtime.
For example, you can provide stored procedure names that you would like to execute through message headers.
For more information, see <<./jdbc.adoc#stored-procedures,Stored Procedures>>.
For more information, see xref:jdbc/stored-procedures.adoc[Stored Procedures].
====== JMX Support
[[jmx-support]]
==== JMX Support
The stored procedure components now provide basic JMX support, exposing some of their properties as MBeans:
@@ -127,37 +129,37 @@ The stored procedure components now provide basic JMX support, exposing some of
* `JdbcCallOperations` cache statistics
[[x2.2-jdbc-gateway-update-optional]]
===== JDBC Support: Outbound Gateway
=== JDBC Support: Outbound Gateway
When you use the JDBC outbound gateway, the update query is no longer mandatory.
You can now provide only a select query by using the request message as a source of parameters.
[[x2.2-jdbc-message-store-channels]]
===== JDBC Support: Channel-specific Message Store Implementation
=== JDBC Support: Channel-specific Message Store Implementation
We added a new message channel-specific message store implementation, providing a more scalable solution using database-specific SQL queries.
For more information, see <<./jdbc.adoc#jdbc-message-store-channels,Backing Message Channels>>.
For more information, see xref:jdbc/message-store.adoc#jdbc-message-store-channels[Backing Message Channels].
[[x2.2-shutdown]]
===== Orderly Shutdown
=== Orderly Shutdown
We added a method called `stopActiveComponents()` to the `IntegrationMBeanExporter`.
It 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 Outbound Gateway Improvements
=== JMS Outbound Gateway Improvements
You can now configure the JMS outbound gateway to use a `MessageListener` container to receive replies.
Doing so can improve performance of the gateway.
[[x2.2-o-t-j-t]]
===== `ObjectToJsonTransformer`
=== `ObjectToJsonTransformer`
By default, the `ObjectToJsonTransformer` now sets the `content-type` header to `application/json`.
For more information, see <<./transformer.adoc#transformer,Transformer>>.
For more information, see xref:transformer.adoc[Transformer].
[[httpChanges]]
===== HTTP Support
=== HTTP Support
Java serialization over HTTP is no longer enabled by default.
Previously, when setting an `expected-response-type` on a `Serializable` object, the `Accept` header was not properly set up.

View File

@@ -1,16 +1,16 @@
[[migration-2.2-3.0]]
=== Changes Between 2.2 and 3.0
= Changes Between 2.2 and 3.0
See the https://github.com/spring-projects/spring-integration/wiki/Spring-Integration-2.2-to-3.0-Migration-Guide[Migration Guide] for important changes that might affect your applications.
You can find migration guides for all versions back to 2.1 on the https://github.com/spring-projects/spring-integration/wiki[wiki].
[[x3.0-new-components]]
==== New Components
== New Components
Version 3.0 added a number of new components.
[[x3.0-request-mapping]]
===== HTTP Request Mapping
=== HTTP Request Mapping
The HTTP module now provides powerful request mapping support for inbound endpoints.
We replaced the `UriPathHandlerMapping` class with `IntegrationRequestMappingHandlerMapping`, which is registered under the bean name of `integrationRequestMappingHandlerMapping` in the application context.
@@ -18,29 +18,29 @@ Upon parsing of the HTTP inbound endpoint, either a new `IntegrationRequestMappi
To achieve flexible request mapping configuration, Spring Integration provides the `<request-mapping/>` child element for `<http:inbound-channel-adapter/>` and the `<http:inbound-gateway/>`.
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 <<./http.adoc#http-namespace,HTTP Namespace Support>>.
For more information see xref:http/namespace.adoc[HTTP Namespace Support].
[[x3.0-spel-customization]]
===== Spring Expression Language (SpEL) Configuration
=== Spring Expression Language (SpEL) Configuration
We added a new `IntegrationEvaluationContextFactoryBean` to allow configuration of custom `PropertyAccessor` implementations and functions for use in SpEL expressions throughout the framework.
For more information, see <<./spel.adoc#spel,Spring Expression Language (SpEL)>>.
For more information, see xref:spel.adoc[Spring Expression Language (SpEL)].
[[x3.0-spel-functions]]
===== SpEL Functions Support
=== SpEL Functions Support
To customize the SpEL `EvaluationContext` with static `Method` functions, we introduced the `<spel-function/>` component.
We also added two built-in functions: `#jsonPath` and `#xpath`.
For more information, see <<./spel.adoc#spel-functions,SpEL Functions>>.
For more information, see xref:spel.adoc#spel-functions[SpEL Functions].
[[x3.0-spel-property-accessors]]
===== SpEL PropertyAccessors Support
=== SpEL PropertyAccessors Support
To customize the SpEL `EvaluationContext` with `PropertyAccessor` implementations, we added the `<spel-property-accessors/>` component.
For more information, see <<./spel.adoc#spel-property-accessors,Property Accessors>>.
For more information, see xref:spel.adoc#spel-property-accessors[Property Accessors].
[[x3.0-redis-new-components]]
===== Redis: New Components
=== Redis: New Components
We added a new Redis-based https://docs.spring.io/spring-integration/api/org/springframework/integration/metadata/MetadataStore.html[`MetadataStore`] implementation.
You can use the `RedisMetadataStore` to maintain the state of a `MetadataStore` across application restarts.
@@ -52,38 +52,38 @@ This new `MetadataStore` implementation can be used with adapters, such as:
We added new queue-based components.
We added the `<int-redis:queue-inbound-channel-adapter/>` and `<int-redis:queue-outbound-channel-adapter/>` components to perform 'right pop' and 'left push' operations, respectively, on a Redis List.
For more information, "`see <<./redis.adoc#redis,Redis Support>>`".
For more information, "`see xref:redis.adoc[Redis Support]`".
[[x3.0-hcr]]
===== Header Channel Registry
=== Header Channel Registry
You can now instruct the framework to store reply channels 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 <<./content-enrichment.adoc#header-enricher,Header Enricher>> for more information.
See xref:content-enrichment.adoc#header-enricher[Header Enricher] for more information.
[[x3.0-configurable-mongo-MS]]
===== MongoDB support: New `ConfigurableMongoDbMessageStore`
=== MongoDB support: New `ConfigurableMongoDbMessageStore`
In addition to the existing `eMongoDbMessageStore`, we introduced a new `ConfigurableMongoDbMessageStore`.
This provides a more robust and flexible implementation of `MessageStore` for MongoDB.
It does not have backward compatibility with the existing store, but we recommend using it for new applications.
Existing applications can use it, but messages in the old store are not available.
See <<./mongodb.adoc#mongodb,MongoDb Support>> for more information.
See xref:mongodb.adoc[MongoDb Support] for more information.
[[x3.0-syslog]]
===== Syslog Support
=== Syslog Support
Building on the 2.2 `SyslogToMapTransformer`, Spring Integration 3.0 introduces `UDP` and `TCP` inbound channel adapters especially tailored for receiving SYSLOG messages.
For more information, see <<./syslog.adoc#syslog,Syslog Support>>.
For more information, see xref:syslog.adoc[Syslog Support].
[[x3.0-tail]]
===== `tail` Support
=== `tail` Support
We added file inbound channel adapters that use the `tail` command to generate messages when lines are added to the end of text files.
See <<./file.adoc#file-tailing,'tail'ing Files>>.
See xref:file/reading.adoc#file-tailing['tail'ing Files].
[[x3.0-jmx]]
===== JMX Support
=== JMX Support
We added `<int-jmx:tree-polling-channel-adapter/>`.
This adapter queries the JMX MBean tree and sends a message with a payload that is the graph of objects that match the query.
@@ -92,10 +92,10 @@ It permits simple transformation to, for example, JSON.
The `IntegrationMBeanExporter` now allows the configuration of a custom `ObjectNamingStrategy` by using the `naming-strategy` attribute.
For more information, see <<./jmx.adoc#jmx,JMX Support>>.
For more information, see xref:jmx.adoc[JMX Support].
[[x3.0-tcp-events]]
===== TCP/IP Connection Events and Connection Management
=== TCP/IP Connection Events and Connection Management
`TcpConnection` instances now emit `ApplicationEvent` instances (specifically `TcpConnectionEvent` instances) when connections are opened or closed or when an exception occurs.
This change lets applications be informed of changes to TCP connections by using the normal Spring `ApplicationListener` mechanism.
@@ -112,35 +112,35 @@ It lets applications broadcast to all open connections, among other uses.
Finally, the connection factories also provide a new method called `closeConnection(String connectionId)`, which lets applications explicitly close a connection by using its ID.
For more information see <<./ip.adoc#tcp-events,TCP Connection Events>>.
For more information see xref:changes-4.1-4.2.adoc#x4.2-tcp-events[TCP Connection Events].
[[x3.0-inbound-script]]
===== Inbound Channel Adapter Script Support
=== Inbound Channel Adapter Script Support
The `<int:inbound-channel-adapter/>` now supports using `<expression/>` and `<script/>` child elements to create a `MessageSource`.
See <<./channel-adapter.adoc#channel-adapter-expressions-and-scripts,Channel Adapter Expressions and Scripts>>.
See xref:channel-adapter.adoc#channel-adapter-expressions-and-scripts[Channel Adapter Expressions and Scripts].
[[x3.0-content-enricher-headers]]
===== Content Enricher: Headers Enrichment Support
=== Content Enricher: Headers Enrichment Support
The content enricher now provides configuration for `<header/>` child elements, to enrich the outbound message with headers based on the reply message from the underlying message flow.
For more information see <<./content-enrichment.adoc#payload-enricher,Payload Enricher>>.
For more information see xref:content-enrichment.adoc#payload-enricher[Payload Enricher].
[[x3.0-general]]
==== General Changes
== General Changes
This section describes general changes from version 2.2 to version 3.0.
[[x3.0-message-id]]
===== Message ID Generation
=== Message ID Generation
Previously, message IDs were generated by using the JDK `UUID.randomUUID()` method.
With this release, the default mechanism has been changed to use a more efficient and significantly faster algorithm.
In addition, we added the ability to change the strategy used to generate message IDs.
For more information see <<./message.adoc#message-id-generation,Message ID Generation>>.
For more information see xref:message.adoc#message-id-generation[Message ID Generation].
[[x3.0-gateway]]
===== "`<gateway>`" Changes
=== "`<gateway>`" Changes
You can now set common headers across all gateway methods, and we added more options for adding information to the message about which method was invoked.
@@ -149,10 +149,10 @@ You can now entirely customize the way that gateway method calls are mapped to m
The `GatewayMethodMetadata` is now a public class.
It lets you programmatically configure the `GatewayProxyFactoryBean` from Java.
For more information, see <<./gateway.adoc#gateway,Messaging Gateways>>.
For more information, see xref:gateway.adoc[Messaging Gateways].
[[x3.0-http-endpointss]]
===== HTTP Endpoint Changes
=== HTTP Endpoint Changes
* *Outbound Endpoint `encode-uri`*: `<http:outbound-gateway/>` and `<http:outbound-channel-adapter/>` now provide an `encode-uri` attribute to allow disabling the encoding of the URI object before sending the request.
@@ -167,10 +167,10 @@ These variables are available in both payload and header expressions.
* *Outbound Endpoint 'uri-variables-expression'*: HTTP outbound endpoints now support the `uri-variables-expression` attribute to specify an `Expression` to evaluate a `Map` for all URI variable placeholders within URL template.
This allows selection of a different map of expressions based on the outgoing message.
For more information, see <<./http.adoc#http,HTTP Support>>.
For more information, see xref:http.adoc[HTTP Support].
[[x3.0-json-transformers]]
===== Jackson Support (JSON)
=== Jackson Support (JSON)
* A new abstraction for JSON conversion has been introduced.
Implementations for Jackson 1.x and Jackson 2 are currently provided, with the version being determined by presence on the classpath.
@@ -178,47 +178,47 @@ Previously, only Jackson 1.x was supported.
* The `ObjectToJsonTransformer` and `JsonToObjectTransformer` now emit/consume headers containing type information.
For more information, see "`JSON Transformers`" in <<./transformer.adoc#transformer,Transformer>>.
For more information, see "`JSON Transformers`" in xref:transformer.adoc[Transformer].
[[x3.0-id-for-chain-sub-components]]
===== Chain Elements `id` Attribute
=== Chain Elements `id` Attribute
Previously, the `id` attribute for elements within a `<chain>` was ignored and, in some cases, disallowed.
Now, the `id` attribute is allowed for all elements within a `<chain>`.
The bean names of chain elements is a combination of the surrounding chain's `id` and the `id` of the element itself.
For example: 'myChain$child.myTransformer.handler'.
For more information see, <<./chain.adoc#chain,Message Handler Chain>>.
For more information see, xref:chain.adoc[Message Handler Chain].
[[x3.0-corr-endpoint-empty-groups]]
===== Aggregator 'empty-group-min-timeout' property
=== Aggregator 'empty-group-min-timeout' property
The `AbstractCorrelatingMessageHandler` provides a new property called `empty-group-min-timeout` to allow empty group expiry to run on a longer schedule than expiring partial groups.
Empty groups are not removed from the `MessageStore` until they have not been modified for at least this number of milliseconds.
For more information, see <<./aggregator.adoc#aggregator-xml,Configuring an Aggregator with XML>>.
For more information, see xref:aggregator.adoc#aggregator-xml[Configuring an Aggregator with XML].
[[x3.0-filelistfilter]]
===== Persistent File List Filters (file, (S)FTP)
=== Persistent File List Filters (file, (S)FTP)
New `FileListFilter` implementations that use a persistent `MetadataStore` are now available.
You can use these to prevent duplicate files after a system restart.
See <<./file.adoc#file-reading,Reading Files>>, <<./ftp.adoc#ftp-inbound,FTP Inbound Channel Adapter>>, and <<./sftp.adoc#sftp-inbound,SFTP Inbound Channel Adapter>> for more information.
See xref:file/reading.adoc[Reading Files], xref:ftp/inbound.adoc[FTP Inbound Channel Adapter], and xref:sftp/inbound.adoc[SFTP Inbound Channel Adapter] for more information.
[[x3.0-scripting-variables]]
===== Scripting Support: Variables Changes
=== Scripting Support: Variables Changes
We introduced a new `variables` attribute for scripting components.
In addition, variable bindings are now allowed for inline scripts.
See <<./groovy.adoc#groovy,Groovy support>> and <<./scripting.adoc#scripting,Scripting Support>> for more information.
See xref:groovy.adoc[Groovy support] and xref:scripting.adoc[Scripting Support] for more information.
[[x3.0-direct-channel-lb-ref]]
===== Direct Channel Load Balancing configuration
=== Direct Channel Load Balancing configuration
Previously, when configuring `LoadBalancingStrategy` on the channel's `dispatcher` child element, the only available option was to use a pre-defined enumeration of values which did not let developers set a custom implementation of the `LoadBalancingStrategy`.
You can now use `load-balancer-ref` to provide a reference to a custom implementation of the `LoadBalancingStrategy`.
For more information, see <<./channel.adoc#channel-implementations-directchannel,`DirectChannel`>>.
For more information, see xref:channel/implementations.adoc#channel-implementations-directchannel[`DirectChannel`].
[[x3.0-pub-sub]]
===== PublishSubscribeChannel Behavior
=== PublishSubscribeChannel Behavior
Previously, sending to a <publish-subscribe-channel/> that had no subscribers would return a `false` result.
If used in conjunction with a `MessagingTemplate`, this would result in an exception being thrown.
@@ -227,7 +227,7 @@ If the message is sent to at least the minimum number of subscribers, the send o
If an application expects to get an exception under these conditions, set the minimum subscribers to at least 1.
[[x3.0--s-ftp-changes]]
===== FTP, SFTP and FTPS Changes
=== FTP, SFTP and FTPS Changes
The FTP, SFTP and FTPS endpoints no longer cache sessions by default.
@@ -240,7 +240,8 @@ This method immediately closes idle sessions and causes in-use sessions to be cl
The `DefaultSftpSessionFactory` (in conjunction with a `CachingSessionFactory`) now supports multiplexing channels over a single SSH connection (SFTP Only).
====== FTP, SFTP and FTPS Inbound Adapters
[[ftp-sftp-and-ftps-inbound-adapters]]
==== FTP, SFTP and FTPS Inbound Adapters
Previously, there was no way to override the default filter used to process files retrieved from a remote server.
The `filter` attribute determines which files are retrieved, but the `FileReadingMessageSource` uses an `AcceptOnceFileListFilter`.
@@ -252,7 +253,8 @@ If you want the behavior of the `AcceptOnceFileListFilter` to be maintained acro
Inbound channel adapters now support the `preserve-timestamp` attribute, which sets the local file modified timestamp to the timestamp from the server (default: `false`).
====== FTP, SFTP, and FTPS Gateways
[[ftp-sftp-and-ftps-gateways]]
==== FTP, SFTP, and FTPS Gateways
The gateways now support the `mv` command, enabling the renaming of remote files.
@@ -265,16 +267,17 @@ By default, the same name as the remote file is used.
The `local-directory-expression` attribute is now supported, enabling the naming of local directories during retrieval (based on the remote directory).
====== Remote File Template
[[remote-file-template]]
==== Remote File Template
A new higher-level abstraction (`RemoteFileTemplate`) is provided over the `Session` implementations used by the FTP and SFTP modules.
While it is used internally by endpoints, you can also use this abstraction programmatically.
Like all Spring `*Template` implementations, it reliably closes the underlying session while allowing low level access to the session.
For more information, see <<./ftp.adoc#ftp,FTP/FTPS Adapters>> and <<./sftp.adoc#sftp,SFTP Adapters>>.
For more information, see xref:ftp.adoc[FTP/FTPS Adapters] and xref:sftp.adoc[SFTP Adapters].
[[x3.0-outbound-gateway-requires-reply]]
===== 'requires-reply' Attribute for Outbound Gateways
=== 'requires-reply' Attribute for Outbound Gateways
All outbound gateways (such as `<jdbc:outbound-gateway/>` or `<jms:outbound-gateway/>`) are designed for 'request-reply' scenarios.
A response is expected from the external service and is published to the `reply-channel` or the `replyChannel` message header.
@@ -299,7 +302,7 @@ By default, with this change, an exception is now thrown by most gateways.
To revert to the previous behavior, set `requires-reply` to `false`.
[[x3.0-amqp-mapping]]
===== AMQP Outbound Gateway Header Mapping
=== AMQP Outbound Gateway Header Mapping
Previously, the <int-amqp:outbound-gateway/> mapped headers before invoking the message converter, and the converter could overwrite headers such as `content-type`.
The outbound adapter maps the headers after the conversion, which means headers like `content-type` from the outbound `Message` (if present) are used.
@@ -310,7 +313,7 @@ The headers affected by the `SimpleMessageConverter` are `content-type` and `con
Custom message converters may set other headers.
[[x3.0-stored-proc-sql-return-type]]
===== Stored Procedure Components Improvements
=== Stored Procedure Components Improvements
For more complex database-specific types not supported by the standard `CallableStatement.getObject` method, we introduced two new additional attributes to the `<sql-parameter-definition/>` element with OUT-direction:
@@ -320,16 +323,16 @@ For more complex database-specific types not supported by the standard `Callable
The `row-mapper` attribute of the stored procedure inbound channel adapter `<returning-resultset/>` child element now supports a reference to a `RowMapper` bean definition.
Previously, it contained only a class name (which is still supported).
For more information, see <<./jdbc.adoc#stored-procedures,Stored Procedures>>.
For more information, see xref:jdbc/stored-procedures.adoc[Stored Procedures].
[[x3.0-ws-outbound-uri-substitution]]
===== Web Service Outbound URI Configuration
=== Web Service Outbound URI Configuration
The web service outbound gateway 'uri' attribute now supports `<uri-variable/>` substitution for all URI schemes supported by Spring Web Services.
For more information, see <<./ws.adoc#outbound-uri,Outbound URI Configuration>>.
For more information, see xref:ws.adoc#outbound-uri[Outbound URI Configuration].
[[x3.0-redis]]
===== Redis Adapter Changes
=== Redis Adapter Changes
The Redis inbound channel adapter can now use a `null` value for the `serializer` property, with the raw data being the message payload.
@@ -337,29 +340,29 @@ The Redis outbound channel adapter now has the `topic-expression` property to de
The Redis inbound channel adapter, in addition to the existing `topics` attribute, now has the `topic-patterns` attribute.
For more information, see <<./redis.adoc#redis,Redis Support>>.
For more information, see xref:redis.adoc[Redis Support].
[[x3.0-advising-filters]]
===== Advising Filters
=== Advising Filters
Previously, when a `<filter/>` had a `<request-handler-advice-chain/>`, the discard action was all performed within the scope of the advice chain (including any downstream flow on the `discard-channel`).
The filter element now has an attribute called `discard-within-advice` (default: `true`) to allow the discard action to be performed after the advice chain completes.
See <<./handler-advice.adoc#advising-filters,Advising Filters>>.
See xref:handler-advice/advising-filters.adoc[Advising Filters].
[[x3.0-annotation-advice]]
===== Advising Endpoints using Annotations
=== Advising Endpoints using Annotations
Request handler advice chains can now be configured using annotations.
See <<./handler-advice.adoc#advising-with-annotations,Advising Endpoints Using Annotations>>.
See xref:handler-advice/advising-with-annotations.adoc[Advising Endpoints Using Annotations].
[[x3.0-o-t-s-t]]
===== ObjectToStringTransformer Improvements
=== ObjectToStringTransformer Improvements
This transformer now correctly transforms `byte[]` and `char[]` payloads to `String`.
For more information, see <<./transformer.adoc#transformer,Transformer>>.
For more information, see xref:transformer.adoc[Transformer].
[[x3.0-jpa-changes]]
===== JPA Support Changes
=== JPA Support Changes
Payloads to persist or merge can now be of type `https://docs.oracle.com/javase/7/docs/api/java/lang/Iterable.html[java.lang.Iterable]`.
@@ -370,55 +373,55 @@ The JPA adapters now have additional attributes to optionally flush and clear en
Retrieving gateways had no mechanism to specify the first record to be retrieved, which is a common use case.
The retrieving gateways now support specifying this parameter by adding the `first-result` and `first-result-expression` attributes to the gateway definition.
For more information, see <<./jpa.adoc#jpa-retrieving-outbound-gateway,Retrieving Outbound Gateway>>.
For more information, see xref:jpa/outbound-gateways.adoc#jpa-retrieving-outbound-gateway[Retrieving Outbound Gateway].
The JPA retrieving gateway and inbound adapter now have an attribute to specify the maximum number of results in a result set as an expression.
In addition, we introduced the `max-results` attribute to replace `max-number-of-results`, which has been deprecated.
`max-results` and `max-results-expression` are used to provide the maximum number of results or an expression to compute the maximum number of results, respectively, in the result set.
For more information, see <<./jpa.adoc#jpa,JPA Support>>.
For more information, see xref:jpa.adoc[JPA Support].
[[x3.0-dalay-expression]]
===== Delayer: delay expression
=== Delayer: delay expression
Previously, the `<delayer>` provided a `delay-header-name` attribute to determine the delay value at runtime.
In complex cases, the `<delayer>` had to be preceded with a `<header-enricher>`.
Spring Integration 3.0 introduced the `expression` attribute and `expression` child element for dynamic delay determination.
The `delay-header-name` attribute is now deprecated, because you can specify the header evaluation in the `expression`.
In addition, we introduced the `ignore-expression-failures` to control the behavior when an expression evaluation fails.
For more information, see <<./delayer.adoc#delayer,Delayer>>.
For more information, see xref:delayer.adoc[Delayer].
[[x3.0-jdbc-mysql-v5_6_4]]
===== JDBC Message Store Improvements
=== JDBC Message Store Improvements
Spring Integration 3.0 adds a new set of DDL scripts for MySQL version 5.6.4 and higher.
Now MySQL supports fractional seconds and is thus improving the FIFO ordering when polling from a MySQL-based message store.
For more information, see <<./jdbc.adoc#jdbc-message-store-generic,The Generic JDBC Message Store>>.
For more information, see xref:jdbc/message-store.adoc#jdbc-message-store-generic[The Generic JDBC Message Store].
[[x3.0-event-for-imap-idle]]
===== IMAP Idle Connection Exceptions
=== IMAP Idle Connection Exceptions
Previously, if an IMAP idle connection failed, it was logged, but there was no mechanism to inform an application.
Such exceptions now generate `ApplicationEvent` instances.
Applications can obtain these events by using an `<int-event:inbound-channel-adapter>` or any `ApplicationListener` configured to receive an `ImapIdleExceptionEvent` (or one of its super classes).
[[x3.0-tcp-headers]]
===== Message Headers and TCP
=== Message Headers and TCP
The TCP connection factories now enable the configuration of a flexible mechanism to transfer selected headers (as well as the payload) over TCP.
A new `TcpMessageMapper` enables the selection of the headers, and you need to configure an appropriate serializer or deserializer to write the resulting `Map` to the TCP stream.
We added a `MapJsonSerializer` as a convenient mechanism to transfer headers and payload over TCP.
For more information, see <<./ip.adoc#ip-headers,Transferring Headers>>.
For more information, see xref:ip/correlation.adoc#ip-headers[Transferring Headers].
[[x3.0-jms-mdca-te]]
===== JMS Message Driven Channel Adapter
=== JMS Message Driven Channel Adapter
Previously, when configuring a `<message-driven-channel-adapter/>`, if you wished to use a specific `TaskExecutor`, you had to declare a container bean and provide it to the adapter by setting the `container` attribute.
We added the `task-executor`, letting it be set directly on the adapter.
This is in addition to several other container attributes that were already available.
[[x3.0-xslt-transformer]]
===== `XsltPayloadTransformer`
=== `XsltPayloadTransformer`
You can now specify the transformer factory class name by setting the `transformer-factory-class` attribute.
See `<<./xml.adoc#xml-xslt-payload-transformers,XsltPayloadTransformer>>`.
See `xref:xml/transformation.adoc#xml-xslt-payload-transformers[XsltPayloadTransformer]`.

View File

@@ -1,263 +1,264 @@
[[migration-3.0-4.0]]
=== Changes between 3.0 and 4.0
= Changes between 3.0 and 4.0
See the https://github.com/spring-projects/spring-integration/wiki/Spring-Integration-3.0-to-4.0-Migration-Guide[Migration Guide] for important changes that might affect your applications.
You can find migration guides for all versions back to 2.1 on the https://github.com/spring-projects/spring-integration/wiki[wiki].
[[x4.0-new-components]]
==== New Components
== New Components
Version 4.0 added a number of new components.
[[x4.0-mqtt]]
===== MQTT Channel Adapters
=== MQTT Channel Adapters
The MQTT channel adapters (previously available in the Spring Integration Extensions repository) are now available as part of the normal Spring Integration distribution.
See <<./mqtt.adoc#mqtt,MQTT Support>>.
See xref:mqtt.adoc[MQTT Support].
[[x4.0-enable-configuration]]
===== `@EnableIntegration`
=== `@EnableIntegration`
We added the `@EnableIntegration` annotation to permit declaration of standard Spring Integration beans when using `@Configuration` classes.
See <<./configuration.adoc#annotations,Annotation Support>> for more information.
See xref:configuration/annotations.adoc[Annotation Support] for more information.
[[x4.0-component-scan]]
===== `@IntegrationComponentScan`
=== `@IntegrationComponentScan`
We added the `@IntegrationComponentScan` annotation to permit classpath scanning for Spring Integration-specific components.
See <<./configuration.adoc#annotations,Annotation Support>> for more information.
See xref:configuration/annotations.adoc[Annotation Support] for more information.
[[x4.0-message-history]]
===== "`@EnableMessageHistory`"
=== "`@EnableMessageHistory`"
You can now enable message history with the `@EnableMessageHistory` annotation in a `@Configuration` class.
In addition, a JMX MBean can modify the message history settings.
Also, `MessageHistory` can track auto-created `MessageHandler` instances for annotated endpoints (such as `@ServiceActivator`, `@Splitter`, and others).
For more information, see <<./message-history.adoc#message-history,Message History>>.
For more information, see xref:message-history.adoc[Message History].
[[x4.0-messaging-gateway]]
===== `@MessagingGateway`
=== `@MessagingGateway`
You can now configure messaging gateway interfaces with the `@MessagingGateway` annotation.
It is an analogue of the `<int:gateway/>` XML element.
For more information, see <<./gateway.adoc#messaging-gateway-annotation,`@MessagingGateway` Annotation>>.
For more information, see xref:gateway.adoc#messaging-gateway-annotation[`@MessagingGateway` Annotation].
[[x4.0-boot]]
===== Spring Boot `@EnableAutoConfiguration`
=== Spring Boot `@EnableAutoConfiguration`
As well as the `@EnableIntegration` annotation mentioned earlier, we introduced a hook to allow the Spring Integration infrastructure beans to be configured with Spring Boot's `@EnableAutoConfiguration` annotation.
For more information, see https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-auto-configuration.html["`Auto-configuration`"] in the Spring Boot Reference Guide.
[[x4.0-global-channel-interceptor]]
===== `@GlobalChannelInterceptor`
=== `@GlobalChannelInterceptor`
As well as the `@EnableIntegration` annotation mentioned above, we introduced the `@GlobalChannelInterceptor` annotation.
For more information, see <<./configuration.adoc#annotations,Annotation Support>>.
For more information, see xref:configuration/annotations.adoc[Annotation Support].
[[x4.0-integration-converter]]
===== `@IntegrationConverter`
=== `@IntegrationConverter`
We introduced the `@IntegrationConverter` annotation as an analogue of the `<int:converter/>` component.
For more information, see <<./configuration.adoc#annotations,Annotation Support>>.
For more information, see xref:configuration/annotations.adoc[Annotation Support].
[[x4.0-enable-publisher]]
===== `@EnablePublisher`
=== `@EnablePublisher`
We added the `@EnablePublisher` annotation to allow the specification of a `default-publisher-channel` for `@Publisher` annotations.
See <<./configuration.adoc#annotations,Annotation Support>> for more information.
See xref:configuration/annotations.adoc[Annotation Support] for more information.
[[x4.0-redis-cms]]
===== Redis Channel Message Stores
=== Redis Channel Message Stores
We added a Redis `MessageGroupStore` that is optimized for use when backing a `QueueChannel` for persistence.
For more information, see <<./redis.adoc#redis-cms,Redis Channel Message Stores>>.
For more information, see xref:redis.adoc#redis-cms[Redis Channel Message Stores].
We added a Redis `ChannelPriorityMessageStore`.
You can use it to retrieve messages by priority.
For more information, see <<./redis.adoc#redis-cms,Redis Channel Message Stores>>.
For more information, see xref:redis.adoc#redis-cms[Redis Channel Message Stores].
[[x4.0-priority-channel-mondodb]]
===== MongodDB Channel Message Store
=== MongodDB Channel Message Store
The MongoDB support now provides the `MongoDbChannelMessageStore`, which is a channel-specific `MessageStore` implementation.
With `priorityEnabled = true`, you can use it in `<int:priority-queue>` elements to achieve priority order polling of persisted messages.
For more information see <<./mongodb.adoc#mongodb-priority-channel-message-store,MongoDB Channel Message Store>>.
For more information see xref:mongodb.adoc#mongodb-priority-channel-message-store[MongoDB Channel Message Store].
[[x4.0-MBeanExport-annotation]]
===== `@EnableIntegrationMBeanExport`
=== `@EnableIntegrationMBeanExport`
You can now enable the `IntegrationMBeanExporter` with the `@EnableIntegrationMBeanExport` annotation in a `@Configuration` class.
For more information, see <<./jmx.adoc#jmx-mbean-exporter,MBean Exporter>>.
For more information, see xref:jmx.adoc#jmx-mbean-exporter[MBean Exporter].
[[x4.0-channel-security-interceptor]]
===== `ChannelSecurityInterceptorFactoryBean`
=== `ChannelSecurityInterceptorFactoryBean`
`ChannelSecurityInterceptorFactoryBean` now supports configuration of Spring Security for message channels that use `@Configuration` classes.
For more information, see <<./security.adoc#security,Security in Spring Integration>>.
For more information, see xref:security.adoc[Security in Spring Integration].
[[x4.0-redis-outbound-gateway]]
===== Redis Command Gateway
=== Redis Command Gateway
The Redis support now provides the `<outbound-gateway>` component to perform generic Redis commands by using the `RedisConnection#execute` method.
For more information, see <<./redis.adoc#redis-outbound-gateway,Redis Outbound Command Gateway>>.
For more information, see xref:redis.adoc#redis-outbound-gateway[Redis Outbound Command Gateway].
[[x4.0-redis-lock-registry]]
===== `RedisLockRegistry`
=== `RedisLockRegistry`
The `RedisLockRegistry` is now available to support global locks visible to multiple application instances and servers.
These can be used with aggregating message handlers across multiple application instances such that group release occurs on only one instance.
For more information, see <<./redis.adoc#redis-lock-registry,Redis Lock Registry>> and <<./aggregator.adoc#aggregator,Aggregator>>.
For more information, see xref:redis.adoc#redis-lock-registry[Redis Lock Registry] and xref:overview.adoc#overview-endpoints-aggregator[Aggregator].
[[x4.0-poller-annotation]]
===== `@Poller`
=== `@Poller`
Annotation-based messaging configuration can now have a `poller` attribute.
This means that methods annotated with `@ServiceActivator`, `@Aggregator`, and similar annotations can now use an `inputChannel` that is a reference to a `PollableChannel`.
For more information, see <<./configuration.adoc#annotations,Annotation Support>>.
For more information, see xref:configuration/annotations.adoc[Annotation Support].
[[x4.0-inbound-channel-adapter-annotation]]
===== `@InboundChannelAdapter` and `SmartLifecycle` for Annotated Endpoints
=== `@InboundChannelAdapter` and `SmartLifecycle` for Annotated Endpoints
We added the `@InboundChannelAdapter` method annotation.
It is an analogue of the `<int:inbound-channel-adapter>` XML component.
In addition, all messaging annotations now provide `SmartLifecycle` options.
For more information, see <<./configuration.adoc#annotations,Annotation Support>>.
For more information, see xref:configuration/annotations.adoc[Annotation Support].
[[x4.0-twitter-sog]]
===== Twitter Search Outbound Gateway
=== Twitter Search Outbound Gateway
We added a new twitter endpoint: `<int-twitter-search-outbound-gateway/>`.
Unlike the search inbound adapter, which polls by using the same search query each time, the outbound gateway allows on-demand customized queries.
For more information, see https://github.com/spring-projects/spring-integration-extensions/tree/main/spring-integration-social-twitter[Spring Integration Social Twitter].
[[x4.0-bridge-annotations]]
===== `@BridgeFrom` and `@BridgeTo` Annotations
=== `@BridgeFrom` and `@BridgeTo` Annotations
We introduced `@BridgeFrom` and `@BridgeTo` `@Bean` method annotations to mark `MessageChannel` beans in `@Configuration` classes.
For more information, see <<./configuration.adoc#annotations,Annotation Support>>.
For more information, see xref:configuration/annotations.adoc[Annotation Support].
[[x4.0-meta-messaging-annotations]]
===== Meta-messaging Annotations
=== Meta-messaging Annotations
Messaging annotations (`@ServiceActivator`, `@Router`, `@MessagingGateway`, and others) can now be configured as meta-annotations for user-defined messaging annotations.
In addition, the user-defined annotations can have the same attributes (`inputChannel`, `@Poller`, `autoStartup`, and others).
For more information, see <<./configuration.adoc#annotations,Annotation Support>>.
For more information, see xref:configuration/annotations.adoc[Annotation Support].
[[x4.0-general]]
==== General Changes
== General Changes
This section describes general changes from version 3.0 to version 4.0.
===== Requires Spring Framework 4.0
[[requires-spring-framework-4-0]]
=== Requires Spring Framework 4.0
We moved the core messaging abstractions (`Message`, `MessageChannel`, and others) to the Spring Framework `spring-messaging` module.
Developers who reference these classes directly in their code need to make changes, as described in the first section of the https://github.com/spring-projects/spring-integration/wiki/Spring-Integration-3.0-to-4.0-Migration-Guide[3.0 to 4.0 Migration Guide].
[[x4.0-xpath-header-enricher-header-type]]
===== Header Type for XPath Header Enricher
=== Header Type for XPath Header Enricher
We introduced the `header-type` attribute for the `header` child element of the `<int-xml:xpath-header-enricher>`.
This attribute provides the target type for the header value (to which the result of the XPath expression evaluation is converted).
For more information see <<./xml.adoc#xml-xpath-header-enricher,XPath Header Enricher>>.
For more information see xref:xml/xpath-header-enricher.adoc[XPath Header Enricher].
[[x4.0-object-to-json-transformer-result-type]]
===== Object To JSON Transformer: Node Result
=== Object To JSON Transformer: Node Result
We introduced the `result-type` attribute for the `<int:object-to-json-transformer>`.
This attribute provides the target type for the result of mapping an object to JSON.
It supports `STRING` (the default) and `NODE`.
For more information see <<./transformer.adoc#transformer-xpath-spel-function,Since version 3.0, Spring Integration also provides a built-in `#xpath` SpEL function for use in expressions.>>.
For more information see xref:transformer.adoc#transformer-xpath-spel-function[Since version 3.0, Spring Integration also provides a built-in `#xpath` SpEL function for use in expressions.].
[[x4.0-jms-header-mapping]]
===== JMS Header Mapping
=== JMS Header Mapping
The `DefaultJmsHeaderMapper` now maps an incoming `JMSPriority` header to the Spring Integration `priority` header.
Previously, `priority` was only considered for outbound messages.
For more information, see <<./jms.adoc#jms-header-mapping,Mapping Message Headers to and from JMS Message>>.
For more information, see xref:changes-3.0-4.0.adoc#x4.0-jms-header-mapping[Mapping Message Headers to and from JMS Message].
[[x4.0-jms-ob]]
===== JMS Outbound Channel Adapter
=== JMS Outbound Channel Adapter
The JMS outbound channel adapter now supports the `session-transacted` attribute (default: `false`).
Previously, you had to inject a customized `JmsTemplate` to use transactions.
See <<./jms.adoc#jms-outbound-channel-adapter,Outbound Channel Adapter>>.
See xref:changes-3.0-4.0.adoc#x4.0-jms-ob[Outbound Channel Adapter].
[[x4.0-jms-ib]]
===== JMS Inbound Channel Adapter
=== JMS Inbound Channel Adapter
The JMS inbound channel adapter now supports the `session-transacted` attribute (default: `false`).
Previously, you had to inject a customized `JmsTemplate` to use transactions.
The adapter allowed 'transacted' in the `acknowledgeMode`, which was incorrect and didn't work.
This value is no longer allowed.
See <<./jms.adoc#jms-inbound-channel-adapter,Inbound Channel Adapter>>.
See xref:changes-3.0-4.0.adoc#x4.0-jms-ib[Inbound Channel Adapter].
[[x4.0-datatype-channel]]
===== Datatype Channels
=== Datatype Channels
You can now specify a `MessageConverter` to be used when converting (if necessary) payloads to one of the accepted `datatype` instances in a Datatype channel.
For more information, see <<./channel.adoc#channel-datatype-channel,Datatype Channel Configuration>>.
For more information, see xref:channel/configuration.adoc#channel-datatype-channel[Datatype Channel Configuration].
[[x4.0-retry-config]]
===== Simpler Retry Advice Configuration
=== Simpler Retry Advice Configuration
We added simplified namespace support to configure a `RequestHandlerRetryAdvice`.
For more information, see <<./handler-advice.adoc#retry-config,Configuring the Retry Advice>>.
For more information, see xref:handler-advice/classes.adoc#retry-config[Configuring the Retry Advice].
[[x4.0-release-strategy-group-timeout]]
===== Correlation Endpoint: Time-based Release Strategy
=== Correlation Endpoint: Time-based Release Strategy
We added the mutually exclusive `group-timeout` and `group-timeout-expression` attributes to `<int:aggregator>` and `<int:resequencer>`.
These attributes allow forced completion of a partial `MessageGroup`, provided the `ReleaseStrategy` does not release a group and no further messages arrive within the time specified.
For more information, see <<./aggregator.adoc#aggregator-xml,Configuring an Aggregator with XML>>.
For more information, see xref:aggregator.adoc#aggregator-xml[Configuring an Aggregator with XML].
[[x4.0-redis-metadata]]
===== Redis Metadata Store
=== Redis Metadata Store
The `RedisMetadataStore` now implements `ConcurrentMetadataStore`, letting it be used, for example, in an `AbstractPersistentAcceptOnceFileListFilter` implementation in a multiple application instance or server environment.
For more information, see <<./redis.adoc#redis-metadata-store,Redis Metadata Store>>, <<./file.adoc#file-reading,Reading Files>>, <<./ftp.adoc#ftp-inbound,FTP Inbound Channel Adapter>>, and <<./sftp.adoc#sftp-inbound,SFTP Inbound Channel Adapter>>.
For more information, see xref:redis.adoc#redis-metadata-store[Redis Metadata Store], xref:file/reading.adoc[Reading Files], xref:ftp/inbound.adoc[FTP Inbound Channel Adapter], and xref:sftp/inbound.adoc[SFTP Inbound Channel Adapter].
[[x4.0-jdbc-cs]]
===== `JdbcChannelMessageStore` and `PriorityChannel`
=== `JdbcChannelMessageStore` and `PriorityChannel`
T`JdbcChannelMessageStore` now implements `PriorityCapableChannelMessageStore`, letting it be used as a `message-store` reference for `priority-queue` instances.
For more information, see <<./jdbc.adoc#jdbc-message-store-channels,Backing Message Channels>>.
For more information, see xref:jdbc/message-store.adoc#jdbc-message-store-channels[Backing Message Channels].
[[x4.0-amqp]]
===== AMQP Endpoints Delivery Mode
=== AMQP Endpoints Delivery Mode
Spring AMQP, by default, creates persistent messages on the broker.
You can override this behavior by setting the `amqp_deliveryMode` header or customizing the mappers.
We added a convenient `default-delivery-mode` attribute to the adapters to provide easier configuration of this important setting.
For more information, see <<./amqp.adoc#amqp-outbound-channel-adapter,Outbound Channel Adapter>> and <<./amqp.adoc#amqp-outbound-gateway,Outbound Gateway>>.
For more information, see xref:amqp/outbound-channel-adapter.adoc[Outbound Channel Adapter] and xref:amqp/outbound-gateway.adoc[Outbound Gateway].
[[x4.0-ftp]]
===== FTP Timeouts
=== FTP Timeouts
The `DefaultFtpSessionFactory` now exposes the `connectTimeout`, `defaultTimeout`, and `dataTimeout` properties, avoiding the need to subclass the factory to set these common properties.
The `postProcess*` methods are still available for more advanced configuration.
See <<./ftp.adoc#ftp-session-factory,FTP Session Factory>> for more information.
See xref:ftp/session-factory.adoc[FTP Session Factory] for more information.
[[x4.0-twitter-status-updating]]
===== Twitter: `StatusUpdatingMessageHandler`
=== Twitter: `StatusUpdatingMessageHandler`
The `StatusUpdatingMessageHandler` (`<int-twitter:outbound-channel-adapter>`) now supports the `tweet-data-expression` attribute to build a `org.springframework.social.twitter.api.TweetData` object for updating the timeline status.
This feature allows, for example, attaching an image.
See https://github.com/spring-projects/spring-integration-extensions/tree/main/spring-integration-social-twitter[Spring Integration Social Twitter] for more information.
[[x4.0-jpa-id-expression]]
===== JPA Retrieving Gateway: `id-expression`
=== JPA Retrieving Gateway: `id-expression`
We introduced the `id-expression` attribute for `<int-jpa:retrieving-outbound-gateway>` to perform `EntityManager.find(Class entityClass, Object primaryKey)`.
See <<./jpa.adoc#jpa-retrieving-outbound-gateway,Retrieving Outbound Gateway>> for more information.
See xref:jpa/outbound-gateways.adoc#jpa-retrieving-outbound-gateway[Retrieving Outbound Gateway] for more information.
[[x4.0-tcp-deserializer-events]]
===== TCP Deserialization Events
=== TCP Deserialization Events
When one of the standard deserializers encounters a problem decoding the input stream to a message, it now emits a `TcpDeserializationExceptionEvent`, letting applications examine the data at the point at which the exception occurred.
See <<./ip.adoc#tcp-events,TCP Connection Events>> for more information.
See xref:changes-4.1-4.2.adoc#x4.2-tcp-events[TCP Connection Events] for more information.
[[x4.0-bean-messaging-annotations]]
===== Messaging Annotations on `@Bean` Definitions
=== Messaging Annotations on `@Bean` Definitions
You can now configure messaging annotations (`@ServiceActivator`, `@Router`, `@InboundChannelAdapter`, and others) on `@Bean` definitions in `@Configuration` classes.
For more information, see <<./configuration.adoc#annotations,Annotation Support>>.
For more information, see xref:configuration/annotations.adoc[Annotation Support].

View File

@@ -1,229 +1,230 @@
[[migration-4.0-4.1]]
=== Changes between 4.0 and 4.1
= Changes between 4.0 and 4.1
See the https://github.com/spring-projects/spring-integration/wiki/Spring-Integration-4.0-to-4.1-Migration-Guide[Migration Guide] for important changes that might affect your applications.
You can find migration guides for all versions back to 2.1 on the https://github.com/spring-projects/spring-integration/wiki[wiki].
==== New Components
[[new-components]]
== New Components
Version 4.1 added a number of new components.
[[x4.1-promise-gateway]]
===== Promise<?> Gateway
=== Promise<?> Gateway
The messaging gateway methods now support a Reactor `Promise` return type.
See <<./gateway.adoc#async-gateway,Asynchronous Gateway>>.
See xref:jms.adoc#jms-async-gateway[Asynchronous Gateway].
[[x4.1-web-socket-adapters]]
===== WebSocket support
=== WebSocket support
The `WebSocket` module is now available.
It is fully based on the Spring WebSocket and Spring Messaging modules and provides an `<inbound-channel-adapter>` and an `<outbound-channel-adapter>`.
See <<./web-sockets.adoc#web-sockets,WebSockets Support>> for more information.
See xref:web-sockets.adoc[WebSockets Support] for more information.
[[x4.1-scatter-gather]]
===== Scatter-Gather Enterprise Integration Pattern
=== Scatter-Gather Enterprise Integration Pattern
We implemented the scatter-gather enterprise integration pattern.
See <<./scatter-gather.adoc#scatter-gather,Scatter-Gather>> for more information.
See xref:scatter-gather.adoc[Scatter-Gather] for more information.
[[x4.1-Routing-Slip]]
===== Routing Slip Pattern
=== Routing Slip Pattern
We added the routing slip EIP pattern implementation.
See <<./router.adoc#routing-slip,Routing Slip>> for more information.
See xref:router/routing-slip.adoc[Routing Slip] for more information.
[[x4.1-idempotent-receiver]]
===== Idempotent Receiver Pattern
=== Idempotent Receiver Pattern
We added the idempotent receiver enterprise integration pattern implementation by adding the `<idempotent-receiver>` component in XML or the `IdempotentReceiverInterceptor` and `IdempotentReceiver` annotations for Java configuration.
See <<./handler-advice.adoc#idempotent-receiver,Idempotent Receiver Enterprise Integration Pattern>> and the https://docs.spring.io/spring-integration/api/index.html[Javadoc] for more information.
See xref:handler-advice/idempotent-receiver.adoc[Idempotent Receiver Enterprise Integration Pattern] and the https://docs.spring.io/spring-integration/api/index.html[Javadoc] for more information.
[[x4.1-BoonJsonObjectMapper]]
===== Boon `JsonObjectMapper`
=== Boon `JsonObjectMapper`
We added the Boon `JsonObjectMapper` for the JSON transformers.
See <<./transformer.adoc#transformer,Transformer>> for more information.
See xref:transformer.adoc[Transformer] for more information.
[[x4.1-redis-queue-gateways]]
===== Redis Queue Gateways
=== Redis Queue Gateways
We added the `<redis-queue-inbound-gateway>` and `<redis-queue-outbound-gateway>` components.
See <<./redis.adoc#redis-queue-inbound-gateway,Redis Queue Inbound Gateway>> and <<./redis.adoc#redis-queue-outbound-gateway,Redis Queue Outbound Gateway>>.
See xref:redis.adoc#redis-queue-inbound-gateway[Redis Queue Inbound Gateway] and xref:redis.adoc#redis-queue-outbound-gateway[Redis Queue Outbound Gateway].
[[x4.1-PollSkipAdvice]]
===== `PollSkipAdvice`
=== `PollSkipAdvice`
We added the `PollSkipAdvice`, which you can use within the `<advice-chain>` of the `<poller>` to determine if the current poll should be suppressed (skipped) by some condition that you implement with `PollSkipStrategy`.
See <<./polling-consumer.adoc#polling-consumer,Poller>> for more information.
See xref:polling-consumer.adoc#polling-consumer[Poller] for more information.
[[x4.1-general]]
==== General Changes
== General Changes
This section describes general changes from version 4.0 to version 4.1.
[[x4.1-amqp-inbound-missing-queues]]
===== AMQP Inbound Endpoints, Channel
=== AMQP Inbound Endpoints, Channel
Elements that use a message listener container (inbound endpoints and channel) now support the `missing-queues-fatal` attribute.
See <<./amqp.adoc#amqp,AMQP Support>> for more information.
See xref:amqp.adoc[AMQP Support] for more information.
[[x4.1-amqp-outbound-lazy-connect]]
===== AMQP Outbound Endpoints
=== AMQP Outbound Endpoints
The AMQP outbound endpoints support a new property called `lazy-connect` (default: `true`).
When `true`, the connection to the broker is not established until the first message arrives (assuming there are no inbound endpoints, which always try to establish the connection during startup).
When set to `false`, an attempt to establish the connection is made during application startup.
See <<./amqp.adoc#amqp,AMQP Support>> for more information.
See xref:amqp.adoc[AMQP Support] for more information.
[[x4.1-sms-copy-on-get]]
===== SimpleMessageStore
=== SimpleMessageStore
The `SimpleMessageStore` no longer makes a copy of the group when calling `getMessageGroup()`.
See <<./message-store.adoc#sms-caution,[WARNING]>> for more information.
See xref:message-store.adoc#sms-caution[[WARNING]] for more information.
[[x4.1-ws-encode-uri]]
===== Web Service Outbound Gateway: `encode-uri`
=== Web Service Outbound Gateway: `encode-uri`
The `<ws:outbound-gateway/>` now provides an `encode-uri` attribute to allow disabling the encoding of the URI object before sending the request.
[[x4.1-http-status-code]]
===== Http Inbound Channel Adapter and Status Code
=== Http Inbound Channel Adapter and Status Code
The `<http:inbound-channel-adapter>` can now be configured with a `status-code-expression` to override the default `200 OK` status.
See <<./http.adoc#http-namespace,HTTP Namespace Support>> for more information.
See xref:http/namespace.adoc[HTTP Namespace Support] for more information.
[[x4.1-mqtt]]
===== MQTT Adapter Changes
=== MQTT Adapter Changes
You can now configure the MQTT channel adapters to connect to multiple servers -- for example, to support High Availability (HA).
See <<./mqtt.adoc#mqtt,MQTT Support>> for more information.
See xref:mqtt.adoc[MQTT Support] for more information.
The MQTT message-driven channel adapter now supports specifying the QoS setting for each subscription.
See <<./mqtt.adoc#mqtt-inbound,Inbound (Message-driven) Channel Adapter>> for more information.
See xref:mqtt.adoc#mqtt-inbound[Inbound (Message-driven) Channel Adapter] for more information.
The MQTT outbound channel adapter now supports asynchronous sends, avoiding blocking until delivery is confirmed.
See <<./mqtt.adoc#mqtt-outbound,Outbound Channel Adapter>> for more information.
See xref:mqtt.adoc#mqtt-outbound[Outbound Channel Adapter] for more information.
It is now possible to programmatically subscribe to and unsubscribe from topics at runtime.
See <<./mqtt.adoc#mqtt-inbound,Inbound (Message-driven) Channel Adapter>> for more information.
See xref:mqtt.adoc#mqtt-inbound[Inbound (Message-driven) Channel Adapter] for more information.
[[x4.1-sftp]]
===== FTP and SFTP Adapter Changes
=== FTP and SFTP Adapter Changes
The FTP and SFTP outbound channel adapters now support appending to remote files and taking specific actions when a remote file already exists.
The remote file templates now also supports this, as well as `rmdir()` and `exists()`.
In addition, the remote file templates provide access to the underlying client object, enabling access to low-level APIs.
See <<./ftp.adoc#ftp,FTP/FTPS Adapters>> and <<./sftp.adoc#sftp,SFTP Adapters>> for more information.
See xref:ftp.adoc[FTP/FTPS Adapters] and xref:sftp.adoc[SFTP Adapters] for more information.
[[x4.1-splitter-iterator]]
===== Splitter and Iterator
=== Splitter and Iterator
`Splitter` components now support an `Iterator` as the result object for producing output messages.
See <<./splitter.adoc#splitter,Splitter>> for more information.
See xref:splitter.adoc[Splitter] for more information.
[[x4.1-aggregator]]
===== Aggregator
=== Aggregator
`Aggregator` instancess now support a new attribute `expire-groups-upon-timeout`.
See <<./aggregator.adoc#aggregator,Aggregator>> for more information.
See xref:overview.adoc#overview-endpoints-aggregator[Aggregator] for more information.
[[x4.1-content-enricher-improvement]]
===== Content Enricher Improvements
=== Content Enricher Improvements
We added a `null-result-expression` attribute, which is evaluated and returned if `<enricher>` returns `null`.
You can add it in `<header>` and `<property>`.
See <<./content-enrichment.adoc#content-enricher,Content Enricher>> for more information.
See xref:content-enrichment.adoc[Content Enricher] for more information.
We added an `error-channel` attribute, which is used to handle an error flow if an `Exception` occurs downstream of the `request-channel`.
This lets you return an alternative object to use for enrichment.
See <<./content-enrichment.adoc#content-enricher,Content Enricher>> for more information.
See xref:content-enrichment.adoc[Content Enricher] for more information.
[[x4.1-header-channel-registry]]
===== Header Channel Registry
=== Header Channel Registry
The `<header-enricher/>` element's `<header-channels-to-string/>` child element can now override the header channel registry's default time for retaining channel mappings.
See <<./content-enrichment.adoc#header-channel-registry,Header Channel Registry>> for more information.
See xref:content-enrichment.adoc#header-channel-registry[Header Channel Registry] for more information.
[[x4.1-orderly-shutdown]]
===== Orderly Shutdown
=== Orderly Shutdown
We made improvements to the orderly shutdown algorithm.
See <<./shutdown.adoc#jmx-shutdown,Orderly Shutdown>> for more information.
See xref:shutdown.adoc[Orderly Shutdown] for more information.
[[x4.1-recipientListRouter]]
===== Management for `RecipientListRouter`
=== Management for `RecipientListRouter`
The `RecipientListRouter` now provides several management operations to configure recipients at runtime.
With that, you can now configure the `<recipient-list-router>` without any `<recipient>` from the start.
See <<./router.adoc#recipient-list-router-management,`RecipientListRouterManagement`>> for more information.
See xref:router/implementations.adoc#recipient-list-router-management[`RecipientListRouterManagement`] for more information.
[[x4.1-AbstractHeaderMapper-changes]]
===== AbstractHeaderMapper: NON_STANDARD_HEADERS token
=== AbstractHeaderMapper: NON_STANDARD_HEADERS token
The `AbstractHeaderMapper` implementation now provides the additional `NON_STANDARD_HEADERS` token to map any user-defined headers, which are not mapped by default.
See <<./amqp.adoc#amqp-message-headers,AMQP Message Headers>> for more information.
See xref:amqp/message-headers.adoc[AMQP Message Headers] for more information.
[[x4.1-amqp-channels]]
===== AMQP Channels: `template-channel-transacted`
=== AMQP Channels: `template-channel-transacted`
We introduced the `template-channel-transacted` attribute for AMQP `MessageChannel` instances.
See <<./amqp.adoc#amqp-channels,AMQP-backed Message Channels>> for more information.
See xref:amqp/channels.adoc[AMQP-backed Message Channels] for more information.
[[x4.1-syslog]]
===== Syslog Adapter
=== Syslog Adapter
The default syslog message converter now has an option to retain the original message in the payload while still setting the headers.
See <<./syslog.adoc#syslog-inbound-adapter,Syslog Inbound Channel Adapter>> for more information.
See xref:syslog.adoc#syslog-inbound-adapter[Syslog Inbound Channel Adapter] for more information.
[[x4.1-async-gateway]]
===== Asynchronous Gateway
=== Asynchronous Gateway
In addition to the `Promise` return type <<x4.1-promise-gateway,mentioned earlier>>, gateway methods may now return a `ListenableFuture`, introduced in Spring Framework 4.0.
In addition to the `Promise` return type xref:changes-4.0-4.1.adoc#x4.1-promise-gateway[mentioned earlier], gateway methods may now return a `ListenableFuture`, introduced in Spring Framework 4.0.
You can also disable asynchronous processing in the gateway, letting a downstream flow directly return a `Future`.
See <<./gateway.adoc#async-gateway,Asynchronous Gateway>>.
See xref:jms.adoc#jms-async-gateway[Asynchronous Gateway].
[[x4.1-aggregator-advice-chain]]
===== Aggregator Advice Chain
=== Aggregator Advice Chain
`Aggregator` and `Resequencer` now support `<expire-advice-chain/>` and `<expire-transactional/>` child elements to advise the `forceComplete` operation.
See <<./aggregator.adoc#aggregator-xml,Configuring an Aggregator with XML>> for more information.
See xref:aggregator.adoc#aggregator-xml[Configuring an Aggregator with XML] for more information.
[[x4.1-script-outbound-channel-adapter]]
===== Outbound Channel Adapter and Scripts
=== Outbound Channel Adapter and Scripts
The `<int:outbound-channel-adapter/>` now supports the `<script/>` child element.
The underlying script must have a `void` return type or return `null`.
See <<./groovy.adoc#groovy,Groovy support>> and <<./scripting.adoc#scripting,Scripting Support>>.
See xref:groovy.adoc[Groovy support] and xref:scripting.adoc[Scripting Support].
[[x4.1-reseq]]
===== Resequencer Changes
=== Resequencer Changes
When a message group in a resequencer times out (using `group-timeout` or a `MessageGroupStoreReaper`), late arriving messages are now, by default, discarded immediately.
See <<./resequencer.adoc#resequencer,Resequencer>>.
See xref:resequencer.adoc[Resequencer].
[[x4.1-Optional-Parameter]]
===== Optional POJO method parameter
=== Optional POJO method parameter
Spring Integration now consistently handles the Java 8's `Optional` type.
See <<./service-activator.adoc#service-activator-namespace,Configuring Service Activator>>.
See xref:service-activator.adoc#service-activator-namespace[Configuring Service Activator].
[[x4.1-queue-channel-queue.typ]]
===== `QueueChannel` backed Queue type
=== `QueueChannel` backed Queue type
The `QueueChannel` backed `Queue type` has been changed from `BlockingQueue` to the more generic `Queue`.
This change allows the use of any external `Queue` implementation (for example, Reactor's `PersistentQueue`).
See <<./channel.adoc#channel-configuration-queuechannel,`QueueChannel` Configuration>>.
See xref:channel/configuration.adoc#channel-configuration-queuechannel[`QueueChannel` Configuration].
[[x4.1-channel-interceptor]]
===== `ChannelInterceptor` Changes
=== `ChannelInterceptor` Changes
The `ChannelInterceptor` now supports additional `afterSendCompletion()` and `afterReceiveCompletion()` methods.
See <<./channel.adoc#channel-interceptors,Channel Interceptors>>.
See xref:channel/interceptors.adoc[Channel Interceptors].
[[x4.1-mail-peek]]
===== IMAP PEEK
=== IMAP PEEK
Since version 4.1.1 there is a change of behavior if you explicitly set the `mail.[protocol].peek` JavaMail property to `false` (where `[protocol]` is `imap` or `imaps`).
See <<./mail.adoc#imap-peek,[IMPORTANT]>>.
See xref:changes-4.0-4.1.adoc#x4.1-mail-peek[[IMPORTANT]].

View File

@@ -1,52 +1,52 @@
[[migration-4.1-4.2]]
=== Changes between 4.1 and 4.2
= Changes between 4.1 and 4.2
See the https://github.com/spring-projects/spring-integration/wiki/Spring-Integration-4.1-to-4.2-Migration-Guide[Migration Guide] for important changes that might affect your applications.
You can find migration guides for all versions back to 2.1 on the https://github.com/spring-projects/spring-integration/wiki[wiki].
[[x4.2-new-components]]
==== New Components
== New Components
Version 4.2 added a number of new components.
[[x4.2-JMX]]
===== Major Management/JMX Rework
=== Major Management/JMX Rework
We added a new `MetricsFactory` strategy interface.
This change, together with other changes in the JMX and management infrastructure, provides much more control over management configuration and runtime performance.
However, this has some important implications for (some) user environments.
For complete details, see <<./metrics.adoc#metrics-management,Metrics and Management>> and <<./jmx.adoc#jmx-42-improvements,JMX Improvements>>.
For complete details, see xref:metrics.adoc[Metrics and Management] and xref:jmx.adoc#jmx-42-improvements[JMX Improvements].
[[x4.2-mongodb-metadata-store]]
===== MongoDB Metadata Store
=== MongoDB Metadata Store
The `MongoDbMetadataStore` is now available.
For more information, see <<./mongodb.adoc#mongodb-metadata-store,MongoDB Metadata Store>>.
For more information, see xref:mongodb.adoc#mongodb-metadata-store[MongoDB Metadata Store].
[[x4.2-secured-channel-annotation]]
===== SecuredChannel Annotation
=== SecuredChannel Annotation
We introduced the `@SecuredChannel` annotation, replacing the deprecated `ChannelSecurityInterceptorFactoryBean`.
For more information, see <<./security.adoc#security,Security in Spring Integration>>.
For more information, see xref:security.adoc[Security in Spring Integration].
[[x4.2-security-context-propagation]]
===== `SecurityContext` Propagation
=== `SecurityContext` Propagation
We introduced the `SecurityContextPropagationChannelInterceptor` for the `SecurityContext` propagation from one message flow's thread to another.
For more information, see <<./security.adoc#security,Security in Spring Integration>>.
For more information, see xref:security.adoc[Security in Spring Integration].
[[x4.2-file-splitter]]
===== FileSplitter
=== FileSplitter
In 4.1.2, we added `FileSplitter`, which splits text files into lines.
It now has full support in the `int-file:` namespace.
See <<./file.adoc#file-splitter,File Splitter>> for more information.
See xref:file/splitter.adoc[File Splitter] for more information.
[[x4.2-zk]]
===== Zookeeper Support
=== Zookeeper Support
We added Zookeeper support to the framework to assist when running on a clustered or multi-host environment.
The change impacts the following features:
@@ -55,144 +55,152 @@ The change impacts the following features:
* `ZookeeperLockRegistry`
* Zookeeper Leadership
See <<./zookeeper.adoc#zookeeper,Zookeeper Support>> for more information.
See xref:zookeeper.adoc[Zookeeper Support] for more information.
[[x4.2-barrier]]
===== Thread Barrier
=== Thread Barrier
A new thread `<int:barrier/>` component is available, letting a thread be suspended until some asynchronous event occurs.
See <<./barrier.adoc#barrier,Thread Barrier>> for more information.
See xref:barrier.adoc[Thread Barrier] for more information.
[[x4.2-stomp]]
===== STOMP Support
=== STOMP Support
We added STOMP support to the framework as an inbound and outbound channel adapters pair.
See <<./stomp.adoc#stomp,STOMP Support>> for more information.
See xref:stomp.adoc[STOMP Support] for more information.
[[x4.2-codec]]
===== Codec
=== Codec
A new `Codec` abstraction has been introduced, to encode and decode objects to and from `byte[]`.
We added an implementation that uses Kryo.
We also added codec-based transformers and message converters.
See <<./codec.adoc#codec,Codec>> for more information.
See xref:codec.adoc[Codec] for more information.
[[x4.2-prepared-statement-setter]]
===== Message PreparedStatement Setter
=== Message PreparedStatement Setter
A new `MessagePreparedStatementSetter` functional interface callback is available for the `JdbcMessageHandler` (`<int-jdbc:outbound-gateway>` and `<int-jdbc:outbound-channel-adapter>`) as an alternative to using `SqlParameterSourceFactory` to populate parameters on the `PreparedStatement` with the `requestMessage` context.
See <<./jdbc.adoc#jdbc-outbound-channel-adapter,Outbound Channel Adapter>> for more information.
See xref:jdbc/outbound-channel-adapter.adoc[Outbound Channel Adapter] for more information.
[[x4.2-general]]
==== General Changes
== General Changes
This section describes general changes from version 4.1 to version 4.2.
[[x4.2-wire-tap]]
===== WireTap
=== WireTap
As an alternative to the existing `selector` attribute, the `<wire-tap/>` element now supports the `selector-expression` attribute.
[[x4.2-file-changes]]
===== File Changes
=== File Changes
See <<./file.adoc#files,File Support>> for more information about these changes.
See xref:file.adoc[File Support] for more information about these changes.
====== Appending New Lines
[[appending-new-lines]]
==== Appending New Lines
The `<int-file:outbound-channel-adapter>` and `<int-file:outbound-gateway>` now support an `append-new-line` attribute.
If set to `true`, a new line is appended to the file after a message is written.
The default attribute value is `false`.
====== Ignoring Hidden Files
[[ignoring-hidden-files]]
==== Ignoring Hidden Files
We added the `ignore-hidden` attribute for the `<int-file:inbound-channel-adapter>` to let you set whether to pick up hidden files from the source directory.
It defaults to `true`.
====== Writing `InputStream` Payloads
[[writing-inputstream-payloads]]
==== Writing `InputStream` Payloads
The `FileWritingMessageHandler` now also accepts `InputStream` as a valid message payload type.
====== `HeadDirectoryScanner`
[[headdirectoryscanner]]
==== `HeadDirectoryScanner`
You can now use the `HeadDirectoryScanner` with other `FileListFilter` implementations.
====== Last Modified Filter
[[last-modified-filter]]
==== Last Modified Filter
We added the `LastModifiedFileListFilter`.
====== Watch Service Directory Scanner
[[watch-service-directory-scanner]]
==== Watch Service Directory Scanner
We added the `WatchServiceDirectoryScanner`.
====== Persistent File List Filter Changes
[[persistent-file-list-filter-changes]]
==== Persistent File List Filter Changes
The `AbstractPersistentFileListFilter` has a new property (`flushOnUpdate`) which, when set to `true`, calls `flush()` on the metadata store if it implements `Flushable` (for example, `PropertiesPersistingMetadataStore`).
[[x4.2-class-package-change]]
===== Class Package Change
=== Class Package Change
We moved the `ScatterGatherHandler` class from the `org.springframework.integration.handler` to the `org.springframework.integration.scattergather`.
===== TCP Changes
[[tcp-changes]]
=== TCP Changes
This section describes general changes to the Spring Integration TCP functionality.
[[x4.2-tcp-serializers]]
====== TCP Serializers
==== TCP Serializers
The TCP `Serializers` no longer `flush()` the `OutputStream`.
This is now done by the `TcpNxxConnection` classes.
If you use the serializers directly within your code, you may have to `flush()` the `OutputStream`.
[[x4.2-tcp-server-exceptions]]
====== Server Socket Exceptions
==== Server Socket Exceptions
`TcpConnectionServerExceptionEvent` instances are now published whenever an unexpected exception occurs on a TCP server socket (also added to 4.1.3 and 4.0.7).
See <<./ip.adoc#tcp-events,TCP Connection Events>> for more information.
See xref:changes-4.1-4.2.adoc#x4.2-tcp-events[TCP Connection Events] for more information.
[[x4.2-tcp-server-port]]
====== TCP Server Port
==== TCP Server Port
If you configure a TCP server socket factory to listen on a random port, you can now obtain the actual port chosen by the OS by using `getPort()`.
`getServerSocketAddress()` is also available.
See "<<./ip.adoc#tcp-connection-factories,TCP Connection Factories>>" for more information.
See "xref:ip/tcp-connection-factories.adoc[TCP Connection Factories]" for more information.
[[x4.2-tcp-gw-rto]]
====== TCP Gateway Remote Timeout
==== TCP Gateway Remote Timeout
The `TcpOutboundGateway` now supports `remote-timeout-expression` as an alternative to the existing `remote-timeout` attribute.
This allows setting the timeout based on each message.
Also, the `remote-timeout` no longer defaults to the same value as `reply-timeout`, which has a completely different meaning.
See <<./ip.adoc#tcp-ob-gateway-attributes,.TCP Outbound Gateway Attributes>> for more information.
See xref:ip/endpoint-reference.adoc#tcp-ob-gateway-attributes[.TCP Outbound Gateway Attributes] for more information.
[[x4.2-tcp-ssl]]
====== TCP SSLSession Available for Header Mapping
==== TCP SSLSession Available for Header Mapping
`TcpConnection` implementations now support `getSslSession()` to let you extract information from the session to add to message headers.
See <<./ip.adoc#ip-msg-headers,IP Message Headers>> for more information.
See xref:ip/msg-headers.adoc[IP Message Headers] for more information.
[[x4.2-tcp-events]]
====== TCP Events
==== TCP Events
New events are now published whenever a correlation exception occurs -- such as sending a message to a non-existent socket.
The `TcpConnectionEventListeningMessageProducer` is deprecated.
Use the generic event adapter instead.
See <<./ip.adoc#tcp-events,TCP Connection Events>> for more information.
See xref:changes-4.1-4.2.adoc#x4.2-tcp-events[TCP Connection Events] for more information.
[[x4.2-inbound-channel-adapter-annotation]]
===== `@InboundChannelAdapter` Changes
=== `@InboundChannelAdapter` Changes
Previously, the `@Poller` on an inbound channel adapter defaulted the `maxMessagesPerPoll` attribute to `-1` (infinity).
This was inconsistent with the XML configuration of `<inbound-channel-adapter/>`, which defaults to `1`.
The annotation now defaults this attribute to `1`.
[[x4.2-api-changes]]
===== API Changes
=== API Changes
`o.s.integration.util.FunctionIterator` now requires a `o.s.integration.util.Function` instead of a `reactor.function.Function`.
This was done to remove an unnecessary hard dependency on Reactor.
@@ -202,177 +210,199 @@ Reactor is still supported for functionality such as the `Promise` gateway.
The dependency was removed for those users who do not need it.
[[x4.2-jms-changes]]
===== JMS Changes
=== JMS Changes
This section describes general changes to the Spring Integration TCP functionality.
====== Reply Listener Lazy Initialization
[[reply-listener-lazy-initialization]]
==== Reply Listener Lazy Initialization
You can now configure the reply listener in JMS outbound gateways to be initialized on-demand and stopped after an idle period, instead of being controlled by the gateway's lifecycle.
See <<./jms.adoc#jms-outbound-gateway,Outbound Gateway>> for more information.
See xref:jms.adoc#jms-outbound-gateway[Outbound Gateway] for more information.
====== Conversion Errors in Message-Driven Endpoints
[[conversion-errors-in-message-driven-endpoints]]
==== Conversion Errors in Message-Driven Endpoints
The `error-channel` is now used for the conversion errors.
In previous versions, they caused transaction rollback and message redelivery.
See <<./jms.adoc#jms-message-driven-channel-adapter,Message-driven Channel Adapter>> and <<./jms.adoc#jms-inbound-gateway,Inbound Gateway>> for more information.
See xref:changes-2.2-3.0.adoc#x3.0-jms-mdca-te[Message-driven Channel Adapter] and xref:jms.adoc#jms-inbound-gateway[Inbound Gateway] for more information.
====== Default Acknowledge Mode
[[default-acknowledge-mode]]
==== Default Acknowledge Mode
When using an implicitly defined `DefaultMessageListenerContainer`, the default `acknowledge` is now `transacted`.
We recommend using `transacted` when using this container, to avoid message loss.
This default now applies to the message-driven inbound adapter and the inbound gateway.
It was already the default for JMS-backed channels.
See <<./jms.adoc#jms-message-driven-channel-adapter,Message-driven Channel Adapter>> and <<./jms.adoc#jms-inbound-gateway,Inbound Gateway>> for more information.
See xref:changes-2.2-3.0.adoc#x3.0-jms-mdca-te[Message-driven Channel Adapter] and xref:jms.adoc#jms-inbound-gateway[Inbound Gateway] for more information.
====== Shared Subscriptions
[[shared-subscriptions]]
==== Shared Subscriptions
We added Namespace support for shared subscriptions (JMS 2.0) to message-driven endpoints and the `<int-jms:publish-subscribe-channel>`.
Previously, you had to wire up listener containers as `<bean/>` declarations to use shared connections.
See <<./jms.adoc#jms,JMS Support>> for more information.
See xref:jms.adoc[JMS Support] for more information.
[[x4.2-conditional-pollers]]
===== Conditional Pollers
=== Conditional Pollers
We now provide much more flexibility for dynamic polling.
See <<./polling-consumer.adoc#conditional-pollers,Conditional Pollers for Message Sources>> for more information.
See xref:changes-4.1-4.2.adoc#x4.2-conditional-pollers[Conditional Pollers for Message Sources] for more information.
[[x4.2-amqp-changes]]
===== AMQP Changes
=== AMQP Changes
This section describes general changes to the Spring Integration AMQP functionality.
====== Publisher Confirmations
[[publisher-confirmations]]
==== Publisher Confirmations
The `<int-amqp:outbound-gateway>` now supports `confirm-correlation-expression`, `confirm-ack-channel`, and `confirm-nack-channel` attributes (which have a purpose similar to that of `<int-amqp:outbound-channel-adapter>`).
====== Correlation Data
[[correlation-data]]
==== Correlation Data
For both the outbound channel adapter and the inbound gateway, if the correlation data is a `Message<?>`, it becomes the basis of the message on the ack or nack channel, with the additional header(s) added.
Previously, any correlation data (including `Message<?>`) was returned as the payload of the ack or nack message.
====== Inbound Gateway Properties
[[inbound-gateway-properties]]
==== Inbound Gateway Properties
The `<int-amqp:inbound-gateway>` now exposes the `amqp-template` attribute to allow more control over an external bean for the reply `RabbitTemplate`.
You can also provide your own `AmqpTemplate` implementation.
In addition, you can use `default-reply-to` if the request message does not have a `replyTo` property.
See <<./amqp.adoc#amqp,AMQP Support>> for more information.
See xref:amqp.adoc[AMQP Support] for more information.
[[x4.2-xpath-splitter]]
===== XPath Splitter Improvements
=== XPath Splitter Improvements
The `XPathMessageSplitter` (`<int-xml:xpath-splitter>`) now allows the configuration of `output-properties` for the internal `javax.xml.transform.Transformer` and supports an `Iterator` mode (defaults to `true`) for the XPath evaluation `org.w3c.dom.NodeList` result.
See <<./xml.adoc#xml-xpath-splitting,Splitting XML Messages>> for more information.
See xref:xml/xpath-splitting.adoc[Splitting XML Messages] for more information.
[[x4.2-http-changes]]
===== HTTP Changes
=== HTTP Changes
This section describes general changes to the Spring Integration HTTP functionality.
====== CORS
[[cors]]
==== CORS
The HTTP inbound endpoints (`<int-http:inbound-channel-adapter>` and `<int-http:inbound-gateway>`) now allow the
configuration of Cross-origin Resource Sharing (CORS).
See <<./http.adoc#http-cors,Cross-origin Resource Sharing (CORS) Support>> for more information.
See xref:http/namespace.adoc#http-cors[Cross-origin Resource Sharing (CORS) Support] for more information.
====== Inbound Gateway Timeout
[[inbound-gateway-timeout]]
==== Inbound Gateway Timeout
You can configure the HTTP inbound gate way to return a status code that you specify when a request times out.
The default is now `500 Internal Server Error` instead of `200 OK`.
See <<./http.adoc#http-response-statuscode,Response Status Code>> for more information.
See xref:http/namespace.adoc#http-response-statuscode[Response Status Code] for more information.
====== Form Data
[[form-data]]
==== Form Data
We added documentation for proxying `multipart/form-data` requests.
See <<./http.adoc#http,HTTP Support>> for more information.
See xref:http.adoc[HTTP Support] for more information.
[[x4.2-gw]]
===== Gateway Changes
=== Gateway Changes
This section describes general changes to the Spring Integration Gateway functionality.
====== Gateway Methods can Return `CompletableFuture<?>`
[[gateway-methods-can-return-completablefuture<?>]]
==== Gateway Methods can Return `CompletableFuture<?>`
When using Java 8, gateway methods can now return `CompletableFuture<?>`.
See <<./gateway.adoc#gw-completable-future,`CompletableFuture`>> for more information.
See xref:gateway.adoc#gw-completable-future[`CompletableFuture`] for more information.
====== MessagingGateway Annotation
[[messaginggateway-annotation]]
==== MessagingGateway Annotation
The request and reply timeout properties are now `String` instead of `Long` to allow configuration with property placeholders or SpEL.
See <<./gateway.adoc#messaging-gateway-annotation,`@MessagingGateway` Annotation>>.
See xref:gateway.adoc#messaging-gateway-annotation[`@MessagingGateway` Annotation].
[[x4.2-aggregator-changes]]
===== Aggregator Changes
=== Aggregator Changes
This section describes general changes to the Spring Integration aggregator functionality.
====== Aggregator Performance
[[aggregator-performance]]
==== Aggregator Performance
This release includes some performance improvements for aggregating components (aggregator, resequencer, and others), by more efficiently removing messages from groups when they are released.
New methods (`removeMessagesFromGroup`) have been added to the message store.
Set the `removeBatchSize` property (default: `100`) to adjust the number of messages deleted in each operation.
Currently, the JDBC, Redis, and MongoDB message stores support this property.
====== Output Message Group Processor
[[output-message-group-processor]]
==== Output Message Group Processor
When using a `ref` or inner bean for the aggregator, you can now directly bind a `MessageGroupProcessor`.
In addition, we added a `SimpleMessageGroupProcessor` that returns the collection of messages in the group.
When an output processor produces a collection of `Message<?>`, the aggregator releases those messages individually.
Configuring the `SimpleMessageGroupProcessor` makes the aggregator a message barrier, where messages are held up until they all arrive and are then released individually.
See <<./aggregator.adoc#aggregator,Aggregator>> for more information.
See xref:overview.adoc#overview-endpoints-aggregator[Aggregator] for more information.
===== FTP and SFTP Changes
[[ftp-and-sftp-changes]]
=== FTP and SFTP Changes
This section describes general changes to the Spring Integration FTP and SFTP functionality.
====== Inbound Channel Adapters
[[inbound-channel-adapters]]
==== Inbound Channel Adapters
You can now specify a `remote-directory-expression` on the inbound channel adapters, to determine the directory at runtime.
See <<./ftp.adoc#ftp,FTP/FTPS Adapters>> and <<./sftp.adoc#sftp,SFTP Adapters>> for more information.
See xref:ftp.adoc[FTP/FTPS Adapters] and xref:sftp.adoc[SFTP Adapters] for more information.
====== Gateway Partial Results
[[gateway-partial-results]]
==== Gateway Partial Results
When you use FTP or SFTP outbound gateways to operate on multiple files (with `mget` and `mput`), an exception can
occur after part of the request is completed.
If such a condition occurs, a `PartialSuccessException` that contains the partial results is thrown.
See <<./ftp.adoc#ftp-outbound-gateway,FTP Outbound Gateway>> and <<./sftp.adoc#sftp-outbound-gateway,SFTP Outbound Gateway>> for more information.
See xref:ftp/outbound-gateway.adoc[FTP Outbound Gateway] and xref:sftp/outbound-gateway.adoc[SFTP Outbound Gateway] for more information.
====== Delegating Session Factory
[[delegating-session-factory]]
==== Delegating Session Factory
We added a delegating session factory, enabling the selection of a particular session factory based on some thread context value.
See <<./ftp.adoc#ftp-dsf,Delegating Session Factory>> and <<./sftp.adoc#sftp-dsf,Delegating Session Factory>> for more information.
See xref:ftp/dsf.adoc[Delegating Session Factory] and xref:sftp/dsf.adoc[Delegating Session Factory] for more information.
====== Default Sftp Session Factory
[[default-sftp-session-factory]]
==== Default Sftp Session Factory
Previously, the `DefaultSftpSessionFactory` unconditionally allowed connections to unknown hosts.
This is now configurable (default: `false`).
The factory now requires a configured `knownHosts`, file unless the `allowUnknownKeys` property is `true` (default: `false`).
See <<./sftp.adoc#sftp-unk-keys,`allowUnknownKeys`::Set to `true` to allow connections to hosts with unknown (or changed) keys.>> for more information.
See xref:sftp/session-factory.adoc#sftp-unk-keys[`allowUnknownKeys`::Set to `true` to allow connections to hosts with unknown (or changed) keys.] for more information.
====== Message Session Callback
[[message-session-callback]]
==== Message Session Callback
We introduced the `MessageSessionCallback<F, T>` to perform any custom `Session` operations with the `requestMessage` context in the `<int-(s)ftp:outbound-gateway/>`.
See <<./ftp.adoc#ftp-session-callback,Using `MessageSessionCallback`>> and <<./sftp.adoc#sftp-session-callback,MessageSessionCallback>> for more information.
See xref:ftp/session-callback.adoc[Using `MessageSessionCallback`] and xref:sftp/session-callback.adoc[MessageSessionCallback] for more information.
===== Websocket Changes
[[websocket-changes]]
=== Websocket Changes
We added `WebSocketHandlerDecoratorFactory` support to the `ServerWebSocketContainer` to allow chained customization for the internal `WebSocketHandler`.
See <<./web-sockets.adoc#web-sockets-namespace,WebSockets Namespace Support>> for more information.
See xref:web-sockets.adoc#web-sockets-namespace[WebSockets Namespace Support] for more information.
===== Application Event Adapters changes
[[application-event-adapters-changes]]
=== Application Event Adapters changes
The `ApplicationEvent` adapters can now operate with `payload` as an `event` to directly allow omitting custom `ApplicationEvent` extensions.
For this purpose, we introduced the `publish-payload` boolean attribute has been introduced on the `<int-event:outbound-channel-adapter>`.
See <<./event.adoc#applicationevent,Spring `ApplicationEvent` Support>> for more information.
See xref:event.adoc[Spring `ApplicationEvent` Support] for more information.

View File

@@ -1,67 +1,77 @@
[[migration-4.2-4.3]]
=== Changes between 4.2 and 4.3
= Changes between 4.2 and 4.3
See the https://github.com/spring-projects/spring-integration/wiki/Spring-Integration-4.2-to-4.3-Migration-Guide[Migration Guide]
for important changes that might affect your applications.
You can find migration guides for all versions back to 2.1 on the https://github.com/spring-projects/spring-integration/wiki[Wiki].
[[x4.3-new-components]]
==== New Components
== New Components
Version 4.3 added a number of new components.
===== AMQP Async Outbound Gateway
[[amqp-async-outbound-gateway]]
=== AMQP Async Outbound Gateway
See <<./amqp.adoc#amqp-async-outbound-gateway,Asynchronous Outbound Gateway>>.
See xref:amqp.adoc#amqp-async-outbound-gateway[Asynchronous Outbound Gateway].
===== `MessageGroupFactory`
[[messagegroupfactory]]
=== `MessageGroupFactory`
We introduced the `MessageGroupFactory` strategy to allow control over `MessageGroup` instances in `MessageGroupStore` logic.
We added `SimpleMessageGroupFactory` implementation for the `SimpleMessageGroup`, with the `GroupType.HASH_SET` as the default
factory for the standard `MessageGroupStore` implementations.
See <<./message-store.adoc#message-store,Message Store>> for more information.
See xref:message-store.adoc[Message Store] for more information.
===== `PersistentMessageGroup`
[[persistentmessagegroup]]
=== `PersistentMessageGroup`
We added the `PersistentMessageGroup` (lazy-load proxy) implementation for persistent `MessageGroupStore` instances,
which return this instance for the `getMessageGroup()` when their `lazyLoadMessageGroups` is `true` (the default).
See <<./message-store.adoc#message-store,Message Store>> for more information.
See xref:message-store.adoc[Message Store] for more information.
===== FTP and SFTP Streaming Inbound Channel Adapters
[[ftp-and-sftp-streaming-inbound-channel-adapters]]
=== FTP and SFTP Streaming Inbound Channel Adapters
We added inbound channel adapters that return an `InputStream` for each file, letting you retrieve remote files without writing them to the local file system.
See <<./ftp.adoc#ftp-streaming,FTP Streaming Inbound Channel Adapter>> and <<./sftp.adoc#sftp-streaming,SFTP Streaming Inbound Channel Adapter>> for more information.
See xref:ftp/streaming.adoc[FTP Streaming Inbound Channel Adapter] and xref:sftp/streaming.adoc[SFTP Streaming Inbound Channel Adapter] for more information.
===== `StreamTransformer`
[[streamtransformer]]
=== `StreamTransformer`
We added `StreamTransformer` to transform an `InputStream` payload to either a `byte[]` or a `String`.
See <<./transformer.adoc#stream-transformer,Stream Transformer>> for more information.
See xref:transformer.adoc#stream-transformer[Stream Transformer] for more information.
===== Integration Graph
[[integration-graph]]
=== Integration Graph
We added `IntegrationGraphServer`, together with the `IntegrationGraphController` REST service, to expose the runtime model of a Spring Integration application as a graph.
See <<./graph.adoc#integration-graph,Integration Graph>> for more information.
See xref:graph.adoc#integration-graph[Integration Graph] for more information.
===== JDBC Lock Registry
[[jdbc-lock-registry]]
=== JDBC Lock Registry
We added `JdbcLockRegistry` for distributed locks shared through a database table.
See <<./jdbc.adoc#jdbc-lock-registry,JDBC Lock Registry>> for more information.
See xref:jdbc.adoc#jdbc-lock-registry[JDBC Lock Registry] for more information.
===== `LeaderInitiator` for `LockRegistry`
[[leaderinitiator-for-lockregistry]]
=== `LeaderInitiator` for `LockRegistry`
We added `LeaderInitiator` implementation based on the `LockRegistry` strategy.
See <<./endpoint.adoc#leadership-event-handling,Leadership Event Handling>> for more information.
See xref:endpoint.adoc#leadership-event-handling[Leadership Event Handling] for more information.
[[x4.3-general]]
==== General Changes
== General Changes
This section describes general changes that version 4.3 brought to Spring Integration.
===== Core Changes
[[core-changes]]
=== Core Changes
This section describes general changes to the core of Spring Integration.
====== Outbound Gateway within a Chain
[[outbound-gateway-within-a-chain]]
==== Outbound Gateway within a Chain
Previously, you could specify a `reply-channel` on an outbound gateway within a chain.
It was completely ignored.
@@ -69,239 +79,282 @@ The gateway's reply goes to the next chain element or, if the gateway is the las
This condition is now detected and disallowed.
If you have such a configuration, remove the `reply-channel`.
====== Asynchronous Service Activator
[[asynchronous-service-activator]]
==== Asynchronous Service Activator
We added an option to make the service activator be synchronous.
See <<./service-activator.adoc#async-service-activator,Asynchronous Service Activator>> for more information.
See xref:service-activator.adoc#async-service-activator[Asynchronous Service Activator] for more information.
====== Messaging Annotation Support changes
[[messaging-annotation-support-changes]]
==== Messaging Annotation Support changes
The messaging annotation support does not require a `@MessageEndpoint` (or any other `@Component`) annotation declaration on the class level.
To restore the previous behavior, set the `spring.integration.messagingAnnotations.require.componentAnnotation` of
`spring.integration.properties` to `true`.
See <<./configuration.adoc#global-properties,Global Properties>> and <<./configuration.adoc#annotations,Annotation Support>> for more information.
See xref:configuration/global-properties.adoc[Global Properties] and xref:configuration/annotations.adoc[Annotation Support] for more information.
===== Mail Changes
[[mail-changes]]
=== Mail Changes
This section describes general changes to the Spring Integration Mail functionality.
====== Customizable User Flag
[[customizable-user-flag]]
==== Customizable User Flag
The customizable `userFlag` (added in 4.2.2 to provide customization of the flag used to denote that the mail has been
seen) is now available in the XML namespace.
See <<./mail.adoc#imap-seen,Marking IMAP Messages When `\Recent` Is Not Supported>> for more information.
See xref:mail.adoc#imap-seen[Marking IMAP Messages When `Recent` Is Not Supported] for more information.
====== Mail Message Mapping
[[mail-message-mapping]]
==== Mail Message Mapping
You can now map inbound mail messages with the `MessageHeaders` containing the mail headers and the payload containing the email content.
Previously, the payload was always the raw `MimeMessage`.
See <<./mail.adoc#mail-mapping,Inbound Mail Message Mapping>> for more information.
See xref:mail.adoc#mail-mapping[Inbound Mail Message Mapping] for more information.
===== JMS Changes
[[jms-changes]]
=== JMS Changes
This section describes general changes to the Spring Integration JMS functionality.
====== Header Mapper
[[header-mapper]]
==== Header Mapper
The `DefaultJmsHeaderMapper` now maps the standard `correlationId` header as a message property by invoking its `toString()` method.
See <<./jms.adoc#jms-header-mapping,Mapping Message Headers to and from JMS Message>> for more information.
See xref:changes-3.0-4.0.adoc#x4.0-jms-header-mapping[Mapping Message Headers to and from JMS Message] for more information.
====== Asynchronous Gateway
[[asynchronous-gateway]]
==== Asynchronous Gateway
The JMS outbound gateway now has an `async` property.
See <<./jms.adoc#jms-async-gateway,Async Gateway>> for more information.
See xref:jms.adoc#jms-async-gateway[Async Gateway] for more information.
===== Aggregator Changes
[[aggregator-changes]]
=== Aggregator Changes
There is a change in behavior when a POJO aggregator releases a collection of `Message<?>` objects.
This is rare, but, if your application does that, you need to make a small change to your POJO.
See this <<./aggregator.adoc#agg-message-collection,IMPORTANT: The `SimpleMessageGroup.getMessages()` method returns an `unmodifiableCollection`.>> note for more information.
See this xref:aggregator.adoc#agg-message-collection[IMPORTANT: The `SimpleMessageGroup.getMessages()` method returns an `unmodifiableCollection`.] note for more information.
===== TCP/UDP Changes
[[tcp/udp-changes]]
=== TCP/UDP Changes
This section describes general changes to the Spring Integration TCP/UDP functionality.
====== Events
[[events]]
==== Events
A new `TcpConnectionServerListeningEvent` is emitted when a server connection factory is started.
See <<./ip.adoc#tcp-events,TCP Connection Events>> for more information.
See xref:changes-4.1-4.2.adoc#x4.2-tcp-events[TCP Connection Events] for more information.
You can now use the `destination-expression` and `socket-expression` attributes on `<int-ip:udp-outbound-channel-adapter>`.
See <<./ip.adoc#udp-adapters,UDP Adapters>> for more information.
See xref:ip/udp-adapters.adoc[UDP Adapters] for more information.
====== Stream Deserializers
[[stream-deserializers]]
==== Stream Deserializers
The various deserializers that cannot allocate the final buffer until the whole message has been assembled now support pooling the raw buffer into which the data is received rather than creating and discarding a buffer for each message.
See <<./ip.adoc#tcp-connection-factories,TCP Connection Factories>> for more information.
See xref:ip/tcp-connection-factories.adoc[TCP Connection Factories] for more information.
====== TCP Message Mapper
[[tcp-message-mapper]]
==== TCP Message Mapper
The message mapper now, optionally, sets a configured content type header.
See <<./ip.adoc#ip-msg-headers,IP Message Headers>> for more information.
See xref:ip/msg-headers.adoc[IP Message Headers] for more information.
===== File Changes
[[file-changes]]
=== File Changes
This section describes general changes to the Spring Integration File functionality.
====== Destination Directory Creation
[[destination-directory-creation]]
==== Destination Directory Creation
The generated file name for the `FileWritingMessageHandler` can represent a sub-path to save the desired directory structure for a file in the target directory.
See <<./file.adoc#file-writing-file-names,Generating File Names>> for more information.
See xref:file/writing.adoc#file-writing-file-names[Generating File Names] for more information.
The `FileReadingMessageSource` now hides the `WatchService` directory scanning logic in the inner class.
We added the `use-watch-service` and `watch-events` options to enable this behavior.
We deprecated the top-level `WatchServiceDirectoryScanner` because of inconsistency around the API.
See <<./file.adoc#watch-service-directory-scanner,`WatchServiceDirectoryScanner`>> for more information.
See xref:file.adoc#watch-service-directory-scanner[`WatchServiceDirectoryScanner`] for more information.
====== Buffer Size
[[buffer-size]]
==== Buffer Size
When writing files, you can now specify the buffer size.
====== Appending and Flushing
[[appending-and-flushing]]
==== Appending and Flushing
You can now avoid flushing files when appending and use a number of strategies to flush the data during idle periods.
See <<./file.adoc#file-flushing,Flushing Files When Using `APPEND_NO_FLUSH`>> for more information.
See xref:file/writing.adoc#file-flushing[Flushing Files When Using `APPEND_NO_FLUSH`] for more information.
====== Preserving Timestamps
[[preserving-timestamps]]
==== Preserving Timestamps
You can now configure the outbound channel adapter to set the destination file's `lastmodified` timestamp.
See <<./file.adoc#file-timestamps,File Timestamps>> for more information.
See xref:file/writing.adoc#file-timestamps[File Timestamps] for more information.
====== Splitter Changes
[[splitter-changes]]
==== Splitter Changes
The `FileSplitter` now automatically closes an FTP or SFTP session when the file is completely read.
This applies when the outbound gateway returns an `InputStream` or when you use the new FTP or SFTP streaming channel adapters.
We also introduced a new `markers-json` option to convert `FileSplitter.FileMarker` to JSON `String` for relaxed downstream network interaction.
See <<./file.adoc#file-splitter,File Splitter>> for more information.
See xref:file/splitter.adoc[File Splitter] for more information.
====== File Filters
[[file-filters]]
==== File Filters
We added `ChainFileListFilter` as an alternative to `CompositeFileListFilter`.
See <<./file.adoc#file-reading,Reading Files>> for more information.
See xref:file/reading.adoc[Reading Files] for more information.
===== AMQP Changes
[[amqp-changes]]
=== AMQP Changes
This section describes general changes to the Spring Integration AMQP functionality.
====== Content Type Message Converter
[[content-type-message-converter]]
==== Content Type Message Converter
The outbound endpoints now support a `RabbitTemplate` configured with a `ContentTypeDelegatingMessageConverter` such
that you can choose the converter based on the message content type.
See <<./amqp.adoc#content-type-conversion-outbound,Outbound Message Conversion>> for more information.
See xref:amqp/content-type-conversion-outbound.adoc[Outbound Message Conversion] for more information.
====== Headers for Delayed Message Handling
[[headers-for-delayed-message-handling]]
==== Headers for Delayed Message Handling
Spring AMQP 1.6 adds support for https://www.rabbitmq.com/blog/2015/04/16/scheduling-messages-with-rabbitmq/[delayed message exchanges].
Header mapping now supports the headers (`amqp_delay` and `amqp_receivedDelay`) used by this feature.
====== AMQP-Backed Channels
[[amqp-backed-channels]]
==== AMQP-Backed Channels
AMQP-backed channels now support message mapping.
See <<./amqp.adoc#amqp-channels,AMQP-backed Message Channels>> for more information.
See xref:amqp/channels.adoc[AMQP-backed Message Channels] for more information.
===== Redis Changes
[[redis-changes]]
=== Redis Changes
This section describes general changes to the Spring Integration Redis functionality.
====== List Push/Pop Direction
[[list-push/pop-direction]]
==== List Push/Pop Direction
Previously, the queue channel adapters always used the Redis list in a fixed direction, pushing to the left end and reading from the right end.
You can now configure the reading and writing direction with the `rightPop` and `leftPush` options for the
`RedisQueueMessageDrivenEndpoint` and `RedisQueueOutboundChannelAdapter`, respectively.
See <<./redis.adoc#redis-queue-inbound-channel-adapter,Redis Queue Inbound Channel Adapter>> and <<./redis.adoc#redis-queue-outbound-channel-adapter,Redis Queue Outbound Channel Adapter>> for more information.
See xref:redis.adoc#redis-queue-inbound-channel-adapter[Redis Queue Inbound Channel Adapter] and xref:redis.adoc#redis-queue-outbound-channel-adapter[Redis Queue Outbound Channel Adapter] for more information.
====== Queue Inbound Gateway Default Serializer
[[queue-inbound-gateway-default-serializer]]
==== Queue Inbound Gateway Default Serializer
The default serializer in the inbound gateway has been changed to a `JdkSerializationRedisSerializer` for compatibility with the outbound gateway.
See <<./redis.adoc#redis-queue-inbound-gateway,Redis Queue Inbound Gateway>> for more information.
See xref:redis.adoc#redis-queue-inbound-gateway[Redis Queue Inbound Gateway] for more information.
===== HTTP Changes
[[http-changes]]
=== HTTP Changes
Previously, with requests that had a body (such as `POST`) that had no `content-type` header, the body was ignored.
With this release, the content type of such requests is considered to be `application/octet-stream` as recommended
by RFC 2616.
See <<./http.adoc#http-inbound,Http Inbound Components>> for more information.
See xref:http/inbound.adoc[Http Inbound Components] for more information.
`uriVariablesExpression` now uses a `SimpleEvaluationContext` by default (since 4.3.15).
See <<./http.adoc#mapping-uri-variables,Mapping URI Variables>> for more information.
See xref:http/namespace.adoc#mapping-uri-variables[Mapping URI Variables] for more information.
===== SFTP Changes
[[sftp-changes]]
=== SFTP Changes
This section describes general changes to the Spring Integration SFTP functionality.
====== Factory Bean
[[factory-bean]]
==== Factory Bean
We added a new factory bean to simplify the configuration of Jsch proxies for SFTP.
See `JschProxyFactoryBean` for more information.
====== `chmod` Changes
[[chmod-changes]]
==== `chmod` Changes
The SFTP outbound gateway (for `put` and `mput` commands) and the SFTP outbound channel adapter now support the `chmod` attribute to change the remote file permissions after uploading.
See `<<./sftp.adoc#sftp-outbound,SFTP Outbound Channel Adapter>>` and `<<./sftp.adoc#sftp-outbound-gateway,SFTP Outbound Gateway>>` for more information.
See `xref:sftp/outbound.adoc[SFTP Outbound Channel Adapter]` and `xref:sftp/outbound-gateway.adoc[SFTP Outbound Gateway]` for more information.
===== FTP Changes
[[ftp-changes]]
=== FTP Changes
This section describes general changes to the Spring Integration FTP functionality.
====== Session Changes
[[session-changes]]
==== Session Changes
The `FtpSession` now supports `null` for the `list()` and `listNames()` methods, since underlying FTP Client can use it.
With that, you can now configure the `FtpOutboundGateway` without the `remoteDirectory` expression.
You can also configure the `<int-ftp:inbound-channel-adapter>` without `remote-directory` or `remote-directory-expression`.
See <<./ftp.adoc#ftp,FTP/FTPS Adapters>> for more information.
See xref:ftp.adoc[FTP/FTPS Adapters] for more information.
===== Router Changes
[[router-changes]]
=== Router Changes
The `ErrorMessageExceptionTypeRouter` now supports the `Exception` superclass mappings to avoid duplication for the same channel in case of multiple inheritors.
For this purpose, the `ErrorMessageExceptionTypeRouter` loads mapping classes during initialization to fail-fast for a `ClassNotFoundException`.
See <<./router.adoc#router,Routers>> for more information.
See xref:router.adoc[Routers] for more information.
===== Header Mapping
[[header-mapping]]
=== Header Mapping
This section describes the changes to header mapping between version 4.2 and 4.3.
====== General
[[general]]
==== General
AMQP, WS, and XMPP header mappings (such as `request-header-mapping` and `reply-header-mapping`) now support negated patterns.
See <<./amqp.adoc#amqp-message-headers,AMQP Message Headers>>, <<./ws.adoc#ws-message-headers,WS Message Headers>>, and <<./xmpp.adoc#xmpp-message-headers,XMPP Message Headers>> for more information.
See xref:amqp/message-headers.adoc[AMQP Message Headers], xref:ws.adoc#ws-message-headers[WS Message Headers], and xref:xmpp.adoc#xmpp-message-headers[XMPP Message Headers] for more information.
====== AMQP Header Mapping
[[amqp-header-mapping]]
==== AMQP Header Mapping
Previously, only standard AMQP headers were mapped by default.
You had to explicitly enable mapping of user-defined headers.
With this release, all headers are mapped by default.
In addition, the inbound `amqp_deliveryMode` header is no longer mapped by default.
See <<./amqp.adoc#amqp-message-headers,AMQP Message Headers>> for more information.
See xref:amqp/message-headers.adoc[AMQP Message Headers] for more information.
===== Groovy Scripts
[[groovy-scripts]]
=== Groovy Scripts
You can now configure groovy scripts with the `compile-static` hint or any other `CompilerConfiguration` options.
See <<./groovy.adoc#groovy-config,Groovy Configuration>> for more information.
See xref:groovy.adoc#groovy-config[Groovy Configuration] for more information.
===== `@InboundChannelAdapter` Changes
[[inboundchanneladapter-changes]]
=== `@InboundChannelAdapter` Changes
The `@InboundChannelAdapter` now has an alias `channel` attribute for the regular `value`.
In addition, the target `SourcePollingChannelAdapter` components can now resolve the target `outputChannel` bean from its provided name (`outputChannelName` options) in a late-binding manner.
See <<./configuration.adoc#annotations,Annotation Support>> for more information.
See xref:configuration/annotations.adoc[Annotation Support] for more information.
===== XMPP Changes
[[xmpp-changes]]
=== XMPP Changes
The XMPP channel adapters now support the XMPP Extensions (XEP).
See <<./xmpp.adoc#xmpp-extensions,XMPP Extensions>> for more information.
See xref:xmpp.adoc#xmpp-extensions[XMPP Extensions] for more information.
===== WireTap Late Binding
[[wiretap-late-binding]]
=== WireTap Late Binding
The `WireTap` `ChannelInterceptor` now can accept a `channelName` that is resolved to the target `MessageChannel`
later, during the first active interceptor operation.
See <<./channel.adoc#channel-wiretap,Wire Tap>> for more information.
See xref:channel/configuration.adoc#channel-wiretap[Wire Tap] for more information.
===== `ChannelMessageStoreQueryProvider` Changes
[[channelmessagestorequeryprovider-changes]]
=== `ChannelMessageStoreQueryProvider` Changes
The `ChannelMessageStoreQueryProvider` now supports H2 databases.
See <<./jdbc.adoc#jdbc-message-store-channels,Backing Message Channels>> for more information.
See xref:jdbc/message-store.adoc#jdbc-message-store-channels[Backing Message Channels] for more information.
===== WebSocket Changes
[[websocket-changes]]
=== WebSocket Changes
The `ServerWebSocketContainer` now exposes an `allowedOrigins` option, and `SockJsServiceOptions` exposes a `suppressCors` option.
See <<./web-sockets.adoc#web-sockets,WebSockets Support>> for more information.
See xref:web-sockets.adoc[WebSockets Support] for more information.

View File

@@ -1,100 +1,109 @@
[[migration-4.3-5.0]]
=== Changes between 4.3 and 5.0
= Changes between 4.3 and 5.0
See the https://github.com/spring-projects/spring-integration/wiki/Spring-Integration-4.3-to-5.0-Migration-Guide[Migration Guide] for important changes that might affect your applications.
You can find migration guides for all versions back to 2.1 on the https://github.com/spring-projects/spring-integration/wiki[wiki].
[[x5.0-new-components]]
==== New Components
== New Components
Version 5.0 added a number of new components.
===== Java DSL
[[java-dsl]]
=== Java DSL
The separate https://github.com/spring-projects/spring-integration-java-dsl[Spring Integration Java DSL] project has now been merged into the core Spring Integration project.
The `IntegrationComponentSpec` implementations for channel adapters and gateways are distributed to their specific modules.
See <<./dsl.adoc#java-dsl,Java DSL>> for more information about Java DSL support.
See xref:dsl.adoc#java-dsl[Java DSL] for more information about Java DSL support.
See also the https://github.com/spring-projects/spring-integration/wiki/Spring-Integration-4.3-to-5.0-Migration-Guide#java-dsl[4.3 to 5.0 Migration Guide] for the required steps to move to Spring Integration 5.0.
===== Testing Support
[[testing-support]]
=== Testing Support
We created a new Spring Integration Test Framework to help with testing Spring Integration applications.
Now, with the `@SpringIntegrationTest` annotation on test classes and the `MockIntegration` factory, you can make your JUnit tests for integration flows somewhat easier.
See <<./testing.adoc#testing,Testing support>> for more information.
See xref:testing.adoc[Testing support] for more information.
===== MongoDB Outbound Gateway
[[mongodb-outbound-gateway]]
=== MongoDB Outbound Gateway
The new `MongoDbOutboundGateway` lets you make queries to the database on demand by sending a message to its request channel.
See <<./mongodb.adoc#mongodb-outbound-gateway,MongoDB Outbound Gateway>> for more information.
See xref:mongodb.adoc#mongodb-outbound-gateway[MongoDB Outbound Gateway] for more information.
===== WebFlux Gateways and Channel Adapters
[[webflux-gateways-and-channel-adapters]]
=== WebFlux Gateways and Channel Adapters
We introduced the new WebFlux support module for Spring WebFlux Framework gateways and channel adapters.
See <<./webflux.adoc#webflux,WebFlux Support>> for more information.
See xref:webflux.adoc[WebFlux Support] for more information.
===== Content Type Conversion
[[content-type-conversion]]
=== Content Type Conversion
Now that we use the new `InvocableHandlerMethod`-based infrastructure for service method invocations, we can perform `contentType` conversion from the payload to a target method argument.
See <<./endpoint.adoc#content-type-conversion,Content Type Conversion>> for more information.
See xref:endpoint.adoc#content-type-conversion[Content Type Conversion] for more information.
===== `ErrorMessagePublisher` and `ErrorMessageStrategy`
[[errormessagepublisher-and-errormessagestrategy]]
=== `ErrorMessagePublisher` and `ErrorMessageStrategy`
We added `ErrorMessagePublisher` and the `ErrorMessageStrategy` for creating `ErrorMessage` instances.
See <<./error-handling.adoc#error-handling,Error Handling>> for more information.
See xref:scatter-gather.adoc#scatter-gather-error-handling[Error Handling] for more information.
===== JDBC Metadata Store
[[jdbc-metadata-store]]
=== JDBC Metadata Store
We added a JDBC implementation of the `MetadataStore` implementation.
This is useful when you need to ensure transactional boundaries for metadata.
See <<./jdbc.adoc#jdbc-metadata-store,JDBC Metadata Store>> for more information.
See xref:jdbc.adoc#jdbc-metadata-store[JDBC Metadata Store] for more information.
[[x5.0-general]]
==== General Changes
== General Changes
Spring Integration is now fully based on Spring Framework `5.0` and Project Reactor `3.1`.
Previous Project Reactor versions are no longer supported.
===== Core Changes
[[core-changes]]
=== Core Changes
The `@Poller` annotation now has the `errorChannel` attribute for easier configuration of the underlying `MessagePublishingErrorHandler`.
See <<./configuration.adoc#annotations,Annotation Support>> for more information.
See xref:configuration/annotations.adoc[Annotation Support] for more information.
All the request-reply endpoints (based on `AbstractReplyProducingMessageHandler`) can now start transactions and, therefore, make the whole downstream flow transactional.
See <<./handler-advice.adoc#tx-handle-message-advice,Transaction Support>> for more information.
See xref:handler-advice/tx-handle-message.adoc[Transaction Support] for more information.
The `SmartLifecycleRoleController` now provides methods to obtain status of endpoints in roles.
See <<./endpoint.adoc#endpoint-roles,Endpoint Roles>> for more information.
See xref:endpoint.adoc#endpoint-roles[Endpoint Roles] for more information.
By default, POJO methods are now invoked by using an `InvocableHandlerMethod`, but you can configure them to use SpEL, as before.
See <<./overview.adoc#pojo-invocation,POJO Method invocation>> for more information.
See xref:overview.adoc#pojo-invocation[POJO Method invocation] for more information.
When targeting POJO methods as message handlers, you can now mark one of the service methods with the `@Default` annotation to provide a fallback mechanism for non-matched conditions.
See <<./service-activator.adoc#service-activator-namespace,Configuring Service Activator>> for more information.
See xref:service-activator.adoc#service-activator-namespace[Configuring Service Activator] for more information.
We added a simple `PassThroughTransactionSynchronizationFactory` to always store a polled message in the current transaction context.
That message is used as a `failedMessage` property of the `MessagingException`, which wraps any raw exception thrown during transaction completion.
See <<./transactions.adoc#transaction-synchronization,Transaction Synchronization>> for more information.
See xref:transactions.adoc#transaction-synchronization[Transaction Synchronization] for more information.
The aggregator expression-based `ReleaseStrategy` now evaluates the expression against the `MessageGroup` instead of just the collection of `Message<?>`.
See <<./aggregator.adoc#aggregator-spel,Aggregators and Spring Expression Language (SpEL)>> for more information.
See xref:aggregator.adoc#aggregator-spel[Aggregators and Spring Expression Language (SpEL)] for more information.
You can now supply the `ObjectToMapTransformer` with a customized `JsonObjectMapper`.
See <<./aggregator.adoc#aggregator-spel,Aggregators and Spring Expression Language (SpEL)>> for more information.
See xref:aggregator.adoc#aggregator-spel[Aggregators and Spring Expression Language (SpEL)] for more information.
The `@GlobalChannelInterceptor` annotation and `<int:channel-interceptor>` now support negative patterns (via `!` prepending) for component names matching.
See <<./channel.adoc#global-channel-configuration-interceptors,Global Channel Interceptor Configuration>> for more information.
See xref:channel/configuration.adoc#global-channel-configuration-interceptors[Global Channel Interceptor Configuration] for more information.
When a candidate failed to acquire the lock, the `LockRegistryLeaderInitiator` now emits a new `OnFailedToAcquireMutexEvent` through `DefaultLeaderEventPublisher`.
See `<<./endpoint.adoc#leadership-event-handling,Leadership Event Handling>>` for more information.
See `xref:endpoint.adoc#leadership-event-handling[Leadership Event Handling]` for more information.
===== Gateway Changes
[[gateway-changes]]
=== Gateway Changes
When the gateway method has a `void` return type and an error channel is provided, the gateway now correctly sets the `errorChannel` header.
Previously, the header was not populated.
@@ -103,40 +112,46 @@ This caused synchronous downstream flows (running on the calling thread) to send
The `RequestReplyExchanger` interface now has a `throws MessagingException` clause to meet the proposed messages exchange contract.
You can now specify the request and reply timeouts with SpEL expressions.
See <<./gateway.adoc#gateway,Messaging Gateways>> for more information.
See xref:gateway.adoc[Messaging Gateways] for more information.
===== Aggregator Performance Changes
[[aggregator-performance-changes]]
=== Aggregator Performance Changes
By default, aggregators now use a `SimpleSequenceSizeReleaseStrategy`, which is more efficient, especially with large groups.
Empty groups are now scheduled for removal after `empty-group-min-timeout`.
See <<./aggregator.adoc#aggregator,Aggregator>> for more information.
See xref:overview.adoc#overview-endpoints-aggregator[Aggregator] for more information.
===== Splitter Changes
[[splitter-changes]]
=== Splitter Changes
The splitter component can now handle and split Java `Stream` and Reactive Streams `Publisher` objects.
If the output channel is a `ReactiveStreamsSubscribableChannel`, the `AbstractMessageSplitter` builds a `Flux` for subsequent iteration instead of a regular `Iterator`, independent of the object being split.
In addition, `AbstractMessageSplitter` provides `protected obtainSizeIfPossible()` methods to allow determination of the size of the `Iterable` and `Iterator` objects, if that is possible.
See <<./splitter.adoc#splitter,Splitter>> for more information.
See xref:splitter.adoc[Splitter] for more information.
===== JMS Changes
[[jms-changes]]
=== JMS Changes
Previously, Spring Integration JMS XML configuration used a default bean name of `connectionFactory` for the JMS connection factory, letting the property be omitted from component definitions.
We renamed it to `jmsConnectionFactory`, which is the bean name used by Spring Boot to auto-configure the JMS connection factory bean.
If your application relies on the previous behavior, you can rename your `connectionFactory` bean to `jmsConnectionFactory` or specifically configure your components to use your bean by using its current name.
See <<./jms.adoc#jms,JMS Support>> for more information.
See xref:jms.adoc[JMS Support] for more information.
===== Mail Changes
[[mail-changes]]
=== Mail Changes
Some inconsistencies with rendering IMAP mail content have been resolved.
See <<./mail.adoc#imap-format-important,the note in the "`Mail-receiving Channel Adapter`" section>> for more information.
See xref:mail.adoc#imap-format-important[the note in the "`Mail-receiving Channel Adapter`" section] for more information.
===== Feed Changes
[[feed-changes]]
=== Feed Changes
Instead of the `com.rometools.fetcher.FeedFetcher`, which is deprecated in ROME, we introduced a new `Resource` property for the `FeedEntryMessageSource`.
See <<./feed.adoc#feed,Feed Adapter>> for more information.
See xref:feed.adoc[Feed Adapter] for more information.
===== File Changes
[[file-changes]]
=== File Changes
We introduced the new `FileHeaders.RELATIVE_PATH` message header to represent relative path in `FileReadingMessageSource`.
@@ -149,13 +164,14 @@ The file outbound channel adapter and gateway (`FileWritingMessageHandler`) now
They also now support setting file permissions on the newly written file.
A new `FileSystemMarkerFilePresentFileListFilter` is now available.
See <<./file.adoc#file-incomplete,Dealing With Incomplete Data>> for more information.
See xref:file/reading.adoc#file-incomplete[Dealing With Incomplete Data] for more information.
The `FileSplitter` now provides a `firstLineAsHeader` option to carry the first line of content as a header in the messages emitted for the remaining lines.
See <<./file.adoc#files,File Support>> for more information.
See xref:file.adoc[File Support] for more information.
===== FTP and SFTP Changes
[[ftp-and-sftp-changes]]
=== FTP and SFTP Changes
The inbound channel adapters now have a property called `max-fetch-size`, which is used to limit the number of files fetched during a poll when no files are currently in the local directory.
By default, they also are configured with a `FileSystemPersistentAcceptOnceFileListFilter` in the `local-filter`.
@@ -174,7 +190,7 @@ The FTP and SFTP streaming inbound channel adapters now add remote file informat
The FTP and SFTP outbound channel adapters (as well as the `PUT` command for outbound gateways) now support `InputStream` as `payload`, too.
The inbound channel adapters can now build file trees locally by using a newly introduced `RecursiveDirectoryScanner`.
See the `scanner` option in the <<./ftp.adoc#ftp-inbound,FTP Inbound Channel Adapter>> section for injection.
See the `scanner` option in the xref:ftp/inbound.adoc[FTP Inbound Channel Adapter] section for injection.
Also, you can now switch these adapters to the `WatchService` instead.
We added The `NLST` command to the `AbstractRemoteFileOutboundGateway` to perform the list files names remote command.
@@ -187,24 +203,28 @@ We added new filters for detecting incomplete remote files.
The `FtpOutboundGateway` and `SftpOutboundGateway` now support an option to remove the remote file after a successful transfer by using the `GET` or `MGET` commands.
See <<./ftp.adoc#ftp,FTP/FTPS Adapters>> and <<./sftp.adoc#sftp,SFTP Adapters>> for more information.
See xref:ftp.adoc[FTP/FTPS Adapters] and xref:sftp.adoc[SFTP Adapters] for more information.
===== Integration Properties
[[integration-properties]]
=== Integration Properties
Version 4.3.2 added a new `spring.integration.readOnly.headers` global property to let you customize the list of headers that should not be copied to a newly created `Message` by the `MessageBuilder`.
See <<./configuration.adoc#global-properties,Global Properties>> for more information.
See xref:configuration/global-properties.adoc[Global Properties] for more information.
===== Stream Changes
[[stream-changes]]
=== Stream Changes
We added a new option on the `CharacterStreamReadingMessageSource` to let it be used to "`pipe`" stdin and publish an application event when the pipe is closed.
See <<./stream.adoc#stream-reading,Reading from Streams>> for more information.
See xref:stream.adoc#stream-reading[Reading from Streams] for more information.
===== Barrier Changes
[[barrier-changes]]
=== Barrier Changes
The `BarrierMessageHandler` now supports a discard channel to which late-arriving trigger messages are sent.
See <<./barrier.adoc#barrier,Thread Barrier>> for more information.
See xref:barrier.adoc[Thread Barrier] for more information.
===== AMQP Changes
[[amqp-changes]]
=== AMQP Changes
The AMQP outbound endpoints now support setting a delay expression when you use the RabbitMQ Delayed Message Exchange plugin.
@@ -215,32 +235,36 @@ Pollable AMQP-backed channels now block the poller thread for the poller's confi
Headers, such as `contentType`, that are added to message properties by the message converter are now used in the final message.
Previously, it depended on the converter type as to which headers and message properties appeared in the final message.
To override the headers set by the converter, set the `headersMappedLast` property to `true`.
See <<./amqp.adoc#amqp,AMQP Support>> for more information.
See xref:amqp.adoc[AMQP Support] for more information.
===== HTTP Changes
[[http-changes]]
=== HTTP Changes
By default, the `DefaultHttpHeaderMapper.userDefinedHeaderPrefix` property is now an empty string instead of `X-`.
See <<./http.adoc#http-header-mapping,HTTP Header Mappings>> for more information.
See xref:http/header-mapping.adoc[HTTP Header Mappings] for more information.
By default, `uriVariablesExpression` now uses a `SimpleEvaluationContext` (since 5.0.4).
See <<./http.adoc#mapping-uri-variables,Mapping URI Variables>> for more information.
See xref:http/namespace.adoc#mapping-uri-variables[Mapping URI Variables] for more information.
===== MQTT Changes
[[mqtt-changes]]
=== MQTT Changes
Inbound messages are now mapped with the `RECEIVED_TOPIC`, `RECEIVED_QOS`, and `RECEIVED_RETAINED` headers to avoid inadvertent propagation to outbound messages when an application relays messages.
The outbound channel adapter now supports expressions for the topic, qos, and retained properties.
The defaults remain the same.
See <<./mqtt.adoc#mqtt,MQTT Support>> for more information.
See xref:mqtt.adoc[MQTT Support] for more information.
===== STOMP Changes
[[stomp-changes]]
=== STOMP Changes
We changed the STOMP module to use `ReactorNettyTcpStompClient`, based on the Project Reactor `3.1` and `reactor-netty` extension.
We renamed `Reactor2TcpStompSessionManager` to `ReactorNettyTcpStompSessionManager`, according to the `ReactorNettyTcpStompClient` foundation.
See <<./stomp.adoc#stomp,STOMP Support>> for more information.
See xref:stomp.adoc[STOMP Support] for more information.
===== Web Services Changes
[[web-services-changes]]
=== Web Services Changes
You can now supply `WebServiceOutboundGateway` instances with an externally configured `WebServiceTemplate` instances.
@@ -248,9 +272,10 @@ You can now supply `WebServiceOutboundGateway` instances with an externally conf
Simple WebService inbound and outbound gateways can now deal with the complete `WebServiceMessage` as a `payload`, allowing the manipulation of MTOM attachments.
See <<./ws.adoc#ws,Web Services Support>> for more information.
See xref:ws.adoc[Web Services Support] for more information.
===== Redis Changes
[[redis-changes]]
=== Redis Changes
The `RedisStoreWritingMessageHandler` is supplied now with additional `String`-based setters for SpEL expressions (for convenience with Java configuration).
You can now configure the `zsetIncrementExpression` on the `RedisStoreWritingMessageHandler` as well.
@@ -259,9 +284,10 @@ In addition, this property has been changed from `true` to `false` since the `IN
You can now supply the `RedisInboundChannelAdapter` with an `Executor` for executing Redis listener invokers.
In addition, the received messages now contain a `RedisHeaders.MESSAGE_SOURCE` header to indicate the source of the message (topic or pattern).
See <<./redis.adoc#redis,Redis Support>> for more information.
See xref:redis.adoc[Redis Support] for more information.
===== TCP Changes
[[tcp-changes]]
=== TCP Changes
We added a new `ThreadAffinityClientConnectionFactory` to bind TCP connections to threads.
@@ -269,28 +295,31 @@ You can now configure the TCP connection factories to support `PushbackInputStre
We added a `ByteArrayElasticRawDeserializer` without `maxMessageSize` to control and buffer incoming data as needed.
See <<./ip.adoc#ip,TCP and UDP Support>> for more information.
See xref:ip.adoc[TCP and UDP Support] for more information.
===== JDBC Changes
[[jdbc-changes]]
=== JDBC Changes
The `JdbcMessageChannelStore` now provides a setter for `ChannelMessageStorePreparedStatementSetter`, letting you customize message insertion in the store.
The `ExpressionEvaluatingSqlParameterSourceFactory` now provides a setter for `sqlParameterTypes`, letting you customize the SQL types of the parameters.
See <<./jdbc.adoc#jdbc,JDBC Support>> for more information.
See xref:jdbc.adoc[JDBC Support] for more information.
===== Metrics Changes
[[metrics-changes]]
=== Metrics Changes
https://micrometer.io/[Micrometer] application monitoring is now supported (since version 5.0.2).
See <<./metrics.adoc#micrometer-integration,Micrometer Integration>> for more information.
See xref:metrics.adoc#micrometer-integration[Micrometer Integration] for more information.
IMPORTANT: Changes were made to the Micrometer `Meters` in version 5.0.3 to make them more suitable for use in dimensional systems.
Further changes were made in 5.0.4.
If you use Micrometer, we recommend a minimum of version 5.0.4.
===== `@EndpointId` Annotations
[[endpointid-annotations]]
=== `@EndpointId` Annotations
Introduced in version 5.0.4, this annotation provides control over bean naming when you use Java configuration.
See <<./overview.adoc#endpoint-bean-names,Endpoint Bean Names>> for more information.
See xref:overview.adoc#endpoint-bean-names[Endpoint Bean Names] for more information.

View File

@@ -1,51 +1,51 @@
[[migration-5.0-5.1]]
=== Changes between 5.0 and 5.1
= Changes between 5.0 and 5.1
[[x5.1-new-components]]
==== New Components
== New Components
The following components are new in 5.1:
* <<x5.1-AmqpDedicatedChannelAdvice>>
* xref:changes-5.0-5.1.adoc#x5.1-AmqpDedicatedChannelAdvice[`AmqpDedicatedChannelAdvice`]
[[x5.1-AmqpDedicatedChannelAdvice]]
===== `AmqpDedicatedChannelAdvice`
=== `AmqpDedicatedChannelAdvice`
See <<./amqp.adoc#amqp-strict-ordering,Strict Message Ordering>>.
See xref:amqp/strict-ordering.adoc[Strict Message Ordering].
[[x5.1-Functions]]
===== Improved Function Support
=== Improved Function Support
The `java.util.function` interfaces now have improved integration support in the Framework components.
Also Kotlin lambdas now can be used for handler and source methods.
See <<./functions-support.adoc#functions-support,`java.util.function` Interfaces Support>>.
See xref:functions-support.adoc[`java.util.function` Interfaces Support].
[[x5.1-LongRunningTest]]
===== `@LongRunningTest`
=== `@LongRunningTest`
A JUnit 5 `@LongRunningTest` conditional annotation is provided to check the environment or system properties for the `RUN_LONG_INTEGRATION_TESTS` entry with the value of `true` to determine if test should be run or skipped.
See <<./testing.adoc#test-junit-rules,JUnit Rules and Conditions>>.
See xref:testing.adoc#test-junit-rules[JUnit Rules and Conditions].
[[x5.1-general]]
==== General Changes
== General Changes
The following changes have been made in version 5.1:
* <<x5.1-java-dsl>>
* <<x5.1-dispatcher-exceptions>>
* <<x5.1-global-channel-interceptors>>
* <<x5.1-object-to-json-transformer>>
* <<x5.1-integration-flows-generated-bean-names>>
* <<x5.1-aggregator>>
* <<x5.1-publisher>>
* <<x51.-integration-graph>>
* <<x51.-global-properties>>
* <<x51.-poller-annotation>>
* xref:changes-5.0-5.1.adoc#x5.1-java-dsl[Java DSL]
* xref:changes-5.0-5.1.adoc#x5.1-dispatcher-exceptions[Dispatcher Exceptions]
* xref:changes-5.0-5.1.adoc#x5.1-global-channel-interceptors[Global Channel Interceptors]
* xref:changes-5.0-5.1.adoc#x5.1-object-to-json-transformer[`ObjectToJsonTransformer`]
* xref:changes-5.0-5.1.adoc#x5.1-integration-flows-generated-bean-names[Integration Flows: Generated Bean Names]
* xref:changes-5.0-5.1.adoc#x5.1-aggregator[Aggregator Changes]
* xref:changes-5.0-5.1.adoc#x5.1-publisher[@Publisher annotation changes]
* xref:changes-5.0-5.1.adoc#x51.-integration-graph[Integration Graph Customization]
* xref:changes-5.0-5.1.adoc#x51.-global-properties[Integration Global Properties]
* xref:changes-5.0-5.1.adoc#x51.-poller-annotation[The `receiveTimeout` for `@Poller`]
[[x5.1-java-dsl]]
===== Java DSL
=== Java DSL
The `IntegrationFlowContext` is now an interface and `IntegrationFlowRegistration` is an inner interface of `IntegrationFlowContext`.
@@ -57,7 +57,7 @@ A generated bean name for any `NamedComponent` within an integration flow is now
The `GenericHandler.handle()` now excepts a `MessageHeaders` type for the second argument.
[[x5.1-dispatcher-exceptions]]
===== Dispatcher Exceptions
=== Dispatcher Exceptions
Exceptions caught and re-thrown by `AbstractDispatcher` are now more consistent:
@@ -72,13 +72,13 @@ Previously:
* Checked exceptions were wrapped in a `MessageDeliveryException` with the `failedMessage` property set.
[[x5.1-global-channel-interceptors]]
===== Global Channel Interceptors
=== Global Channel Interceptors
Global channel interceptors now apply to dynamically registered channels, such as through the `IntegrationFlowContext` when using the Java DSL or beans that are initialized using `beanFactory.initializeBean()`.
Previously, when beans were created after the application context was refreshed, interceptors were not applied.
[[x5.1-channel-interceptors]]
===== Channel Interceptors
=== Channel Interceptors
`ChannelInterceptor.postReceive()` is no longer called when no message is received; it is no longer necessary to check for a `null` `Message<?>`.
Previously, the method was called.
@@ -86,22 +86,22 @@ If you have an interceptor that relies on the previous behavior, implement `afte
Furthermore, the `PolledAmqpChannel` and `PolledJmsChannel` previously did not invoke `afterReceiveCompleted()` with `null`; they now do.
[[x5.1-object-to-json-transformer]]
===== `ObjectToJsonTransformer`
=== `ObjectToJsonTransformer`
A new `ResultType.BYTES` mode is introduced for the `ObjectToJsonTransformer`.
See <<./transformer.adoc#json-transformers,JSON Transformers>> for more information.
See xref:transformer.adoc#json-transformers[JSON Transformers] for more information.
[[x5.1-integration-flows-generated-bean-names]]
===== Integration Flows: Generated Bean Names
=== Integration Flows: Generated Bean Names
Starting with version 5.0.5, generated bean names for the components in an `IntegrationFlow` include the flow bean name, followed by a dot, as a prefix.
For example, if a flow bean were named `flowBean`, a generated bean might be named `flowBean.generatedBean`.
See <<./dsl.adoc#java-dsl-flows,Working With Message Flows>> for more information.
See xref:dsl/java-flows.adoc[Working With Message Flows] for more information.
[[x5.1-aggregator]]
===== Aggregator Changes
=== Aggregator Changes
If the `groupTimeout` is evaluated to a negative value, an aggregator now expires the group immediately.
Only `null` is considered as a signal to do nothing for the current message.
@@ -109,18 +109,18 @@ Only `null` is considered as a signal to do nothing for the current message.
A new `popSequence` property has been introduced to allow (by default) to call a `MessageBuilder.popSequenceDetails()` for the output message.
Also an `AbstractAggregatingMessageGroupProcessor` returns now an `AbstractIntegrationMessageBuilder` instead of the whole `Message` for optimization.
See <<./aggregator.adoc#aggregator,Aggregator>> for more information.
See xref:overview.adoc#overview-endpoints-aggregator[Aggregator] for more information.
[[x5.1-publisher]]
===== @Publisher annotation changes
=== @Publisher annotation changes
Starting with version 5.1, you must explicitly turn on the `@Publisher` AOP functionality by using `@EnablePublisher` or by using the `<int:enable-publisher>` child element on `<int:annotation-config>`.
Also the `proxy-target-class` and `order` attributes have been added for tuning the `ProxyFactory` configuration.
See <<./message-publishing.adoc#publisher-annotation,Annotation-driven Configuration with the `@Publisher` Annotation>> for more information.
See xref:message-publishing.adoc#publisher-annotation[Annotation-driven Configuration with the `@Publisher` Annotation] for more information.
[[x5.1-files]]
==== Files Changes
== Files Changes
If you are using `FileExistsMode.APPEND` or `FileExistsMode.APPEND_NO_FLUSH` you can provide a `newFileCallback` that will be called when creating a new file.
This callback receives the newly created file and the message that triggered the callback.
@@ -129,23 +129,23 @@ This could be used to write a CSV header, for an example.
The `FileReadingMessageSource` now doesn't check and create a directory until its `start()` is called.
So, if an Inbound Channel Adapter for the `FileReadingMessageSource` has `autoStartup = false`, there are no failures against the file system during application start up.
See <<./file.adoc#files,File Support>> for more information.
See xref:file.adoc[File Support] for more information.
[[x5.1-amqp]]
==== AMQP Changes
== AMQP Changes
We have made `ID` and `Timestamp` header mapping changes in the `DefaultAmqpHeaderMapper`.
See the note near the bottom of <<./amqp.adoc#amqp-message-headers,AMQP Message Headers>> for more information.
See the note near the bottom of xref:amqp/message-headers.adoc[AMQP Message Headers] for more information.
The `contentType` header is now correctly mapped as an entry in the general headers map.
See <<./amqp.adoc#amqp-content-type,contentType Header>> for more information.
See xref:amqp/message-headers.adoc#amqp-content-type[contentType Header] for more information.
Starting with version 5.1.3, if a message conversion exception occurs when using manual acknowledgments, and an error channel is defined, the payload is a `ManualAckListenerExecutionFailedException` with additional `channel` and `deliveryTag` properties.
This enables the error flow to ack/nack the original message.
See <<./amqp.adoc#amqp-conversion-inbound,Inbound Message Conversion>> for more information.
See xref:amqp/conversion-inbound.adoc[Inbound Message Conversion] for more information.
[[x5.1-jdbc]]
==== JDBC Changes
== JDBC Changes
A confusing `max-rows-per-poll` property on the JDBC Inbound Channel Adapter and JDBC Outbound Gateway has been deprecated in favor of the newly introduced `max-rows` property.
@@ -154,61 +154,61 @@ The `JdbcMessageHandler` supports now a `batchUpdate` functionality when the pay
The indexes for the `INT_CHANNEL_MESSAGE` table (for the `JdbcChannelMessageStore`) have been optimized.
If you have large message groups in such a store, you may wish to alter the indexes.
See <<./jdbc.adoc#jdbc,JDBC Support>> for more information.
See xref:jdbc.adoc[JDBC Support] for more information.
[[x5.1-ftp-sftp]]
==== FTP and SFTP Changes
== FTP and SFTP Changes
A `RotatingServerAdvice` is now available to poll multiple servers and directories with the inbound channel adapters.
See <<./ftp.adoc#ftp-rotating-server-advice,Inbound Channel Adapters: Polling Multiple Servers and Directories>> and <<./sftp.adoc#sftp-rotating-server-advice,Inbound Channel Adapters: Polling Multiple Servers and Directories>> for more information.
See xref:ftp/rotating-server-advice.adoc[Inbound Channel Adapters: Polling Multiple Servers and Directories] and xref:sftp/rotating-server-advice.adoc[Inbound Channel Adapters: Polling Multiple Servers and Directories] for more information.
Also, inbound adapter `localFilenameExpression` instances can contain the `#remoteDirectory` variable, which contains the remote directory being polled.
The generic type of the comparators (used to sort the fetched file list for the streaming adapters) has changed from `Comparator<AbstractFileInfo<F>>` to `Comparator<F>`.
See <<./ftp.adoc#ftp-streaming,FTP Streaming Inbound Channel Adapter>> and <<./sftp.adoc#sftp-streaming,SFTP Streaming Inbound Channel Adapter>> for more information.
See xref:ftp/streaming.adoc[FTP Streaming Inbound Channel Adapter] and xref:sftp/streaming.adoc[SFTP Streaming Inbound Channel Adapter] for more information.
In addition, the synchronizers for inbound channel adapters can now be provided with a `Comparator`.
This is useful when using `maxFetchSize` to limit the files retrieved.
The `CachingSessionFactory` has a new property `testSession` which, when true, causes the factory to perform a `test()` operation on the `Session` when checking out an existing session from the cache.
See <<./sftp.adoc#sftp-session-caching,SFTP Session Caching>> and <<./ftp.adoc#ftp-session-caching,FTP Session Caching>> for more information.
See xref:sftp/session-caching.adoc[SFTP Session Caching] and xref:ftp/session-caching.adoc[FTP Session Caching] for more information.
The outbound gateway MPUT command now supports a message payload with a collection of files or strings.
See <<./sftp.adoc#sftp-outbound-gateway,SFTP Outbound Gateway>> and <<./ftp.adoc#ftp-outbound-gateway,FTP Outbound Gateway>> for more information.
See xref:sftp/outbound-gateway.adoc[SFTP Outbound Gateway] and xref:ftp/outbound-gateway.adoc[FTP Outbound Gateway] for more information.
[[x51.-tcp]]
==== TCP Support
== TCP Support
When using SSL, host verification is now enabled, by default, to prevent man-in-the-middle attacks with a trusted certificate.
See <<./ip.adoc#tcp-ssl-host-verification,Host Verification>> for more information.
See xref:ip/ssl-tls.adoc#tcp-ssl-host-verification[Host Verification] for more information.
In addition the key and trust store types can now be configured on the `DefaultTcpSSLContextSupport`.
[[x5.1-twitter]]
==== Twitter Support
== Twitter Support
Since the Spring Social project has moved to https://spring.io/blog/2018/07/03/spring-social-end-of-life-announcement[end of life status], Twitter support in Spring Integration has been moved to the Extensions project.
See https://github.com/spring-projects/spring-integration-extensions/tree/main/spring-integration-social-twitter[Spring Integration Social Twitter] for more information.
[[x51.-jms]]
==== JMS Support
== JMS Support
The `JmsSendingMessageHandler` now provides `deliveryModeExpression` and `timeToLiveExpression` options to determine respective QoS options for JMS message to send at runtime.
The `DefaultJmsHeaderMapper` now allows to map inbound `JMSDeliveryMode` and `JMSExpiration` properties via setting to `true` respective `setMapInboundDeliveryMode()` and `setMapInboundExpiration()` options.
When a `JmsMessageDrivenEndpoint` or `JmsInboundGateway` is stopped, the associated listener container is now shut down; this closes its shared connection and any consumers.
You can configure the endpoints to revert to the previous behavior.
See <<./jms.adoc#jms,JMS Support>> for more information.
See xref:jms.adoc[JMS Support] for more information.
[[x51.-http]]
==== HTTP/WebFlux Support
== HTTP/WebFlux Support
The `statusCodeExpression` (and `Function`) is now supplied with the `RequestEntity<?>` as a root object for evaluation context, so request headers, method, URI and body are available for target status code calculation.
See <<./http.adoc#http,HTTP Support>> and <<./webflux.adoc#webflux,WebFlux Support>> for more information.
See xref:http.adoc[HTTP Support] and xref:webflux.adoc[WebFlux Support] for more information.
[[x51.-jmx]]
==== JMX Changes
== JMX Changes
Object name key values are now quoted if they contain any characters other than those allowed in a Java identifier (or period `.`).
For example `org.springframework.integration:type=MessageChannel,` `name="input:foo.myGroup.errors"`.
@@ -216,25 +216,25 @@ This has the side effect that previously "allowed" names, with such characters,
For example `org.springframework.integration:type=MessageChannel,` `name="input#foo.myGroup.errors"`.
[[x51.-micrometer]]
==== Micrometer Support Changes
== Micrometer Support Changes
It is now simpler to customize the standard Micrometer meters created by the framework.
See <<./metrics.adoc#micrometer-integration,Micrometer Integration>> for more information.
See xref:metrics.adoc#micrometer-integration[Micrometer Integration] for more information.
[[x51.-integration-graph]]
==== Integration Graph Customization
== Integration Graph Customization
It is now possible to add additional properties to the `IntegrationNode` s via `Function<NamedComponent, Map<String, Object>> additionalPropertiesCallback` on the `IntegrationGraphServer`.
See <<./graph.adoc#integration-graph,Integration Graph>> for more information.
See xref:graph.adoc#integration-graph[Integration Graph] for more information.
[[x51.-global-properties]]
==== Integration Global Properties
== Integration Global Properties
The Integration global properties (including defaults) can now be printed in the logs, when a `DEBUG` logic level is turned on for the `org.springframework.integration` category.
See <<./configuration.adoc#global-properties,Global Properties>> for more information.
See xref:configuration/global-properties.adoc[Global Properties] for more information.
[[x51.-poller-annotation]]
==== The `receiveTimeout` for `@Poller`
== The `receiveTimeout` for `@Poller`
The `@Poller` annotation now provides a `receiveTimeout` option for convenience.
See <<./configuration.adoc#configuration-using-poller-annotation,Using the `@Poller` Annotation>> for more information.
See xref:configuration/annotations.adoc#configuration-using-poller-annotation[Using the `@Poller` Annotation] for more information.

View File

@@ -1,154 +1,154 @@
[[migration-5.1-5.2]]
=== Changes between 5.1 and 5.2
= Changes between 5.1 and 5.2
[[x5.2-package-class]]
=== Package and Class Changes
== Package and Class Changes
`Pausable` has been moved from `o.s.i.endpoint` to `o.s.i.core`.
[[x5.2-behavior]]
=== Behavior Changes
== Behavior Changes
See the https://github.com/spring-projects/spring-integration/wiki/Spring-Integration-5.1-to-5.2-Migration-Guide[Migration Guide] about behavior changes in this version.
[[x5.2-new-components]]
=== New Components
== New Components
[[x5.2-rsocket-support]]
==== RSocket Support
=== RSocket Support
The `spring-integration-rsocket` module is now available with channel adapter implementations for RSocket protocol support.
See <<./rsocket.adoc#rsocket,RSocket Support>> for more information.
See xref:rsocket.adoc[RSocket Support] for more information.
[[x5.2-rate-limit-advice]]
==== Rate Limit Advice Support
=== Rate Limit Advice Support
The `RateLimiterRequestHandlerAdvice` is now available for limiting requests rate on handlers.
See <<./handler-advice.adoc#rate-limiter-advice,Rate Limiter Advice>> for more information.
See xref:handler-advice/classes.adoc#rate-limiter-advice[Rate Limiter Advice] for more information.
[[x5.2-cache-advice]]
==== Caching Advice Support
=== Caching Advice Support
The `CacheRequestHandlerAdvice` is now available for caching request results on handlers.
See <<./handler-advice.adoc#cache-advice,Caching Advice>> for more information.
See xref:handler-advice/classes.adoc#cache-advice[Caching Advice] for more information.
[[x5.2-kotlin-scripts]]
==== Kotlin Scripts Support
=== Kotlin Scripts Support
The JSR223 scripting module now includes a support for Kotlin scripts.
See <<./scripting.adoc#scripting,Scripting Support>> for more information.
See xref:scripting.adoc[Scripting Support] for more information.
[[x5.2-flux-aggregator]]
==== Flux Aggregator Support
=== Flux Aggregator Support
The `FluxAggregatorMessageHandler` is now available for grouping and windowing messages logic based on the Project Reactor `Flux` operators.
See <<./aggregator.adoc#flux-aggregator,Flux Aggregator>> for more information.
See xref:aggregator.adoc#flux-aggregator[Flux Aggregator] for more information.
[[x5.2-sftp-events]]
==== FTP/SFTP Event Publisher
=== FTP/SFTP Event Publisher
The FTP and SFTP modules now provide an event listener for certain Apache Mina FTP/SFTP server events.
See <<./ftp.adoc#ftp-server-events, Apache Mina FTP Server Events>> and <<./sftp.adoc#sftp-server-events, Apache Mina SFTP Server Events>> for more information.
See xref:ftp/server-events.adoc[Apache Mina FTP Server Events] and xref:sftp/server-events.adoc[Apache Mina SFTP Server Events] for more information.
[[x5.2-avro]]
==== Avro Transformers
=== Avro Transformers
Simple Apache Avro transformers are now provided.
See <<./transformers.adoc#avro-transformers, Avro Transformers>> for more information.
See xref:changes-5.1-5.2.adoc#x5.2-avro[Avro Transformers] for more information.
[[x5.2-general]]
=== General Changes
== General Changes
The `JsonToObjectTransformer` now supports generics for the target object to deserialize into.
See <<./transformer.adoc#json-transformers,JSON Transformers>> for more information.
See xref:transformer.adoc#json-transformers[JSON Transformers] for more information.
The `splitter` now supports a `discardChannel` configuration option.
See <<./splitter.adoc#splitter,Splitter>> for more information.
See xref:splitter.adoc[Splitter] for more information.
The Control Bus can now handle `Pausable` (extension of `Lifecycle`) operations.
See <<./control-bus.adoc#control-bus,Control Bus>> for more information.
See xref:groovy.adoc#groovy-control-bus[Control Bus] for more information.
The `Function<MessageGroup, Map<String, Object>>` strategy has been introduced for the aggregator component to merge and compute headers for output messages.
See <<./aggregator.adoc#aggregator-api,Aggregator Programming Model>> for more information.
See xref:aggregator.adoc#aggregator-api[Aggregator Programming Model] for more information.
All the `MessageHandlingException` s thrown in the framework, includes now a bean resource and source for back tracking a configuration part in case no end-user code involved.
See <<./error-handling.adoc#error-handling,Error Handling>> for more information.
See xref:scatter-gather.adoc#scatter-gather-error-handling[Error Handling] for more information.
For better end-user experience, Java DSL now provides a configurer variant for starting flow with a gateway interface.
See `IntegrationFlows.from(Class<?> serviceInterface, Consumer<GatewayProxySpec> endpointConfigurer)` JavaDocs for more information.
Also a `MethodArgsHolder` is now a root object for evaluation context for all the expressions in the `GatewayProxyFactoryBean`.
The `#args` and `#method` evaluation context variables are now deprecated.
See <<./gateway.adoc#gateway,Messaging Gateways>> for more information.
See xref:gateway.adoc[Messaging Gateways] for more information.
[[x5.2-amqp]]
==== AMQP Changes
=== AMQP Changes
The outbound endpoints can now be configured to synthesize a "nack" if no publisher confirm is received within a timeout.
See <<./amqp.adoc#amqp-outbound-endpoints,Outbound Channel Adapter>> for more information.
See xref:changes-4.0-4.1.adoc#x4.1-amqp-outbound-lazy-connect[Outbound Channel Adapter] for more information.
The inbound channel adapter can now receive batched messages as a `List<?>` payload instead of receiving a discrete message for each batch fragment.
See <<./amqp.adoc#amqp-debatching,Batched Messages>> for more information.
See xref:amqp/inbound-channel-adapter.adoc#amqp-debatching[Batched Messages] for more information.
The outbound channel adapter can now be configured to block the calling thread until a publisher confirm (acknowledgment) is received.
See <<./amqp.adoc#amqp-outbound-channel-adapter,Outbound Channel Adapter>> for more information.
See xref:amqp/outbound-channel-adapter.adoc[Outbound Channel Adapter] for more information.
[[x5.2-file]]
==== File Changes
=== File Changes
Some improvements to filtering remote files have been made.
See <<./file.adoc#remote-persistent-flf,Remote Persistent File List Filters>> for more information.
See xref:file/remote-persistent-flf.adoc[Remote Persistent File List Filters] for more information.
[[x5.2-tcp]]
==== TCP Changes
=== TCP Changes
The length header used by the `ByteArrayLengthHeaderSerializer` can now include the length of the header in addition to the payload.
See <<./ip.adoc#tcp-codecs,Message Demarcation (Serializers and Deserializers)>> for more information.
See xref:ip/tcp-connection-factories.adoc#tcp-codecs[Message Demarcation (Serializers and Deserializers)] for more information.
When using a `TcpNioServerConnectionFactory`, priority is now given to accepting new connections over reading from existing connections, but it is configurable.
See <<./ip.adoc#note-nio,About Non-blocking I/O (NIO)>> for more information.
See xref:ip/note-nio.adoc[About Non-blocking I/O (NIO)] for more information.
The outbound gateway has a new property `closeStreamAfterSend`; when used with a new connection for each request/reply it signals EOF to the server, without closing the connection.
This is useful for servers that use the EOF to signal end of message instead of some delimiter in the data.
See <<./ip.adoc#tcp-gateways, TCP Gateways>> for more information.
See xref:ip/tcp-gateways.adoc[TCP Gateways] for more information.
The client connection factories now support `connectTimeout` which causes an exception to be thrown if the connection is not established in that time.
See <<./ip.adoc#tcp-connection-factory, TCP Connection Factories>> for more information.
See xref:ip.adoc#tcp-connection-factory[ TCP Connection Factories] for more information.
`SoftEndOfStreamException` is now a `RuntimeException` instead of extending `IOException`.
[[x5.2-mail]]
==== Mail Changes
=== Mail Changes
The `AbstractMailReceiver` has now an `autoCloseFolder` option (`true` by default), to disable an automatic folder close after a fetch, but populate `IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE` header instead for downstream interaction.
See <<./mail.adoc#mail-inbound,Mail-receiving Channel Adapter>> for more information.
See xref:mail.adoc#mail-inbound[Mail-receiving Channel Adapter] for more information.
[[x5.2-http]]
==== HTTP Changes
=== HTTP Changes
The HTTP inbound endpoint now support a request payload validation.
See <<./http.adoc#http,HTTP Support>> for more information.
See xref:http.adoc[HTTP Support] for more information.
[[x5.2-webflux]]
==== WebFlux Changes
=== WebFlux Changes
The `WebFluxRequestExecutingMessageHandler` now supports a `Publisher`, `Resource` and `MultiValueMap` as a request message `payload`.
The `WebFluxInboundEndpoint` now supports a request payload validation.
See <<./webflux.adoc#webflux,WebFlux Support>> for more information.
See xref:webflux.adoc[WebFlux Support] for more information.
[[x5.2-mongodb]]
==== MongoDb Changes
=== MongoDb Changes
The `MongoDbMessageStore` can now be configured with custom converters.
See <<./mongodb.adoc#mongodb, MongoDB Support>> for more information.
See xref:mongodb.adoc[MongoDB Support] for more information.
[[x5.2-routers]]
==== Router Changes
=== Router Changes
You can now disable falling back to the channel key as the channel bean name.
See <<./router.adoc#dynamic-routers, Dynamic Routers>> for more information.
See xref:router/dynamic-routers.adoc[Dynamic Routers] for more information.
[[x5.2--ftp-sftp]]
==== FTP/SFTP Changes
=== FTP/SFTP Changes
The `RotatingServerAdvice` is decoupled now from the `RotationPolicy` and its `StandardRotationPolicy`.
@@ -156,4 +156,4 @@ The remote file information, including host/port and directory are included now
Also this information is included into headers in the read operations results of the `AbstractRemoteFileOutboundGateway` implementations.
The FTP outbound endpoints now support `chmod` to change permissions on the uploaded file.
(SFTP already supported it since version 4.3).
See <<./ftp.adoc#ftp, FTP(S) Support>> and <<./sftp.adoc#sftp, SFTP Support>> for more information.
See xref:ftp.adoc[FTP(S) Support] and xref:sftp.adoc[SFTP Support] for more information.

View File

@@ -1,162 +1,162 @@
[[migration-5.2-5.3]]
=== Changes between 5.2 and 5.3
= Changes between 5.2 and 5.3
[[x5.3-new-components]]
=== New Components
== New Components
[[x5.3-integration-pattern]]
==== Integration Pattern
=== Integration Pattern
The `IntegrationPattern` abstraction has been introduced to indicate which enterprise integration pattern (an `IntegrationPatternType`) and category a Spring Integration component belongs to.
See its JavaDocs and <<./graph.adoc#integration-graph,Integration Graph>> for more information about this abstraction and its use-cases.
See its JavaDocs and xref:graph.adoc#integration-graph[Integration Graph] for more information about this abstraction and its use-cases.
[[x5.3-reactive-message-handler]]
==== `ReactiveMessageHandler`
=== `ReactiveMessageHandler`
The `ReactiveMessageHandler` is now natively supported in the framework.
See <<./reactive-streams.adoc#reactive-message-handler,ReactiveMessageHandler>> for more information.
See xref:reactive-streams.adoc#reactive-message-handler[ReactiveMessageHandler] for more information.
[[x5.3-reactive-message-source-producer]]
==== `ReactiveMessageSourceProducer`
=== `ReactiveMessageSourceProducer`
The `ReactiveMessageSourceProducer` is a reactive implementation of the `MessageProducerSupport` to wrap a provided `MessageSource` into a `Flux` for on demand `receive()` calls.
See <<./reactive-streams.adoc#reactive-streams,Reactive Streams Support>> for more information.
See xref:reactive-streams.adoc[Reactive Streams Support] for more information.
[[x5.3-java-dsl-extensions]]
==== Java DSL Extensions
=== Java DSL Extensions
A new `IntegrationFlowExtension` API has been introduced to allow extension of the existing Java DSL with custom or composed EIP-operators.
This also can be used to introduce customizers for any out-of-the-box `IntegrationComponentSpec` extensions.
See <<./dsl.adoc#java-dsl-extensions,DSL Extensions>> for more information.
See xref:changes-5.2-5.3.adoc#x5.3-java-dsl-extensions[DSL Extensions] for more information.
[[x5.3-kotlin-dsl]]
==== Kotlin DSL
=== Kotlin DSL
The Kotlin DSL for integration flow configurations has been introduced.
See <<./kotlin-dsl.adoc#kotlin-dsl,Kotlin DSL Chapter>> for more information.
See xref:kotlin-dsl.adoc[Kotlin DSL Chapter] for more information.
[[x5.3-reactive-request-handler-advice]]
==== ReactiveRequestHandlerAdvice
=== ReactiveRequestHandlerAdvice
A `ReactiveRequestHandlerAdvice` is provided to customize `Mono` replies from message handlers.
See <<./handler-advice.adoc#reactive-advice,Reactive Advice>> for more information.
See xref:handler-advice/reactive.adoc[Reactive Advice] for more information.
[[x5.3-handle-message-advice-adapter]]
==== HandleMessageAdviceAdapter
=== HandleMessageAdviceAdapter
A `HandleMessageAdviceAdapter` is provided to wrap any `MethodInterceptor` for applying on the `MessageHandler.handleMessage()` instead of a default `AbstractReplyProducingMessageHandler.RequestHandler.handleRequestMessage()` behavior.
See <<./handler-advice.adoc#handle-message-advice,Handling Message Advice>> for more information.
See xref:handler-advice/handle-message.adoc[Handling Message Advice] for more information.
[[x5.3-mongodb-reactive-channel-adapters]]
==== MongoDB Reactive Channel Adapters
=== MongoDB Reactive Channel Adapters
The `spring-integration-mongodb` module now provides channel adapter implementations for the Reactive MongoDb driver support in Spring Data.
Also, a reactive implementation for MongoDb change stream support is present with the `MongoDbChangeStreamMessageProducer`.
See <<./mongodb.adoc#mongodb,MongoDB Support>> for more information.
See xref:mongodb.adoc[MongoDB Support] for more information.
[[x5.3-receive-message-advice]]
==== ReceiveMessageAdvice
=== ReceiveMessageAdvice
A special `ReceiveMessageAdvice` has been introduced to proxy exactly `MessageSource.receive()` or `PollableChannel.receive()`.
See <<./polling-consumer.adoc#smart-polling,Smart Polling>> for more information.
See xref:polling-consumer.adoc#smart-polling[Smart Polling] for more information.
[[x5.3-general]]
=== General Changes
== General Changes
The gateway proxy now doesn't proxy `default` methods by default.
See <<./gateway.adoc#gateway-calling-default-methods,Invoking `default` Methods>> for more information.
See xref:gateway.adoc#gateway-calling-default-methods[Invoking `default` Methods] for more information.
Internal components (such as `_org.springframework.integration.errorLogger`) now have a shortened name when they are represented in the integration graph.
See <<./graph.adoc#integration-graph,Integration Graph>> for more information.
See xref:graph.adoc#integration-graph[Integration Graph] for more information.
In the aggregator, when the `MessageGroupProcessor` returns a `Message`, the `MessageBuilder.popSequenceDetails()` is performed on the output message if the `sequenceDetails` matches the header in the first message of the group.
See <<./aggregator.adoc#aggregator-api,Aggregator Programming Model>> for more information.
See xref:aggregator.adoc#aggregator-api[Aggregator Programming Model] for more information.
A new `publishSubscribeChannel()` operator, based on the `BroadcastCapableChannel` and `BroadcastPublishSubscribeSpec`, was added into Java DSL.
This fluent API has its advantage when we configure sub-flows as pub-sub subscribers for broker-backed channels like `SubscribableJmsChannel`, `SubscribableRedisChannel` etc.
See <<./dsl.adoc#java-dsl-subflows,Sub-flows support>> for more information.
See xref:dsl/java-subflows.adoc[Sub-flows support] for more information.
Transactional support in Spring Integration now also includes options to configure a `ReactiveTransactionManager` if a `MessageSource` or `MessageHandler` implementation produces a reactive type for payload to send.
See `TransactionInterceptorBuilder` for more information.
See also <<./transactions.adoc#reactive-transactions,Reactive Transactions>>.
See also xref:transactions.adoc#reactive-transactions[Reactive Transactions].
A new `intercept()` operator to register `ChannelInterceptor` instances without creating explicit channels was added into Java DSL.
See <<./dsl.adoc#java-dsl-intercept,Operator intercept()>> for more information.
See xref:dsl/java-intercept.adoc[Operator intercept()] for more information.
The `MessageStoreSelector` has a new mechanism to compare an old and new value.
See <<./handler-advice.adoc#idempotent-receiver,Idempotent Receiver Enterprise Integration Pattern>> for more information.
See xref:handler-advice/idempotent-receiver.adoc[Idempotent Receiver Enterprise Integration Pattern] for more information.
The `MessageProducerSupport` base class now has a `subscribeToPublisher(Publisher<? extends Message<?>>)` API to allow implementation of message-driven producer endpoints which emit messages via reactive `Publisher`.
See <<./reactive-streams.adoc#reactive-streams,Reactive Streams Support>> for more information.
See xref:reactive-streams.adoc[Reactive Streams Support] for more information.
[[x5.3-amqp]]
=== AMQP Changes
== AMQP Changes
The outbound channel adapter has a new property `multiSend` allowing multiple messages to be sent within the scope of one `RabbitTemplate` invocation.
See <<./amqp.adoc#amqp-outbound-channel-adapter,AMQP Outbound Channel Adapter>> for more information.
See xref:amqp/outbound-channel-adapter.adoc[AMQP Outbound Channel Adapter] for more information.
The inbound channel adapter now supports a listener container with the `consumerBatchEnabled` property set to `true`.
See <<./amqp.adoc#amqp-inbound-channel-adapter,AMQP Inbound Channel Adapter>>
See xref:amqp/inbound-channel-adapter.adoc[AMQP Inbound Channel Adapter]
[[x5.3-http]]
=== HTTP Changes
== HTTP Changes
The `encodeUri` property on the `AbstractHttpRequestExecutingMessageHandler` has been deprecated in favor of newly introduced `encodingMode`.
See `DefaultUriBuilderFactory.EncodingMode` JavaDocs and <<./http.adoc#http-uri-encoding,Controlling URI Encoding>> for more information.
See `DefaultUriBuilderFactory.EncodingMode` JavaDocs and xref:http/namespace.adoc#http-uri-encoding[Controlling URI Encoding] for more information.
This also affects `WebFluxRequestExecutingMessageHandler`, respective Java DSL and XML configuration.
The same option is added into an `AbstractWebServiceOutboundGateway`.
[[x5.3-ws]]
=== Web Services Changes
== Web Services Changes
Java DSL support has been added for Web Service components.
The `encodeUri` property on the `AbstractWebServiceOutboundGateway` has been deprecated in favor of newly introduced `encodingMode` - similar to HTTP changes above.
See <<./ws.adoc#ws,Web Services Support>> for more information.
See xref:ws.adoc[Web Services Support] for more information.
[[x5.3-tcp]]
=== TCP Changes
== TCP Changes
The `FailoverClientConnectionFactory` no longer fails back, by default, until the current connection fails.
See <<./ip.adoc#failover-cf,TCP Failover Client Connection Factory>> for more information.
See xref:ip/tcp-connection-factories.adoc#failover-cf[TCP Failover Client Connection Factory] for more information.
The `TcpOutboundGateway` now supports asynchronous request/reply.
See <<./ip.adoc#tcp-gateways,TCP Gateways>> for more information.
See xref:ip/tcp-gateways.adoc[TCP Gateways] for more information.
You can now configure client connections to perform some arbitrary test on new connections.
See <<./ip.adoc#testing-connections,Testing Connections>> for more information.
See xref:ip/testing-connections.adoc[Testing Connections] for more information.
[[x5.3-rsocket]]
=== RSocket Changes
== RSocket Changes
A `decodeFluxAsUnit` option has been added to the `RSocketInboundGateway` with the meaning to decode incoming `Flux` as a single unit or apply decoding for each event in it.
See <<./rsocket.adoc#rsocket-inbound,RSocket Inbound Gateway>> for more information.
See xref:rsocket.adoc#rsocket-inbound[RSocket Inbound Gateway] for more information.
[[x5.3-zookeeper]]
=== Zookeeper Changes
== Zookeeper Changes
A `LeaderInitiatorFactoryBean` (as well as its XML `<int-zk:leader-listener>`) exposes a `candidate` option for more control over a `Candidate` configuration.
See <<./zookeeper.adoc#zk-leadership,Leadership event handling>> for more information.
See xref:zookeeper.adoc#zk-leadership[Leadership event handling] for more information.
[[x5.3-mqtt]]
=== MQTT Changes
== MQTT Changes
The inbound channel adapter can now be configured to provide user control over when a message is acknowledged as being delivered.
See <<./mqtt.adoc#mqtt-ack-mode,Manual Acks>> for more information.
See xref:mqtt.adoc#mqtt-ack-mode[Manual Acks] for more information.
The outbound adapter now publishes a `MqttConnectionFailedEvent` when a connection can't be created, or is lost.
Previously, only the inbound adapter did so.
See <<./mqtt.adoc#mqtt-events,MQTT Events>>.
See xref:mqtt.adoc#mqtt-events[MQTT Events].
[[x5.3-sftp]]
=== (S)FTP Changes
== (S)FTP Changes
The `FileTransferringMessageHandler` (for FTP and SFTP, for example) in addition to `File`, `byte[]`, `String` and `InputStream` now also supports an `org.springframework.core.io.Resource`.
See <<./sftp.adoc#sftp,SFTP Support>> and <<./ftp.adoc#ftp,FTP Support>> for more information.
See xref:sftp.adoc[SFTP Support] and xref:ftp.adoc[FTP Support] for more information.
[[x5.3-file]]
=== File Changes
== File Changes
The `FileSplitter` doesn't require a Jackson processor (or similar) dependency any more for the `markersJson` mode.
It uses a `SimpleJsonSerializer` for a straightforward string representation of the `FileSplitter.FileMarker` instances.
See <<./file.adoc#file-splitter,FileSplitter>> for more information.
See xref:file/splitter.adoc[FileSplitter] for more information.

View File

@@ -1,82 +1,82 @@
[[migration-5.3-5.4]]
=== Changes between 5.3 and 5.4
= Changes between 5.3 and 5.4
[[x5.4-new-components]]
=== New Components
== New Components
[[x5.4-sik]]
==== Channel Adapters for Apache Kafka
== Channel Adapters for Apache Kafka
The standalone https://projects.spring.io/spring-integration-kafka/[Spring Integration for Apache Kafka] project has been merged as a `spring-integration-kafka` module to this project.
The `KafkaProducerMessageHandler` `sendTimeoutExpression` default has changed.
You can now access the `Future<?>` for underlying `send()` operations.
See <<./kafka.adoc#kafka,Spring for Apache Kafka Support>> for more information.
See xref:kafka.adoc[Spring for Apache Kafka Support] for more information.
[[x5.4-r2dbc]]
==== R2DBC Channel Adapters
== R2DBC Channel Adapters
The Channel Adapters for R2DBC database interaction have been introduced.
See <<./r2dbc.adoc#r2dbc,R2DBC Support>> for more information.
See xref:r2dbc.adoc[R2DBC Support] for more information.
[[x5.4-redis-stream]]
==== Redis Stream Support
== Redis Stream Support
The Channel Adapters for Redis Stream support have been introduced.
See <<./redis.adoc#redis-stream-outbound,Redis Stream Outbound Channel Adapter>> for more information.
See xref:redis.adoc#redis-stream-outbound[Redis Stream Outbound Channel Adapter] for more information.
[[x5.4-renewable-lock]]
==== Renewable Lock Registry
== Renewable Lock Registry
A Renewable lock registry has been introduced to allow renew lease of a distributed lock.
See <<./jdbc.adoc#jdbc-lock-registry,JDBC implementation>> for more information.
See xref:jdbc.adoc#jdbc-lock-registry[JDBC implementation] for more information.
[[x5.4-zeromq]]
==== ZeroMQ Support
== ZeroMQ Support
`ZeroMqChannel`, `ZeroMqMessageHandler` and `ZeroMqMessageProducer` have been introduced.
See <<./zeromq.adoc#zeromq,ZeroMQ Support>> for more information.
See xref:zeromq.adoc[ZeroMQ Support] for more information.
[[x5.4-general]]
=== General Changes
== General Changes
The one-way messaging gateway (the `void` method return type) now sets a `nullChannel` explicitly into the `replyChannel` header to ignore any possible downstream replies.
See <<./gateway.adoc#gateway-default-reply-channel,Setting the Default Reply Channel>> for more information.
See xref:gateway.adoc#gateway-default-reply-channel[Setting the Default Reply Channel] for more information.
Also the gateway method invokers (`GatewayProxyFactoryBean.MethodInvocationGateway`) are now supplied with the managed bean name as a combination of gateway proxy bean name plus method signature.
For example: `sampleGateway#echo(String)`.
This effects message history and metrics exposed for the gateway method calls and also give fine-grained logs during start and close of application context.
The aggregator (and resequencer) can now expire orphaned groups (groups in a persistent store where no new messages arrive after an application restart).
See <<./aggregator.adoc#aggregator-expiring-groups, Aggregator Expiring Groups>> for more information.
See xref:aggregator.adoc#aggregator-expiring-groups[Aggregator Expiring Groups] for more information.
The legacy metrics that were replaced by Micrometer meters have been removed.
The <<./barrier.adoc#barrier,Thread Barrier>> has now two separate timeout options: `requestTimeout` and `triggerTimeout`.
The xref:barrier.adoc[Thread Barrier] has now two separate timeout options: `requestTimeout` and `triggerTimeout`.
[[x5.4-tcp]]
=== TCP/UDP Changes
== TCP/UDP Changes
Connection factories now support multiple sending components (`TcpSender`); they remain limited to one receiving component (`TcpListener`).
This allows, for example, an inbound gateway and outbound channel adapter to share the same factory, supporting both request/reply and arbitrary messaging from the server to the client.
Shared factories should not be used with outbound gateways, unless single-use connections or the `ThreadAffinityClientConnectionFactory` are being used.
See <<./ip.adoc#ip-collaborating-adapters,Collaborating Channel Adapters>> and <<./ip.adoc#tcp-gateways, TCP Gateways>> for more information.
See xref:ip/correlation.adoc#ip-collaborating-adapters[Collaborating Channel Adapters] and xref:ip/tcp-gateways.adoc[TCP Gateways] for more information.
The UDP channel adapters can now be configured with a `SocketCustomizer` which allows the setting of socket properties that are not directly supported by the adapters.
See <<./ip.adoc#udp-adapters,UDP Adapters>> for more information.
See xref:ip/udp-adapters.adoc[UDP Adapters] for more information.
[[x5.4-amqp]]
=== AMQP Changes
== AMQP Changes
The outbound endpoints now have a new mechanism for handling publisher confirms and returns.
See <<./amqp.adoc#alternative-confirms-returns,Alternative Mechanism for Publisher Confirms and Returns>> for more information.
See xref:amqp/alternative-confirms-returns.adoc[Alternative Mechanism for Publisher Confirms and Returns] for more information.
A new `BatchMode.EXTRACT_PAYLOAD_WITH_HEADERS` is supported by the `AmqpInboundChannelAdapter`.
See <<./amqp.adoc#amqp-inbound-channel-adapter,Inbound Channel Adapter>> for more information.
See xref:amqp/inbound-channel-adapter.adoc[Inbound Channel Adapter] for more information.
[[x5.4-mail]]
=== Mail Changes
== Mail Changes
The `AbstractMailReceiver` can now produce the `MimeMessage` as-is without eager fetching its content.
See <<./mail.adoc#mail-inbound, Mail-receiving Channel Adapter>> for more information.
See xref:mail.adoc#mail-inbound[Mail-receiving Channel Adapter] for more information.

View File

@@ -1,76 +1,76 @@
[[migration-5.4-5.5]]
=== Changes between 5.4 and 5.5
= Changes between 5.4 and 5.5
[[x5.5-new-components]]
=== New Components
== New Components
[[x5.5-file-aggregator]]
==== File Aggregator
== File Aggregator
A `FileSplitter.FileMaker`-based implementation of `CorrelationStrategy`, `ReleaseStrategy` and `MessageGroupProcessor` as a `FileAggregator` component was introduced.
See <<./file.adoc#file-aggregator, File Aggregator>> for more information.
See xref:file/aggregator.adoc[File Aggregator] for more information.
[[x5.5-mqtt-v5]]
==== MQTT v5 Support
== MQTT v5 Support
The `Mqttv5PahoMessageDrivenChannelAdapter` and `Mqttv5PahoMessageHandler` (including respective `MqttHeaderMapper`) were introduced to support MQTT v5 protocol communication.
See <<./mqtt.adoc#mqtt-v5, MQTT v5 Support>> for more information.
See xref:mqtt.adoc#mqtt-v5[MQTT v5 Support] for more information.
[[x5.5-general]]
=== General Changes
== General Changes
All the persistent `MessageGroupStore` implementation provide a `streamMessagesForGroup(Object groupId)` contract based on the target database streaming API.
See <<./message-store.adoc#message-store,Message Store>> for more information.
See xref:message-store.adoc[Message Store] for more information.
The `integrationGlobalProperties` bean (if declared) must be now an instance of `org.springframework.integration.context.IntegrationProperties` instead of `java.util.Properties`, which support is deprecated for backward compatibility.
The `spring.integration.channels.error.requireSubscribers=true` global property is added to indicate that the global default `errorChannel` must be configured with the `requireSubscribers` option (or not).
The `spring.integration.channels.error.ignoreFailures=true` global property is added to indicate that the global default `errorChannel` must ignore (or not) dispatching errors and pass the message to the next handler.
See <<./configuration.adoc#global-properties,Global Properties>> for more information.
See xref:configuration/global-properties.adoc[Global Properties] for more information.
An `AbstractPollingEndpoint` (source polling channel adapter and polling consumer) treats `maxMessagesPerPoll == 0` as to skip calling the source.
It can be changed to different value later on, e.g. via a Control Bus.
See <<./endpoint.adoc#endpoint-pollingconsumer,Polling Consumer>> for more information.
See xref:endpoint.adoc#endpoint-pollingconsumer[Polling Consumer] for more information.
The `ConsumerEndpointFactoryBean` now accept a `reactiveCustomizer` `Function` to any input channel as reactive stream source and use a `ReactiveStreamsConsumer` underneath.
This is covered as a `ConsumerEndpointSpec.reactive()` option in Java DSL and as a `@Reactive` nested annotation for the messaging annotations.
See <<./reactive-streams.adoc#reactive-streams,Reactive Streams Support>> for more information.
See xref:reactive-streams.adoc[Reactive Streams Support] for more information.
The `groupTimeoutExpression` for a correlation message handler (an `Aggregator` and `Resequencer`) can now be evaluated to a `java.util.Date` for some fine-grained scheduling use-cases.
Also the `BiFunction groupConditionSupplier` option is added to the `AbstractCorrelatingMessageHandler` to supply a `MessageGroup` condition against a message to be added to the group.
See <<./aggregator.adoc#aggregator,Aggregator>> for more information.
See xref:overview.adoc#overview-endpoints-aggregator[Aggregator] for more information.
The `MessageGroup` abstraction can be supplied with a `condition` to evaluate later on to make a decision for the group.
See <<./message-store.adoc#message-group-condition,Message Group Condition>> for more information.
See xref:message-store.adoc#message-group-condition[Message Group Condition] for more information.
[[x5.5-integration-flows-composition]]
==== Integration Flows Composition
== Integration Flows Composition
The new `IntegrationFlows.from(IntegrationFlow)` factory method has been added to allow starting the current `IntegrationFlow` from the output of an existing flow.
In addition, the `IntegrationFlowDefinition` has added a `to(IntegrationFlow)` terminal operator to continue the current flow at the input channel of some other flow.
See <<./dsl.adoc#integration-flows-composition,Integration Flows Composition>> for more information.
See xref:dsl/integration-flows-composition.adoc[Integration Flows Composition] for more information.
[[x5.5-amqp]]
==== AMQP Changes
== AMQP Changes
The `AmqpInboundChannelAdapter` and `AmqpInboundGateway` (and the respective Java DSL builders) now support an `org.springframework.amqp.rabbit.retry.MessageRecoverer` as an AMQP-specific alternative to the general purpose `RecoveryCallback`.
See <<./amqp.adoc#amqp,AMQP Support>> for more information.
See xref:amqp.adoc[AMQP Support] for more information.
[[x5.5-redis]]
==== Redis Changes
== Redis Changes
The `ReactiveRedisStreamMessageProducer` has now setters for all the `StreamReceiver.StreamReceiverOptionsBuilder` options, including an `onErrorResume` function.
See <<./redis.adoc#redis,Redis Support>> for more information.
See xref:redis.adoc[Redis Support] for more information.
[[x5.5-http]]
==== HTTP Changes
== HTTP Changes
The `HttpRequestExecutingMessageHandler` doesn't fallback to the `application/x-java-serialized-object` content type any more and lets the `RestTemplate` make the final decision for the request body conversion based on the `HttpMessageConverter` provided.
It also has now an `extractResponseBody` flag (which is `true` by default) to return just the response body, or to return the whole `ResponseEntity` as the reply message payload, independently of the provided `expectedResponseType`.
Same option is presented for the `WebFluxRequestExecutingMessageHandler`, too.
See <<./http.adoc#http,HTTP Support>> for more information.
See xref:http.adoc[HTTP Support] for more information.
[[x5.5-file]]
==== File/FTP/SFTP Changes
== File/FTP/SFTP Changes
The persistent file list filters now have a boolean property `forRecursion`.
Setting this property to `true`, also sets `alwaysAcceptDirectories`, which means that the recursive operation on the outbound gateways (`ls` and `mget`) will now always traverse the full directory tree each time.
@@ -84,30 +84,30 @@ The `FileInboundChannelAdapterSpec` has now a convenient `recursive(boolean)` op
The `remoteDirectoryExpression` can now be used in the `mv` command for convenience.
[[x5.5-mongodb]]
==== MongoDb Changes
== MongoDb Changes
The `MongoDbMessageSourceSpec` was added into MongoDd Java DSL.
An `update` option is now exposed on both the `MongoDbMessageSource` and `ReactiveMongoDbMessageSource` implementations.
See <<./mongodb.adoc#mongodb,MongoDb Support>> for more information.
See xref:mongodb.adoc[MongoDb Support] for more information.
[[x5.5-websocket]]
==== WebSockets Changes
== WebSockets Changes
The WebSocket channel adapters based on `ServerWebSocketContainer` can now be registered and removed at runtime.
See <<./web-sockets.adoc#web-sockets,WebSockets Support>> for more information.
See xref:web-sockets.adoc[WebSockets Support] for more information.
[[x5.5-jpa]]
==== JPA Changes
== JPA Changes
The `JpaOutboundGateway` now supports an `Iterable` message payload for a `PersistMode.DELETE`.
See <<./jpa.adoc#jpa-outbound-channel-adapter,Outbound Channel Adapter>> for more information.
See xref:jpa/outbound-channel-adapter.adoc[Outbound Channel Adapter] for more information.
[[x55-gw]]
==== Gateway Changes
== Gateway Changes
Previously, when using XML configuration, `@Gateway.payloadExpression` was ignored for no-argument methods.
There is one possible breaking change - if the method is annotated with `@Payload` as well as `@Gateway` (with a different expression) previously, the `@Payload` would be applied, now the `@Gateway.payloadExpression` is applied.
See <<./gateway.adoc#gateway-configuration-annotations,Gateway Configuration with Annotations and XML>> and <<./gateway.adoc#gateway-calling-no-argument-methods,Invoking No-Argument Methods>> for more information.
See xref:gateway.adoc#gateway-configuration-annotations[Gateway Configuration with Annotations and XML] and xref:gateway.adoc#gateway-calling-no-argument-methods[Invoking No-Argument Methods] for more information.

View File

@@ -1,121 +1,121 @@
[[migration-5.5-6.0]]
=== Changes between 5.5 and 6.0
= Changes between 5.5 and 6.0
[[x6.0-new-components]]
=== New Components
== New Components
A Groovy DSL implementation for integration flow definitions has been added.
See <<./groovy-dsl.adoc#groovy-dsl,Groovy DSL>> for more information.
See xref:groovy-dsl.adoc[Groovy DSL] for more information.
[[x6.0-mqtt]]
==== MQTT ClientManager
=== MQTT ClientManager
A new MQTT `ClientManager` has been added to support a reusable MQTT connection across different channel adapters.
See <<./mqtt.adoc#mqtt-shared-client,Shared MQTT Client Support>> for more information.
See xref:mqtt.adoc#mqtt-shared-client[Shared MQTT Client Support] for more information.
[[x6.0-graphql]]
==== GraphQL Support
=== GraphQL Support
The GraphQL support has been added.
See <<./graphql.adoc#graphql,GraphQL Support>> for more information.
See xref:graphql.adoc[GraphQL Support] for more information.
[[x6.0-camel]]
==== Apache Camel Support
=== Apache Camel Support
Support for Apache Camel routes has been introduced.
See <<./camel.adoc#camel,Apache Camel Support>> for more information.
See xref:camel.adoc[Apache Camel Support] for more information.
[[x6.0-hazelcast]]
==== Hazelcast Support
=== Hazelcast Support
The Hazelcast Spring Integration Extensions project has been migrated as the `spring-integration-hazelcast` module.
See <<./hazelcast.adoc#hazelcast,Hazelcast Support>> for more information.
See xref:hazelcast.adoc[Hazelcast Support] for more information.
[[x6.0-smb]]
==== SMB Support
=== SMB Support
SMB support has been added from the Spring Integration Extensions project.
The Java DSL (see `org.springframework.integration.smb.dsl.Smb` factory) also has been added to this module.
An `SmbStreamingMessageSource` and `SmbOutboundGateway` implementation are introduced.
See <<./smb.adoc#smb,SMB Support>> for more information.
See xref:smb.adoc[SMB Support] for more information.
[[x6.0-postgres]]
==== PostgreSQL Push Notification
=== PostgreSQL Push Notification
A `PostgresSubscribableChannel` allows to receive push notifications via `PostgresChannelMessageTableSubscriber` upon new messages add to the `JdbcChannelMessageStore`.
See <<./jdbc.adoc#postgresql-push,PostgreSQL: Receiving Push Notifications>> for more information.
See xref:jdbc/message-store.adoc#postgresql-push[PostgreSQL: Receiving Push Notifications] for more information.
[[x6.0-rmq]]
==== RabbitMQ Stream Queue Support
=== RabbitMQ Stream Queue Support
The AMQP module has been enhanced to provide support for inbound and outbound channel adapters using RabbitMQ Stream Queues.
See <<./amqp.adoc#rmq-streams,RabbitMQ Stream Queue Support>> for more information.
See xref:amqp/rmq-streams.adoc[RabbitMQ Stream Queue Support] for more information.
[[x6.0-sftp]]
==== Apache MINA SFTP
=== Apache MINA SFTP
The SFTP modules has been fully reworked from outdated JCraft JSch library to more robust and modern `org.apache.sshd:sshd-sftp` module of the Apache MINA project.
See <<./sftp.adoc#sftp,SFTP Adapters>> for more information.
See xref:sftp.adoc[SFTP Adapters] for more information.
[[x6.0-micrometer-observation]]
==== Micrometer Observation
=== Micrometer Observation
Enabling observation for timers and tracing using Micrometer is now supported.
See <<./metrics.adoc#micrometer-observation,Micrometer Observation>> for more information.
See xref:metrics.adoc#micrometer-observation[Micrometer Observation] for more information.
[[x6.0-graalmv-polyglot]]
==== GraalVM Polyglot Support
=== GraalVM Polyglot Support
The Scripting module now provides a `PolyglotScriptExecutor` implementation based on the GraalVM Polyglot support.
JavaScript support is now based on this executor since its JSR223 implementation has been removed from Java by itself.
See <<./scripting.adoc#scripting,Scripting Support>> for more information.
See xref:scripting.adoc[Scripting Support] for more information.
[[x6.0-cassandra]]
==== Apache Cassandra Support
=== Apache Cassandra Support
The Apache Cassandra Spring Integration Extensions project has been migrated as the `spring-integration-cassandra` module.
See <<./cassandra.adoc#cassandra,Apache Cassandra Support>> for more information.
See xref:cassandra.adoc[Apache Cassandra Support] for more information.
[[x6.0-kotlin-coroutines]]
==== Kotlin Coroutines
=== Kotlin Coroutines
Kotlin Coroutines support has been introduced to the framework.
See <<./kotlin-functions.adoc#kotlin-coroutines,Kotlin Coroutines>> for more information.
See xref:kotlin-functions.adoc#kotlin-coroutines[Kotlin Coroutines] for more information.
[[x6.0-aot]]
==== Native Images
=== Native Images
Support for creating GraalVM native images is provided.
See <<./native-aot.adoc#native-images-support,Native Images Support>> for more information.
See xref:native-aot.adoc[Native Images Support] for more information.
[[x6.0-general]]
=== General Changes
== General Changes
The messaging annotations are now `@Repeatable` and the same type can be declared several times on the same service method.
The messaging annotations don't require a `poller` attribute as an array of `@Poller` anymore.
See <<./configuration.adoc#annotations,Annotation Support>> for more information.
See xref:configuration/annotations.adoc[Annotation Support] for more information.
For convenience, the XML and Java DSL for Scatter-Gather, based on the `RecipientListRouter`, now sets an `applySequence = true`, so the gatherer part can rely on the default correlation strategies.
See <<./scatter-gather.adoc#scatter-gather,Scatter-Gather>> for more information.
See xref:scatter-gather.adoc[Scatter-Gather] for more information.
Another convenient behavior change has been made to the `AbstractMappingMessageRouter`.
Now, setting a `defaultOutputChannel` also resets the `channelKeyFallback` property to `false`, so no attempts will be made to resolve a channel from its key, but the logic immediately falls back to sending the message to the `defaultOutputChannel`.
See <<./router.adoc#router-common-parameters-all,Router Options>> for more information.
See xref:router/common-parameters.adoc#router-common-parameters-all[Router Options] for more information.
The `AggregatingMessageHandler` now does not split a `Collection<Message<?>>` result of the `MessageGroupProcessor` (unless it is a `SimpleMessageGroupProcessor`) on the output, but emits a single message containing this whole collection as a payload.
See <<./aggregator.adoc#aggregator,Aggregator>> for more information.
See xref:overview.adoc#overview-endpoints-aggregator[Aggregator] for more information.
The `IntegrationFlows` factory is now marked as deprecated in favor of the fluent API available in the `IntegrationFlow` interface itself.
The factory class will be removed in the future releases.
See <<./dsl.adoc#java-dsl,Java DSL>> for more information.
See xref:dsl.adoc#java-dsl[Java DSL] for more information.
The `org.springframework.util.concurrent.ListenableFuture` has been deprecated starting with Spring Framework `6.0`.
All Spring Integration async API has been migrated to the `CompletableFuture`.
@@ -129,7 +129,7 @@ Alongside with a `@MessagingGateway` annotation the interface can also be marked
The default naming strategy for gateway proxy beans can be customized via `@IntegrationComponentScan.nameGenerator()` attribute.
If `AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR` bean is present, it is consulted otherwise before falling back to the `AnnotationBeanNameGenerator`.
See <<./gateway.adoc#gateway, Messaging Gateway>> for more information.
See xref:gateway.adoc[Messaging Gateway] for more information.
The `integrationGlobalProperties` bean is now declared by the framework as an instance of `org.springframework.integration.context.IntegrationProperties` instead of the previously deprecated `java.util.Properties`.
@@ -137,62 +137,62 @@ Message handlers which produce a collection as a reply (e.g. `JpaOutboundGateway
Previously, `null` was returned ending the flow, or throwing an exception, depending on `requiresReply`.
[[x6.0-rmi]]
=== RMI Removal
== RMI Removal
The `spring-integration-rmi` module has been removed altogether after being deprecated in previous versions.
There is no replacement: it is recommended to migrate to more secure network and application protocols, such as WebSockets, RSockets, gRPC or REST.
[[x6.0-gemfire]]
=== GemFire Removal
== GemFire Removal
The `spring-integration-gemfire` module has been removed altogether since there is no Spring Data `2022.0.0` support for VMware GemFire or Apache Geode.
[[x6.0-http]]
=== HTTP Changes
== HTTP Changes
The `#cookies` variable for expression evaluation context, exposed in the `HttpRequestHandlingEndpointSupport`, is now a `MultiValueMap` to carry all the values for cookies set by the client.
See <<./http.adoc#http,HTTP Support>> for more information.
See xref:http.adoc[HTTP Support] for more information.
[[x6.0-kafka]]
=== Apache Kafka Changes
== Apache Kafka Changes
When providing a `RetryTemplate` on the inbound gateway or message-driven channel adapter, if an `errorChannel` is also provided, an `ErrorMessageSendingRecoverer` is automatically configured.
In addition, the new `KafkaErrorMessageSendingRecoverer` is provided; this can be used with a `DefaultErrorHandler` to avoid issues with long aggregated retry delays causing partitions rebalances.
See <<./kafka.adoc#kafka,Spring for Apache Kafka Support>> for more information.
See xref:kafka.adoc[Spring for Apache Kafka Support] for more information.
[[x6.0-jdbc]]
=== JDBC Changes
== JDBC Changes
The `DefaultLockRepository` can now be supplied with a `PlatformTransactionManager` instead of relying on the primary bean from the application context.
See <<./jdbc.adoc#jdbc-lock-registry,JDBC Lock Registry>> for more information.
See xref:jdbc.adoc#jdbc-lock-registry[JDBC Lock Registry] for more information.
[[x6.0-tcp]]
=== TCP/IP Changes
== TCP/IP Changes
The `lookupHost` property of the `AbstractConnectionFactory` and `DatagramPacketMessageMapper` is now set to `false` by default to avoid delays in the environments where DNS is not configured.
See <<./ip.adoc#ip,TCP and UDP Support>> for more information.
See xref:ip.adoc[TCP and UDP Support] for more information.
[[x6.0-jms]]
=== JMS Changes
== JMS Changes
The `JmsOutboundGateway` now creates a `TemporaryTopic` instead of `TemporaryQueue` if `replyPubSubDomain` option is set to `true`.
See <<./jms.adoc#jms,JMS Support>> for more information.
See xref:jms.adoc[JMS Support] for more information.
[[x6.0-security]]
=== Security Changes
== Security Changes
The `ChannelSecurityInterceptor` and its annotation `@SecuredChannel` and XML `<secured-channels>` configurations have been deprecated in favor of `AuthorizationChannelInterceptor`.
See <<./security.adoc#security,Security Support>> for more information.
See xref:security.adoc[Security Support] for more information.
[[x6.0-webflux]]
=== Webflux Request Attributes Support
== Webflux Request Attributes Support
Webclient Request attributes support has been added for `WebFluxRequestExecutingMessageHandler`.
See <<./webflux.adoc#webflux-request-attributes,WebFlux Request Attributes>> for more information.
See xref:webflux.adoc#webflux-request-attributes[WebFlux Request Attributes] for more information.

View File

@@ -1,39 +1,39 @@
[[migration-6.0-6.1]]
=== Changes between 6.0 and 6.1
= Changes between 6.0 and 6.1
[[x6.1-new-components]]
=== New Components
== New Components
[[x6.1-zip]]
==== Zip Support
=== Zip Support
The Zip Spring Integration Extension project has been migrated as the `spring-integration-zip` module.
See <<./zip.adoc#zip,Zip Support>> for more information.
See xref:zip.adoc[Zip Support] for more information.
[[x6.1-context-holder-advice]]
==== `ContextHolderRequestHandlerAdvice`
=== `ContextHolderRequestHandlerAdvice`
The `ContextHolderRequestHandlerAdvice` allows to store a value from a request message into some context around `MessageHandler` execution.
See <<./handler-advice.adoc#context-holder-advice, Context Holder Advice>> for more information.
See xref:handler-advice/context-holder.adoc[Context Holder Advice] for more information.
[[x6.1-handle-reactive]]
==== The `handleReactive()` operator for Java DSL
=== The `handleReactive()` operator for Java DSL
The `IntegrationFlow` can now end with a convenient `handleReactive(ReactiveMessageHandler)` operator.
See <<./reactive-streams.adoc#reactive-message-handler, `ReactiveMessageHandler`>> for more information.
See xref:reactive-streams.adoc#reactive-message-handler[`ReactiveMessageHandler`] for more information.
[[x6.1-partitioned-channel]]
==== `PartitionedChannel`
== `PartitionedChannel`
A new `PartitionedChannel` has been introduced to process messages with the same partition key in the same thread.
See <<./channel.adoc#partitioned-channel, `PartitionedChannel`>> for more information.
See xref:channel/implementations.adoc#partitioned-channel[`PartitionedChannel`] for more information.
[[x6.1-general]]
=== General Changes
== General Changes
- Added support for transforming to/from Protocol Buffers.
See <<./transformer.adoc#Protobuf-transformers, Protocol Buffers Transformers>> for more information.
See xref:transformer.adoc#Protobuf-transformers[Protocol Buffers Transformers] for more information.
- The `MessageFilter` now emits a warning into logs when message is silently discarded and dropped.
See <<./filter.adoc#filter, Filter>> for more information.
See xref:filter.adoc[Filter] for more information.
- The default timeout for send and receive operations in gateways and replying channel adapters has been changed from infinity to `30` seconds.
Only one left as a `1` second is a `receiveTimeout` for `PollingConsumer` to not block a scheduler thread too long and let other queued tasks to be performed with the `TaskScheduler`.
@@ -41,44 +41,44 @@ Only one left as a `1` second is a `receiveTimeout` for `PollingConsumer` to not
- The `IntegrationComponentSpec.get()` method has been deprecated with removal planned for the next version.
Since `IntegrationComponentSpec` is a `FactoryBean`, its bean definition must stay as is without any target object resolutions.
The Java DSL and the framework by itself will manage the `IntegrationComponentSpec` lifecycle.
See <<./dsl.adoc#java-dsl, Java DSL>> for more information.
See xref:dsl.adoc#java-dsl[ Java DSL] for more information.
- The `AbstractMessageProducingHandler` is marked as an `async` by default if its output channel is configured to a `ReactiveStreamsSubscribableChannel`.
See <<./service-activator.adoc#async-service-activator,Asynchronous Service Activator>> for more information.
See xref:service-activator.adoc#async-service-activator[Asynchronous Service Activator] for more information.
[[x6.1-web-sockets]]
=== Web Sockets Changes
== Web Sockets Changes
A `ClientWebSocketContainer` can now be configured with a predefined `URI` instead of a combination of `uriTemplate` and `uriVariables`.
See <<./web-sockets.adoc#web-socket-overview, WebSocket Overview>> for more information.
See xref:web-sockets.adoc#web-socket-overview[WebSocket Overview] for more information.
[[x6.1-jms]]
=== JMS Changes
== JMS Changes
The `JmsInboundGateway`, via its `ChannelPublishingJmsMessageListener`, can now be configured with a `replyToExpression` to resolve a reply destination against the request message at runtime.
See <<./jms.adoc#jms-inbound-gateway, JMS Inbound Gateway>> for more information.
See xref:jms.adoc#jms-inbound-gateway[JMS Inbound Gateway] for more information.
[[x6.1-mail]]
=== Mail Changes
== Mail Changes
The (previously deprecated) `ImapIdleChannelAdapter.sendingTaskExecutor` property has been removed in favor of an asynchronous message process downstream in the flow.
See <<./mail.adoc#mail-inbound, Mail-receiving Channel Adapter>> for more information.
See xref:mail.adoc#mail-inbound[Mail-receiving Channel Adapter] for more information.
[[x6.1-file]]
=== Files Changes
== Files Changes
The `FileReadingMessageSource` now exposes `watchMaxDepth` and `watchDirPredicate` options for the `WatchService`.
See <<./file.adoc#watch-service-directory-scanner, `WatchServiceDirectoryScanner`>> for more information.
See xref:file.adoc#watch-service-directory-scanner[ `WatchServiceDirectoryScanner`] for more information.
[[x6.1-amqp]]
=== AMQP Changes
== AMQP Changes
The Java DSL API for Rabbit Streams (the `RabbitStream` factory) exposes additional properties for simple configurations.
See <<./amqp.adoc#rmq-streams, `RabbitMQ Stream Queue Support`>> for more information.
See xref:amqp/rmq-streams.adoc[`RabbitMQ Stream Queue Support`] for more information.
[[x6.1-jdbc]]
=== JDBC Changes
== JDBC Changes
The `DefaultLockRepository` now exposes setters for `insert`, `update` and `renew` queries.
See <<./jdbc.adoc#jdbc-lock-registry, JDBC Lock Registry>> for more information.
See xref:jdbc.adoc#jdbc-lock-registry[ JDBC Lock Registry] for more information.

View File

@@ -1,5 +1,5 @@
[[channel-adapter]]
=== Channel Adapter
= Channel Adapter
A channel adapter is a message endpoint that enables connecting a single sender or receiver to a message channel.
Spring Integration provides a number of adapters to support various transports, such as JMS, file, HTTP, web services, mail, and more.
@@ -9,7 +9,7 @@ There are both inbound and outbound adapters, and each may be configured with XM
These provide an easy way to extend Spring Integration, as long as you have a method that can be invoked as either a source or a destination.
[[channel-adapter-namespace-inbound]]
==== Configuring An Inbound Channel Adapter
== Configuring An Inbound Channel Adapter
An `inbound-channel-adapter` element (a `SourcePollingChannelAdapter` in Java configuration) can invoke any method on a Spring-managed object and send a non-null return value to a `MessageChannel` after converting the method's output to a `Message`.
When the adapter's subscription is activated, a poller tries to receive messages from the source.
@@ -17,9 +17,11 @@ The poller is scheduled with the `TaskScheduler` according to the provided confi
To configure the polling interval or cron expression for an individual channel adapter, you can provide a 'poller' element with one of the scheduling attributes, such as 'fixed-rate' or 'cron'.
The following example defines two `inbound-channel-adapter` instances:
====
[tabs]
======
Java DSL::
+
[source, java, role="primary"]
.Java DSL
----
@Bean
public IntegrationFlow source1() {
@@ -37,8 +39,10 @@ public IntegrationFlow source2() {
.get();
}
----
Java::
+
[source, java, role="secondary"]
.Java
----
public class SourceService {
@@ -53,8 +57,10 @@ public class SourceService {
}
}
----
Kotlin DSL::
+
[source, kotlin, role="secondary"]
.Kotlin DSL
----
@Bean
fun messageSourceFlow() =
@@ -63,8 +69,10 @@ fun messageSourceFlow() =
...
}
----
XML::
+
[source, xml, role="secondary"]
.XML
----
<int:inbound-channel-adapter ref="source1" method="method1" channel="channel1">
<int:poller fixed-rate="5000"/>
@@ -74,12 +82,12 @@ fun messageSourceFlow() =
<int:poller cron="30 * 9-17 * * MON-FRI"/>
</int:channel-adapter>
----
====
======
See also <<channel-adapter-expressions-and-scripts>>.
See also xref:channel-adapter.adoc#channel-adapter-expressions-and-scripts[Channel Adapter Expressions and Scripts].
NOTE: If no poller is provided, then a single default poller must be registered within the context.
See <<./endpoint.adoc#endpoint-namespace,Endpoint Namespace Support>> for more detail.
See xref:endpoint.adoc#endpoint-namespace[Endpoint Namespace Support] for more detail.
[IMPORTANT]
.Important: Poller Configuration
@@ -87,25 +95,21 @@ See <<./endpoint.adoc#endpoint-namespace,Endpoint Namespace Support>> for more d
All the `inbound-channel-adapter` types are backed by a `SourcePollingChannelAdapter`, which means they contain a poller configuration that polls the `MessageSource` (to invoke a custom method that produces the value that becomes a `Message` payload) based on the configuration specified in the Poller.
The following example shows the configuration of two pollers:
====
[source,xml]
----
<int:poller max-messages-per-poll="1" fixed-rate="1000"/>
<int:poller max-messages-per-poll="10" fixed-rate="1000"/>
----
====
In the first configuration, the polling task is invoked once per poll, and, during each task (poll), the method (which results in the production of the message) is invoked once, based on the `max-messages-per-poll` attribute value.
In the second configuration, the polling task is invoked 10 times per poll or until it returns 'null', thus possibly producing ten messages per poll while each poll happens at one-second intervals.
However, what happens if the configuration looks like the following example:
====
[source,xml]
----
<int:poller fixed-rate="1000"/>
----
====
Note that there is no `max-messages-per-poll` specified.
As we cover later, the identical poller configuration in the `PollingConsumer` (for example, `service-activator`, `filter`, `router`, and others) would have a default value of `-1` for `max-messages-per-poll`, which means "`execute the polling task non-stop unless the polling method returns null (perhaps because there are no more messages in the `QueueChannel`)`" and then sleep for one second.
@@ -116,30 +120,30 @@ This makes sure that the poller can react to lifecycle events (such as start and
However, if you are sure that your method can return null, and you need to poll for as many sources as available per each poll, you should explicitly set `max-messages-per-poll` to a negative value, as the following example shows:
====
[source,xml]
----
<int:poller max-messages-per-poll="-1" fixed-rate="1000"/>
----
====
Starting with version 5.5, a `0` value for `max-messages-per-poll` has a special meaning - skip the `MessageSource.receive()` call altogether, which may be considered as pausing for this inbound channel adapter until the `maxMessagesPerPoll` is changed to a non-zero value at a later time, e.g. via a Control Bus.
Starting with version 6.2, the `fixed-delay` and `fixed-rate` can be configured in https://en.wikipedia.org/wiki/ISO_8601#Durations[ISO 8601 Duration] format, e.g. `PT10S`, `P1D` etc.
In addition, an `initial-interval` of the underlying `PeriodicTrigger` is also exposed with similar value formats as `fixed-delay` and `fixed-rate`.
Also see <<./endpoint.adoc#global-default-poller,Global Default Poller>> for more information.
Also see xref:endpoint.adoc#global-default-poller[Global Default Poller] for more information.
=====
[[channel-adapter-namespace-outbound]]
==== Configuring An Outbound Channel Adapter
== Configuring An Outbound Channel Adapter
An `outbound-channel-adapter` element (a `@ServiceActivator` for Java configuration) can also connect a `MessageChannel` to any POJO consumer method that should be invoked with the payload of messages sent to that channel.
The following example shows how to define an outbound channel adapter:
====
[tabs]
======
Java DSL::
+
[source, java, role="primary"]
.Java DSL
----
@Bean
public IntegrationFlow outboundChannelAdapterFlow(MyPojo myPojo) {
@@ -147,8 +151,10 @@ public IntegrationFlow outboundChannelAdapterFlow(MyPojo myPojo) {
.handle(myPojo, "handle");
}
----
Java::
+
[source, java, role="secondary"]
.Java
----
public class MyPojo {
@@ -159,8 +165,10 @@ public class MyPojo {
}
----
Kotlin DSL::
+
[source, kotlin, role="secondary"]
.Kotlin DSL
----
@Bean
fun outboundChannelAdapterFlow(myPojo: MyPojo) =
@@ -168,20 +176,24 @@ fun outboundChannelAdapterFlow(myPojo: MyPojo) =
handle(myPojo, "handle")
}
----
XML::
+
[source, xml, role="secondary"]
.XML
----
<int:outbound-channel-adapter channel="channel1" ref="target" method="handle"/>
<beans:bean id="target" class="org.MyPojo"/>
----
====
======
If the channel being adapted is a `PollableChannel`, you must provide a poller sub-element (the `@Poller` sub-annotation on the `@ServiceActivator`), as the following example shows:
====
[tabs]
======
Java::
+
[source, java, role="primary"]
.Java
----
public class MyPojo {
@@ -192,8 +204,10 @@ public class MyPojo {
}
----
XML::
+
[source, xml, role="secondary"]
.XML
----
<int:outbound-channel-adapter channel="channel2" ref="target" method="handle">
<int:poller fixed-rate="3000" />
@@ -201,19 +215,17 @@ public class MyPojo {
<beans:bean id="target" class="org.MyPojo"/>
----
====
======
You should use a `ref` attribute if the POJO consumer implementation can be reused in other `<outbound-channel-adapter>` definitions.
However, if the consumer implementation is referenced by only a single definition of the `<outbound-channel-adapter>`, you can define it as an inner bean, as the following example shows:
====
[source,xml]
----
<int:outbound-channel-adapter channel="channel" method="handle">
<beans:bean class="org.Foo"/>
</int:outbound-channel-adapter>
----
====
NOTE: Using both the `ref` attribute and an inner handler definition in the same `<outbound-channel-adapter>` configuration is not allowed, as it creates an ambiguous condition.
Such a configuration results in an exception being thrown.
@@ -223,7 +235,7 @@ The created channel's name matches the `id` attribute of the `<inbound-channel-a
Therefore, if `channel` is not provided, `id` is required.
[[channel-adapter-expressions-and-scripts]]
==== Channel Adapter Expressions and Scripts
== Channel Adapter Expressions and Scripts
Like many other Spring Integration components, the `<inbound-channel-adapter>` and `<outbound-channel-adapter>` also provide support for SpEL expression evaluation.
To use SpEL, provide the expression string in the 'expression' attribute instead of providing the 'ref' and 'method' attributes that are used for method-invocation on a bean.
@@ -233,7 +245,6 @@ Starting with Spring Integration 3.0, an `<int:inbound-channel-adapter/>` can al
If you provide a script as a `Resource` by using the `location` attribute, you can also set `refresh-check-delay`, which allows the resource to be periodically refreshed.
If you want the script to be checked on each poll, you would need to coordinate this setting with the poller's trigger, as the following example shows:
====
[source,xml]
----
<int:inbound-channel-adapter ref="source1" method="method1" channel="channel1">
@@ -241,11 +252,10 @@ If you want the script to be checked on each poll, you would need to coordinate
<script:script lang="ruby" location="Foo.rb" refresh-check-delay="5000"/>
</int:inbound-channel-adapter>
----
====
See also the `cacheSeconds` property on the `ReloadableResourceBundleExpressionSource` when using the `<expression/>` sub-element.
For more information regarding expressions, see <<./spel.adoc#spel,Spring Expression Language (SpEL)>>.
For scripts, see <<./groovy.adoc#groovy,Groovy support>> and <<./scripting.adoc#scripting,Scripting Support>>.
For more information regarding expressions, see xref:spel.adoc[Spring Expression Language (SpEL)].
For scripts, see xref:groovy.adoc[Groovy support] and xref:scripting.adoc[Scripting Support].
IMPORTANT: The `<int:inbound-channel-adapter/>` (`SourcePollingChannelAdapter`) is an endpoint which starts a message flow by periodically triggering to poll some underlying `MessageSource`.
Since, at the time of polling, there is no message object, expressions and scripts do not have access to a root `Message`, so there are no payload or headers properties that are available in most other messaging SpEL expressions.

View File

@@ -0,0 +1,6 @@
[[channel]]
= Message Channels
:page-section-summary-toc: 1
While the `Message` plays the crucial role of encapsulating data, it is the `MessageChannel` that decouples message producers from message consumers.

View File

@@ -0,0 +1,197 @@
[[channel-implementations]]
= Message Channel Implementations
Spring Integration provides different message channel implementations.
The following sections briefly describe each one.
[[channel-implementations-publishsubscribechannel]]
== `PublishSubscribeChannel`
The `PublishSubscribeChannel` implementation broadcasts any `Message` sent to it to all of its subscribed handlers.
This is most often used for sending event messages, whose primary role is notification (as opposed to document messages, which are generally intended to be processed by a single handler).
Note that the `PublishSubscribeChannel` is intended for sending only.
Since it broadcasts to its subscribers directly when its `send(Message)` method is invoked, consumers cannot poll for messages (it does not implement `PollableChannel` and therefore has no `receive()` method).
Instead, any subscriber must itself be a `MessageHandler`, and the subscriber's `handleMessage(Message)` method is invoked in turn.
Prior to version 3.0, invoking the `send` method on a `PublishSubscribeChannel` that had no subscribers returned `false`.
When used in conjunction with a `MessagingTemplate`, a `MessageDeliveryException` was thrown.
Starting with version 3.0, the behavior has changed such that a `send` is always considered successful if at least the minimum subscribers are present (and successfully handle the message).
This behavior can be modified by setting the `minSubscribers` property, which defaults to `0`.
NOTE: If you use a `TaskExecutor`, only the presence of the correct number of subscribers is used for this determination, because the actual handling of the message is performed asynchronously.
[[channel-implementations-queuechannel]]
== `QueueChannel`
The `QueueChannel` implementation wraps a queue.
Unlike the `PublishSubscribeChannel`, the `QueueChannel` has point-to-point semantics.
In other words, even if the channel has multiple consumers, only one of them should receive any `Message` sent to that channel.
It provides a default no-argument constructor (providing an essentially unbounded capacity of `Integer.MAX_VALUE`) as well as a constructor that accepts the queue capacity, as the following listing shows:
[source,java]
----
public QueueChannel(int capacity)
----
A channel that has not reached its capacity limit stores messages in its internal queue, and the `send(Message<?>)` method returns immediately, even if no receiver is ready to handle the message.
If the queue has reached capacity, the sender blocks until room is available in the queue.
Alternatively, if you use the send method that has an additional timeout parameter, the queue blocks until either room is available or the timeout period elapses, whichever occurs first.
Similarly, a `receive()` call returns immediately if a message is available on the queue, but, if the queue is empty, then a receive call may block until either a message is available or the timeout, if provided, elapses.
In either case, it is possible to force an immediate return regardless of the queue's state by passing a timeout value of 0.
Note, however, that calls to the versions of `send()` and `receive()` with no `timeout` parameter block indefinitely.
[[channel-implementations-prioritychannel]]
== `PriorityChannel`
Whereas the `QueueChannel` enforces first-in-first-out (FIFO) ordering, the `PriorityChannel` is an alternative implementation that allows for messages to be ordered within the channel based upon a priority.
By default, the priority is determined by the `priority` header within each message.
However, for custom priority determination logic, a comparator of type `Comparator<Message<?>>` can be provided to the `PriorityChannel` constructor.
[[channel-implementations-rendezvouschannel]]
== `RendezvousChannel`
The `RendezvousChannel` enables a "`direct-handoff`" scenario, wherein a sender blocks until another party invokes the channel's `receive()` method.
The other party blocks until the sender sends the message.
Internally, this implementation is quite similar to the `QueueChannel`, except that it uses a `SynchronousQueue` (a zero-capacity implementation of `BlockingQueue`).
This works well in situations where the sender and receiver operate in different threads, but asynchronously dropping the message in a queue is not appropriate.
In other words, with a `RendezvousChannel`, the sender knows that some receiver has accepted the message, whereas with a `QueueChannel`, the message would have been stored to the internal queue and potentially never received.
TIP: Keep in mind that all of these queue-based channels are storing messages in-memory only by default.
When persistence is required, you can either provide a 'message-store' attribute within the 'queue' element to reference a persistent `MessageStore` implementation or you can replace the local channel with one that is backed by a persistent broker, such as a JMS-backed channel or channel adapter.
The latter option lets you take advantage of any JMS provider's implementation for message persistence, as discussed in xref:jms.adoc[JMS Support].
However, when buffering in a queue is not necessary, the simplest approach is to rely upon the `DirectChannel`, discussed in the next section.
The `RendezvousChannel` is also useful for implementing request-reply operations.
The sender can create a temporary, anonymous instance of `RendezvousChannel`, which it then sets as the 'replyChannel' header when building a `Message`.
After sending that `Message`, the sender can immediately call `receive` (optionally providing a timeout value) in order to block while waiting for a reply `Message`.
This is very similar to the implementation used internally by many of Spring Integration's request-reply components.
[[channel-implementations-directchannel]]
== `DirectChannel`
The `DirectChannel` has point-to-point semantics but otherwise is more similar to the `PublishSubscribeChannel` than any of the queue-based channel implementations described earlier.
It implements the `SubscribableChannel` interface instead of the `PollableChannel` interface, so it dispatches messages directly to a subscriber.
As a point-to-point channel, however, it differs from the `PublishSubscribeChannel` in that it sends each `Message` to a single subscribed `MessageHandler`.
In addition to being the simplest point-to-point channel option, one of its most important features is that it enables a single thread to perform the operations on "`both sides`" of the channel.
For example, if a handler subscribes to a `DirectChannel`, then sending a `Message` to that channel triggers invocation of that handler's `handleMessage(Message)` method directly in the sender's thread, before the `send()` method invocation can return.
The key motivation for providing a channel implementation with this behavior is to support transactions that must span across the channel while still benefiting from the abstraction and loose coupling that the channel provides.
If the `send()` call is invoked within the scope of a transaction, the outcome of the handler's invocation (for example, updating a database record) plays a role in determining the ultimate result of that transaction (commit or rollback).
NOTE: Since the `DirectChannel` is the simplest option and does not add any additional overhead that would be required for scheduling and managing the threads of a poller, it is the default channel type within Spring Integration.
The general idea is to define the channels for an application, consider which of those need to provide buffering or to throttle input, and modify those to be queue-based `PollableChannels`.
Likewise, if a channel needs to broadcast messages, it should not be a `DirectChannel` but rather a `PublishSubscribeChannel`.
Later, we show how each of these channels can be configured.
The `DirectChannel` internally delegates to a message dispatcher to invoke its subscribed message handlers, and that dispatcher can have a load-balancing strategy exposed by `load-balancer` or `load-balancer-ref` attributes (mutually exclusive).
The load balancing strategy is used by the message dispatcher to help determine how messages are distributed amongst message handlers when multiple message handlers subscribe to the same channel.
As a convenience, the `load-balancer` attribute exposes an enumeration of values pointing to pre-existing implementations of `LoadBalancingStrategy`.
A `round-robin` (load-balances across the handlers in rotation) and `none` (for the cases where one wants to explicitly disable load balancing) are the only available values.
Other strategy implementations may be added in future versions.
However, since version 3.0, you can provide your own implementation of the `LoadBalancingStrategy` and inject it by using the `load-balancer-ref` attribute, which should point to a bean that implements `LoadBalancingStrategy`, as the following example shows:
A `FixedSubscriberChannel` is a `SubscribableChannel` that only supports a single `MessageHandler` subscriber that cannot be unsubscribed.
This is useful for high-throughput performance use-cases when no other subscribers are involved and no channel interceptors are needed.
[source,xml]
----
<int:channel id="lbRefChannel">
<int:dispatcher load-balancer-ref="lb"/>
</int:channel>
<bean id="lb" class="foo.bar.SampleLoadBalancingStrategy"/>
----
Note that the `load-balancer` and `load-balancer-ref` attributes are mutually exclusive.
The load-balancing also works in conjunction with a boolean `failover` property.
If the `failover` value is true (the default), the dispatcher falls back to any subsequent handlers (as necessary) when preceding handlers throw exceptions.
The order is determined by an optional order value defined on the handlers themselves or, if no such value exists, the order in which the handlers subscribed.
If a certain situation requires that the dispatcher always try to invoke the first handler and then fall back in the same fixed order sequence every time an error occurs, no load-balancing strategy should be provided.
In other words, the dispatcher still supports the `failover` boolean property even when no load-balancing is enabled.
Without load-balancing, however, the invocation of handlers always begins with the first, according to their order.
For example, this approach works well when there is a clear definition of primary, secondary, tertiary, and so on.
When using the namespace support, the `order` attribute on any endpoint determines the order.
NOTE: Keep in mind that load-balancing and `failover` apply only when a channel has more than one subscribed message handler.
When using the namespace support, this means that more than one endpoint shares the same channel reference defined in the `input-channel` attribute.
Starting with version 5.2, when `failover` is true, a failure of the current handler together with the failed message is logged under `debug` or `info` if configured respectively.
[[executor-channel]]
== `ExecutorChannel`
The `ExecutorChannel` is a point-to-point channel that supports the same dispatcher configuration as `DirectChannel` (load-balancing strategy and the `failover` boolean property).
The key difference between these two dispatching channel types is that the `ExecutorChannel` delegates to an instance of `TaskExecutor` to perform the dispatch.
This means that the send method typically does not block, but it also means that the handler invocation may not occur in the sender's thread.
It therefore does not support transactions that span the sender and receiving handler.
CAUTION: The sender can sometimes block.
For example, when using a `TaskExecutor` with a rejection policy that throttles the client (such as the `ThreadPoolExecutor.CallerRunsPolicy`), the sender's thread can execute the method any time the thread pool is at its maximum capacity and the executor's work queue is full.
Since that situation would only occur in a non-predictable way, you should not rely upon it for transactions.
[[partitioned-channel]]
== `PartitionedChannel`
Starting with version 6.1, a `PartitionedChannel` implementation is provided.
This is an extension of `AbstractExecutorChannel` and represents point-to-point dispatching logic where the actual consumption is processed on a specific thread, determined by the partition key evaluated from a message sent to this channel.
This channel is similar to the `ExecutorChannel` mentioned above, but with the difference that messages with the same partition key are always handled in the same thread, preserving ordering.
It does not require an external `TaskExecutor`, but can be configured with a custom `ThreadFactory` (e.g. `Thread.ofVirtual().name("partition-", 0).factory()`).
This factory is used to populate single-thread executors into a `MessageDispatcher` delegate, per partition.
By default, the `IntegrationMessageHeaderAccessor.CORRELATION_ID` message header is used as the partition key.
This channel can be configured as a simple bean:
[source,java]
----
@Bean
PartitionedChannel somePartitionedChannel() {
return new PartitionedChannel(3, (message) -> message.getHeaders().get("partitionKey"));
}
----
The channel will have `3` partitions - dedicated threads; will use the `partitionKey` header to determine in which partition the message will be handled.
See `PartitionedChannel` class Javadocs for more information.
[[flux-message-channel]]
== `FluxMessageChannel`
The `FluxMessageChannel` is an `org.reactivestreams.Publisher` implementation for `"sinking"` sent messages into an internal `reactor.core.publisher.Flux` for on demand consumption by reactive subscribers downstream.
This channel implementation is neither a `SubscribableChannel`, nor a `PollableChannel`, so only `org.reactivestreams.Subscriber` instances can be used to consume from this channel honoring back-pressure nature of reactive streams.
On the other hand, the `FluxMessageChannel` implements a `ReactiveStreamsSubscribableChannel` with its `subscribeTo(Publisher<Message<?>>)` contract allowing receiving events from reactive source publishers, bridging a reactive stream into the integration flow.
To achieve fully reactive behavior for the whole integration flow, such a channel must be placed between all the endpoints in the flow.
See xref:reactive-streams.adoc[Reactive Streams Support] for more information about interaction with Reactive Streams.
[[channel-implementations-threadlocalchannel]]
== Scoped Channel
Spring Integration 1.0 provided a `ThreadLocalChannel` implementation, but that has been removed as of 2.0.
Now the more general way to handle the same requirement is to add a `scope` attribute to a channel.
The value of the attribute can be the name of a scope that is available within the context.
For example, in a web environment, certain scopes are available, and any custom scope implementations can be registered with the context.
The following example shows a thread-local scope being applied to a channel, including the registration of the scope itself:
[source,xml]
----
<int:channel id="threadScopedChannel" scope="thread">
<int:queue />
</int:channel>
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="thread" value="org.springframework.context.support.SimpleThreadScope" />
</map>
</property>
</bean>
----
The channel defined in the previous example also delegates to a queue internally, but the channel is bound to the current thread, so the contents of the queue are similarly bound.
That way, the thread that sends to the channel can later receive those same messages, but no other thread would be able to access them.
While thread-scoped channels are rarely needed, they can be useful in situations where `DirectChannel` instances are being used to enforce a single thread of operation but any reply messages should be sent to a "`terminal`" channel.
If that terminal channel is thread-scoped, the original sending thread can collect its replies from the terminal channel.
Now, since any channel can be scoped, you can define your own scopes in addition to thread-Local.

View File

@@ -0,0 +1,70 @@
[[channel-interceptors]]
= Channel Interceptors
One of the advantages of a messaging architecture is the ability to provide common behavior and capture meaningful information about the messages passing through the system in a non-invasive way.
Since the `Message` instances are sent to and received from `MessageChannel` instances, those channels provide an opportunity for intercepting the send and receive operations.
The `ChannelInterceptor` strategy interface, shown in the following listing, provides methods for each of those operations:
[source,java]
----
public interface ChannelInterceptor {
Message<?> preSend(Message<?> message, MessageChannel channel);
void postSend(Message<?> message, MessageChannel channel, boolean sent);
void afterSendCompletion(Message<?> message, MessageChannel channel, boolean sent, Exception ex);
boolean preReceive(MessageChannel channel);
Message<?> postReceive(Message<?> message, MessageChannel channel);
void afterReceiveCompletion(Message<?> message, MessageChannel channel, Exception ex);
}
----
After implementing the interface, registering the interceptor with a channel is just a matter of making the following call:
[source,java]
----
channel.addInterceptor(someChannelInterceptor);
----
The methods that return a `Message` instance can be used for transforming the `Message` or can return 'null' to prevent further processing (of course, any of the methods can throw a `RuntimeException`).
Also, the `preReceive` method can return `false` to prevent the receive operation from proceeding.
NOTE: Keep in mind that `receive()` calls are only relevant for `PollableChannels`.
In fact, the `SubscribableChannel` interface does not even define a `receive()` method.
The reason for this is that when a `Message` is sent to a `SubscribableChannel`, it is sent directly to zero or more subscribers, depending on the type of channel (for example,
a `PublishSubscribeChannel` sends to all of its subscribers).
Therefore, the `preReceive(...)`, `postReceive(...)`, and `afterReceiveCompletion(...)` interceptor methods are invoked only when the interceptor is applied to a `PollableChannel`.
Spring Integration also provides an implementation of the https://www.enterpriseintegrationpatterns.com/WireTap.html[Wire Tap] pattern.
It is a simple interceptor that sends the `Message` to another channel without otherwise altering the existing flow.
It can be very useful for debugging and monitoring.
An example is shown in xref:channel/configuration.adoc#channel-wiretap[Wire Tap].
Because it is rarely necessary to implement all of the interceptor methods, the interface provides no-op methods (those returning `void` method have no code, the `Message`-returning methods return the `Message` as-is, and the `boolean` method returns `true`).
TIP: The order of invocation for the interceptor methods depends on the type of channel.
As described earlier, the queue-based channels are the only ones where the `receive()` method is intercepted in the first place.
Additionally, the relationship between send and receive interception depends on the timing of the separate sender and receiver threads.
For example, if a receiver is already blocked while waiting for a message, the order could be as follows: `preSend`, `preReceive`, `postReceive`, `postSend`.
However, if a receiver polls after the sender has placed a message on the channel and has already returned, the order would be as follows: `preSend`, `postSend` (some-time-elapses), `preReceive`, `postReceive`.
The time that elapses in such a case depends on a number of factors and is therefore generally unpredictable (in fact, the receive may never happen).
The type of queue also plays a role (for example, rendezvous versus priority).
In short, you cannot rely on the order beyond the fact that `preSend` precedes `postSend` and `preReceive` precedes `postReceive`.
Starting with Spring Framework 4.1 and Spring Integration 4.1, the `ChannelInterceptor` provides new methods: `afterSendCompletion()` and `afterReceiveCompletion()`.
They are invoked after `send()' and 'receive()` calls, regardless of any exception that is raised, which allow for resource cleanup.
Note that the channel invokes these methods on the `ChannelInterceptor` list in the reverse order of the initial `preSend()` and `preReceive()` calls.
Starting with version 5.1, global channel interceptors now apply to dynamically registered channels - such as through beans that are initialized by using `beanFactory.initializeBean()` or `IntegrationFlowContext` when using the Java DSL.
Previously, interceptors were not applied when beans were created after the application context was refreshed.
Also, starting with version 5.1, `ChannelInterceptor.postReceive()` is no longer called when no message is received; it is no longer necessary to check for a `null` `Message<?>`.
Previously, the method was called.
If you have an interceptor that relies on the previous behavior, implement `afterReceiveCompleted()` instead, since that method is invoked, regardless of whether a message is received or not.
NOTE: Starting with version 5.2, the `ChannelInterceptorAware` is deprecated in favor of `InterceptableChannel` from the Spring Messaging module, which it extends now for backward compatibility.

View File

@@ -0,0 +1,56 @@
[[channel-interfaces]]
= The MessageChannel Interface
Spring Integration's top-level `MessageChannel` interface is defined as follows:
[source,java]
----
public interface MessageChannel {
boolean send(Message message);
boolean send(Message message, long timeout);
}
----
When sending a message, the return value is `true` if the message is sent successfully.
If the send call times out or is interrupted, it returns `false`.
[[channel-interfaces-pollablechannel]]
== `PollableChannel`
Since message channels may or may not buffer messages (as discussed in the xref:overview.adoc[Spring Integration Overview]), two sub-interfaces define the buffering (pollable) and non-buffering (subscribable) channel behavior.
The following listing shows the definition of the `PollableChannel` interface:
[source,java]
----
public interface PollableChannel extends MessageChannel {
Message<?> receive();
Message<?> receive(long timeout);
}
----
As with the send methods, when receiving a message, the return value is null in the case of a timeout or interrupt.
[[channel-interfaces-subscribablechannel]]
== `SubscribableChannel`
The `SubscribableChannel` base interface is implemented by channels that send messages directly to their subscribed `MessageHandler` instances.
Therefore, they do not provide receive methods for polling.
Instead, they define methods for managing those subscribers.
The following listing shows the definition of the `SubscribableChannel` interface:
[source,java]
----
public interface SubscribableChannel extends MessageChannel {
boolean subscribe(MessageHandler handler);
boolean unsubscribe(MessageHandler handler);
}
----

View File

@@ -0,0 +1,16 @@
[[channel-special-channels]]
= Special Channels
:page-section-summary-toc: 1
Two special channels are defined within the application context by default: `errorChannel` and `nullChannel`.
The 'nullChannel' (an instance of `NullChannel`) acts like `/dev/null`, logging any message sent to it at the `DEBUG` level and returning immediately.
The special treatment is applied for an `org.reactivestreams.Publisher` payload of a transmitted message: it is subscribed to in this channel immediately, to initiate reactive stream processing, although the data is discarded.
An error thrown from a reactive stream processing (see `Subscriber.onError(Throwable)`) is logged under the `warn` level for possible investigation.
If there is need to do anything with such an error, the `xref:handler-advice/reactive.adoc[ReactiveRequestHandlerAdvice]` with a `Mono.doOnError()` customization can be applied to the message handler producing `Mono` reply into this `nullChannel`.
Any time you face channel resolution errors for a reply that you do not care about, you can set the affected component's `output-channel` attribute to 'nullChannel' (the name, 'nullChannel', is reserved within the application context).
The 'errorChannel' is used internally for sending error messages and may be overridden with a custom configuration.
This is discussed in greater detail in xref:scatter-gather.adoc#scatter-gather-error-handling[Error Handling].
See also xref:dsl/java-channels.adoc[Message Channels] in the Java DSL chapter for more information about message channel and interceptors.

View File

@@ -0,0 +1,33 @@
[[channel-template]]
= `MessagingTemplate`
When the endpoints and their various configuration options are introduced, Spring Integration provides a foundation for messaging components that enables non-invasive invocation of your application code from the messaging system.
However, it is sometimes necessary to invoke the messaging system from your application code.
For convenience when implementing such use cases, Spring Integration provides a `MessagingTemplate` that supports a variety of operations across the message channels, including request and reply scenarios.
For example, it is possible to send a request and wait for a reply, as follows:
[source,java]
----
MessagingTemplate template = new MessagingTemplate();
Message reply = template.sendAndReceive(someChannel, new GenericMessage("test"));
----
In the preceding example, a temporary anonymous channel would be created internally by the template.
The 'sendTimeout' and 'receiveTimeout' properties may also be set on the template, and other exchange types are also supported.
The following listing shows the signatures for such methods:
[source,java]
----
public boolean send(final MessageChannel channel, final Message<?> message) { ...
}
public Message<?> sendAndReceive(final MessageChannel channel, final Message<?> request) { ...
}
public Message<?> receive(final PollableChannel<?> channel) { ...
}
----
NOTE: A less invasive approach that lets you invoke simple interfaces with payload or header values instead of `Message` instances is described in xref:gateway.adoc#gateway-proxy[Enter the `GatewayProxyFactoryBean`].

View File

@@ -1,5 +1,5 @@
[[claim-check]]
=== Claim Check
= Claim Check
In earlier sections, we covered several content enricher components that can help you deal with situations where a message is missing a piece of data.
We also discussed content filtering, which lets you remove data items from a message.
@@ -20,12 +20,11 @@ Spring Integration provides two types of claim check transformers:
Convenient namespace-based mechanisms are available to configure them.
[[claim-check-in]]
==== Incoming Claim Check Transformer
== Incoming Claim Check Transformer
An incoming claim check transformer transforms an incoming message by storing it in the message store identified by its `message-store` attribute.
The following example defines an incoming claim check transformer:
====
[source,xml]
----
<int:claim-check-in id="checkin"
@@ -33,7 +32,6 @@ The following example defines an incoming claim check transformer:
message-store="testMessageStore"
output-channel="output"/>
----
====
In the preceding configuration, the message that is received on the `input-channel` is persisted to the message store identified with the `message-store` attribute and indexed with a generated ID.
That ID is the claim check for that message.
@@ -44,7 +42,6 @@ You can access the message store manually and get the contents of the message, o
The following listing provides an overview of all available parameters of an incoming claim check transformer:
====
[source,xml]
----
<int:claim-check-in auto-startup="true" <1>
@@ -86,14 +83,12 @@ Optional.
<8> Defines a poller.
This element is not available inside a `Chain` element.
Optional.
====
[[claim-check-out]]
==== Outgoing Claim Check Transformer
== Outgoing Claim Check Transformer
An outgoing claim check transformer lets you transform a message with a claim check payload into a message with the original content as its payload.
====
[source,xml]
----
<int:claim-check-out id="checkout"
@@ -101,7 +96,6 @@ An outgoing claim check transformer lets you transform a message with a claim ch
message-store="testMessageStore"
output-channel="output"/>
----
====
In the preceding configuration, the message received on the `input-channel` should have a claim check as its payload.
The outgoing claim check transformer transforms it into a message with the original payload by querying the message store for a message identified by the provided claim check.
@@ -109,7 +103,6 @@ It then sends the newly checked-out message to the `output-channel`.
The following listing provides an overview of all available parameters of an outgoing claim check transformer:
====
[source,xml]
----
<int:claim-check-out auto-startup="true" <1>
@@ -156,9 +149,9 @@ Optional.
<9> Defines a poller.
This element is not available inside a `Chain` element.
Optional.
====
==== Claim Once
[[claim-once]]
== Claim Once
Sometimes, a particular message must be claimed only once.
As an analogy, consider process of handling airplane luggage.
@@ -172,7 +165,6 @@ This feature has an impact in terms of storage space, especially in the case of
Therefore, if you do not expect multiple claims to be made, we recommend that you set the `remove-message` attribute's value to `true`.
The following example show how to use the `remove-message` attribute:
====
[source,xml]
----
<int:claim-check-out id="checkout"
@@ -181,9 +173,9 @@ The following example show how to use the `remove-message` attribute:
output-channel="output"
remove-message="true"/>
----
====
==== A Word on Message Store
[[a-word-on-message-store]]
== A Word on Message Store
Although we rarely care about the details of the claim checks (as long as they work), you should know that the current implementation of the actual claim check (the pointer) in Spring Integration uses a UUID to ensure uniqueness.

View File

@@ -1,5 +1,5 @@
[[codec]]
=== Codec
= Codec
Version 4.2 of Spring Integration introduced the `Codec` abstraction.
Codecs encode and decode objects to and from `byte[]`.
@@ -11,14 +11,16 @@ We provide one implementation that uses https://github.com/EsotericSoftware/kryo
* `DecodingTransformer`
* `CodecMessageConverter`
==== `EncodingPayloadTransformer`
[[encodingpayloadtransformer]]
== `EncodingPayloadTransformer`
This transformer encodes the payload to a `byte[]` by using the codec.
It does not affect message headers.
See the https://docs.spring.io/spring-integration/api/org/springframework/integration/transformer/EncodingPayloadTransformer.html[Javadoc] for more information.
==== `DecodingTransformer`
[[decodingtransformer]]
== `DecodingTransformer`
This transformer decodes a `byte[]` by using the codec.
It needs to be configured with the `Class` to which the object should be decoded (or an expression that resolves to a `Class`).
@@ -26,14 +28,16 @@ If the resulting object is a `Message<?>`, inbound headers are not retained.
See the https://docs.spring.io/spring-integration/api/org/springframework/integration/transformer/DecodingTransformer.html[Javadoc] for more information.
==== `CodecMessageConverter`
[[codecmessageconverter]]
== `CodecMessageConverter`
Certain endpoints (such as TCP and Redis) have no concept of message headers.
They support the use of a `MessageConverter`, and the `CodecMessageConverter` can be used to convert a message to or from a `byte[]` for transmission.
See the https://docs.spring.io/spring-integration/api/org/springframework/integration/codec/CodecMessageConverter.html[Javadoc] for more information.
==== Kryo
[[kryo]]
== Kryo
Currently, this is the only implementation of `Codec`, and it provides two kinds of `Codec`:
@@ -49,7 +53,8 @@ The framework provides several custom serializers:
The first can be used with the `PojoCodec` by initializing it with the `FileKryoRegistrar`.
The second and third are used with the `MessageCodec`, which is initialized with the `MessageKryoRegistrar`.
===== Customizing Kryo
[[customizing-kryo]]
=== Customizing Kryo
By default, Kryo delegates unknown Java types to its `FieldSerializer`.
Kryo also registers default serializers for each primitive type, along with `String`, `Collection`, and `Map`.
@@ -57,7 +62,6 @@ Kryo also registers default serializers for each primitive type, along with `Str
A more efficient approach is to implement a custom serializer that is aware of the object's structure and can directly serialize selected primitive fields.
The following example shows such a serializer:
====
[source,java]
----
public class AddressSerializer extends Serializer<Address> {
@@ -75,7 +79,6 @@ public class AddressSerializer extends Serializer<Address> {
}
}
----
====
The `Serializer` interface exposes `Kryo`, `Input`, and `Output`, which provide complete control over which fields are included and other internal settings, as described in the https://github.com/EsotericSoftware/kryo[Kryo documentation].
@@ -87,19 +90,20 @@ Spring Integration currently defaults to using 40, 41, and 42 (for the file and
We recommend you start at 60, to allow for expansion in the framework.
You can override these framework defaults by configuring the registrars mentioned earlier.
====== Using a Custom Kryo Serializer
[[using-a-custom-kryo-serializer]]
==== Using a Custom Kryo Serializer
If you need custom serialization, see the https://github.com/EsotericSoftware/kryo[Kryo] documentation, because you need to use the native API to do the customization.
For an example, see the https://github.com/spring-projects/spring-integration/blob/main/spring-integration-core/src/main/java/org/springframework/integration/codec/kryo/MessageCodec.java[`MessageCodec`] implementation.
====== Implementing KryoSerializable
[[implementing-kryoserializable]]
==== Implementing KryoSerializable
If you have `write` access to the domain object source code, you can implement `KryoSerializable` as described https://github.com/EsotericSoftware/kryo#kryoserializable[here].
In this case, the class provides the serialization methods itself and no further configuration is required.
However, benchmarks have shown this is not quite as efficient as registering a custom serializer explicitly.
The following example shows a custom Kryo serializer:
====
[source,java]
----
public class Address implements KryoSerializable {
@@ -120,15 +124,14 @@ public class Address implements KryoSerializable {
}
}
----
====
You can also use this technique to wrap a serialization library other than Kryo.
====== Using the `@DefaultSerializer` Annotation
[[using-the-defaultserializer-annotation]]
==== Using the `@DefaultSerializer` Annotation
Kryo also provides a `@DefaultSerializer` annotation, as described https://github.com/EsotericSoftware/kryo#default-serializers[here].
====
[source,java]
----
@DefaultSerializer(SomeClassSerializer.class)
@@ -136,7 +139,6 @@ public class SomeClass {
// ...
}
----
====
If you have `write` access to the domain object, this may be a simpler way to specify a custom serializer.
Note that this does not register the class with an ID, which may make the technique unhelpful for certain situations.

View File

@@ -0,0 +1,12 @@
[[configuration]]
= Configuration
:page-section-summary-toc: 1
Spring Integration offers a number of configuration options.
Which option you choose depends upon your particular needs and at what level you prefer to work.
As with the Spring framework in general, you can mix and match the various techniques to suit the problem at hand.
For example, you can choose the XSD-based namespace for the majority of configuration and combine it with a handful of objects that you configure with annotations.
As much as possible, the two provide consistent naming.
The XML elements defined by the XSD schema match the names of the annotations, and the attributes of those XML elements match the names of annotation properties.
You can also use the API directly, but we expect most developers to choose one of the higher-level options or a combination of the namespace-based and annotation-driven configuration.

View File

@@ -0,0 +1,309 @@
[[annotations]]
= Annotation Support
In addition to the XML namespace support for configuring message endpoints, you can also use annotations.
First, Spring Integration provides the class-level `@MessageEndpoint` as a stereotype annotation, meaning that it is itself annotated with Spring's `@Component` annotation and is therefore automatically recognized as a bean definition by Spring's component scanning.
Even more important are the various method-level annotations.
They indicate that the annotated method is capable of handling a message.
The following example demonstrates both class-level and method-level annotations:
[source,java]
----
@MessageEndpoint
public class FooService {
@ServiceActivator
public void processMessage(Message message) {
...
}
}
----
Exactly what it means for the method to "`handle`" the Message depends on the particular annotation.
Annotations available in Spring Integration include:
* `@Aggregator` (see xref:overview.adoc#overview-endpoints-aggregator[Aggregator])
* `@Filter` (see xref:filter.adoc[Filter])
* `@Router` (see xref:router.adoc[Routers])
* `@ServiceActivator` (see xref:service-activator.adoc[Service Activator])
* `@Splitter` (see xref:splitter.adoc[Splitter])
* `@Transformer` (see xref:transformer.adoc[Transformer])
* `@InboundChannelAdapter` (see xref:overview.adoc#overview-endpoints-channeladapter[Channel Adapter])
* `@BridgeFrom` (see xref:bridge.adoc#bridge-annot[Configuring a Bridge with Java Configuration])
* `@BridgeTo` (see xref:bridge.adoc#bridge-annot[Configuring a Bridge with Java Configuration])
* `@MessagingGateway` (see xref:gateway.adoc[Messaging Gateways])
* `@IntegrationComponentScan` (see xref:overview.adoc#configuration-enable-integration[Configuration and `@EnableIntegration`])
NOTE: If you use XML configuration in combination with annotations, the `@MessageEndpoint` annotation is not required.
If you want to configure a POJO reference from the `ref` attribute of a `<service-activator/>` element, you can provide only the method-level annotations.
In that case, the annotation prevents ambiguity even when no method-level attribute exists on the `<service-activator/>` element.
In most cases, the annotated handler method should not require the `Message` type as its parameter.
Instead, the method parameter type can match the message's payload type, as the following example shows:
[source,java]
----
public class ThingService {
@ServiceActivator
public void bar(Thing thing) {
...
}
}
----
When the method parameter should be mapped from a value in the `MessageHeaders`, another option is to use the parameter-level `@Header` annotation.
In general, methods annotated with the Spring Integration annotations can accept the `Message` itself, the message payload, or a header value (with `@Header`) as the parameter.
In fact, the method can accept a combination, as the following example shows:
[source,java]
----
public class ThingService {
@ServiceActivator
public void otherThing(String payload, @Header("x") int valueX, @Header("y") int valueY) {
...
}
}
----
You can also use the `@Headers` annotation to provide all the message headers as a `Map`, as the following example shows:
[source,java]
----
public class ThingService {
@ServiceActivator
public void otherThing(String payload, @Headers Map<String, Object> headerMap) {
...
}
}
----
NOTE: The value of the annotation can also be a SpEL expression (for example, `someHeader.toUpperCase()`), which is useful when you wish to manipulate the header value before injecting it.
It also provides an optional `required` property, which specifies whether the attribute value must be available within the headers.
The default value for the `required` property is `true`.
For several of these annotations, when a message-handling method returns a non-null value, the endpoint tries to send a reply.
This is consistent across both configuration options (namespace and annotations) in that such an endpoint's output channel is used (if available), and the `REPLY_CHANNEL` message header value is used as a fallback.
TIP: The combination of output channels on endpoints and the reply channel message header enables a pipeline approach, where multiple components have an output channel and the final component allows the reply message to be forwarded to the reply channel (as specified in the original request message).
In other words, the final component depends on the information provided by the original sender and can dynamically support any number of clients as a result.
This is an example of the https://www.enterpriseintegrationpatterns.com/ReturnAddress.html[return address] pattern.
In addition to the examples shown here, these annotations also support the `inputChannel` and `outputChannel` properties, as the following example shows:
[source,java]
----
@Service
public class ThingService {
@ServiceActivator(inputChannel="input", outputChannel="output")
public void otherThing(String payload, @Headers Map<String, Object> headerMap) {
...
}
}
----
The processing of these annotations creates the same beans as the corresponding XML components -- `AbstractEndpoint` instances and `MessageHandler` instances (or `MessageSource` instances for the inbound channel adapter).
See xref:configuration/meta-annotations.adoc#annotations_on_beans[Annotations on `@Bean` Methods].
The bean names are generated from the following pattern: `[componentName].[methodName].[decapitalizedAnnotationClassShortName]`.
In the preceding example the bean name is `thingService.otherThing.serviceActivator` for the `AbstractEndpoint` and the same name with an additional `.handler` (`.source`) suffix for the `MessageHandler` (`MessageSource`) bean.
Such a name can be customized using an `@EndpointId` annotation alongside with these messaging annotations.
The `MessageHandler` instances (`MessageSource` instances) are also eligible to be tracked by xref:message-history.adoc[the message history].
Starting with version 4.0, all messaging annotations provide `SmartLifecycle` options (`autoStartup` and `phase`) to allow endpoint lifecycle control on application context initialization.
They default to `true` and `0`, respectively.
To change the state of an endpoint (such as `start()` or `stop()`), you can obtain a reference to the endpoint bean by using the `BeanFactory` (or autowiring) and invoke the methods.
Alternatively, you can send a command message to the `Control Bus` (see xref:groovy.adoc#groovy-control-bus[Control Bus]).
For these purposes, you should use the `beanName` mentioned earlier in the preceding paragraph.
[IMPORTANT]
=====
Channels automatically created after parsing the mentioned annotations (when no specific channel bean is configured), and the corresponding consumer endpoints, are declared as beans near the end of the context initialization.
These beans **can** be autowired in other services, but they have to be marked with the `@Lazy` annotation because the definitions, typically, won't yet be available during normal autowiring processing.
[source, java]
----
@Autowired
@Lazy
@Qualifier("someChannel")
MessageChannel someChannel;
...
@Bean
Thing1 dependsOnSPCA(@Qualifier("someInboundAdapter") @Lazy SourcePollingChannelAdapter someInboundAdapter) {
...
}
----
=====
Starting with version 6.0, all the messaging annotations are `@Repeatable` now, so several of the same type can be declared on the same service method with the meaning to create as many endpoints as those annotations are repeated:
[source, java]
----
@Transformer(inputChannel = "inputChannel1", outputChannel = "outputChannel1")
@Transformer(inputChannel = "inputChannel2", outputChannel = "outputChannel2")
public String transform(String input) {
return input.toUpperCase();
}
----
[[configuration-using-poller-annotation]]
== Using the `@Poller` Annotation
Before Spring Integration 4.0, messaging annotations required that the `inputChannel` be a reference to a `SubscribableChannel`.
For `PollableChannel` instances, an `<int:bridge/>` element was needed to configure an `<int:poller/>` and make the composite endpoint be a `PollingConsumer`.
Version 4.0 introduced the `@Poller` annotation to allow the configuration of `poller` attributes directly on the messaging annotations, as the following example shows:
[source,java]
----
public class AnnotationService {
@Transformer(inputChannel = "input", outputChannel = "output",
poller = @Poller(maxMessagesPerPoll = "${poller.maxMessagesPerPoll}", fixedDelay = "${poller.fixedDelay}"))
public String handle(String payload) {
...
}
}
----
The `@Poller` annotation provides only simple `PollerMetadata` options.
You can configure the `@Poller` annotation's attributes (`maxMessagesPerPoll`, `fixedDelay`, `fixedRate`, and `cron`) with property placeholders.
Also, starting with version 5.1, the `receiveTimeout` option for `PollingConsumer` s is also provided.
If it is necessary to provide more polling options (for example, `transaction`, `advice-chain`, `error-handler`, and others), you should configure the `PollerMetadata` as a generic bean and use its bean name as the `@Poller` 's `value` attribute.
In this case, no other attributes are allowed (they must be specified on the `PollerMetadata` bean).
Note, if `inputChannel` is a `PollableChannel` and no `@Poller` is configured, the default `PollerMetadata` is used (if it is present in the application context).
To declare the default poller by using a `@Configuration` annotation, use code similar to the following example:
[source,java]
----
@Bean(name = PollerMetadata.DEFAULT_POLLER)
public PollerMetadata defaultPoller() {
PollerMetadata pollerMetadata = new PollerMetadata();
pollerMetadata.setTrigger(new PeriodicTrigger(10));
return pollerMetadata;
}
----
The following example shows how to use the default poller:
[source,java]
----
public class AnnotationService {
@Transformer(inputChannel = "aPollableChannel", outputChannel = "output")
public String handle(String payload) {
...
}
}
----
The following example shows how to use a named poller:
[source,java]
----
@Bean
public PollerMetadata myPoller() {
PollerMetadata pollerMetadata = new PollerMetadata();
pollerMetadata.setTrigger(new PeriodicTrigger(1000));
return pollerMetadata;
}
----
The following example shows an endpoint that uses the default poller:
[source,java]
----
public class AnnotationService {
@Transformer(inputChannel = "aPollableChannel", outputChannel = "output"
poller = @Poller("myPoller"))
public String handle(String payload) {
...
}
}
----
Starting with version 4.3.3, the `@Poller` annotation has the `errorChannel` attribute for easier configuration of the underlying `MessagePublishingErrorHandler`.
This attribute plays the same role as `error-channel` in the `<poller>` XML component.
See xref:endpoint.adoc#endpoint-namespace[Endpoint Namespace Support] for more information.
The `poller()` attribute on the messaging annotations is mutually exclusive with the `reactive()` attribute.
See next section for more information.
[[configuration-using-reactive-annotation]]
== Using `@Reactive` Annotation
The `ReactiveStreamsConsumer` has been around since version 5.0, but it was applied only when an input channel for the endpoint is a `FluxMessageChannel` (or any `org.reactivestreams.Publisher` implementation).
Starting with version 5.3, its instance is also created by the framework when the target message handler is a `ReactiveMessageHandler` independently of the input channel type.
The `@Reactive` sub-annotation (similar to mentioned above `@Poller`) has been introduced for all the messaging annotations starting with version 5.5.
It accepts an optional `Function<? super Flux<Message<?>>, ? extends Publisher<Message<?>>>` bean reference and, independently of the input channel type and message handler, turns the target endpoint into the `ReactiveStreamsConsumer` instance.
The function is used from the `Flux.transform()` operator to apply some customization (`publishOn()`, `doOnNext()`, `log()`, `retry()` etc.) on a reactive stream source from the input channel.
The following example demonstrates how to change the publishing thread from the input channel independently of the final subscriber and producer to that `DirectChannel`:
[source,java]
----
@Bean
public Function<Flux<?>, Flux<?>> publishOnCustomizer() {
return flux -> flux.publishOn(Schedulers.parallel());
}
@ServiceActivator(inputChannel = "directChannel", reactive = @Reactive("publishOnCustomizer"))
public void handleReactive(String payload) {
...
}
----
The `reactive()` attribute on the messaging annotations is mutually exclusive with the `poller()` attribute.
See xref:configuration/annotations.adoc#configuration-using-poller-annotation[Using the `@Poller` Annotation] and xref:reactive-streams.adoc[Reactive Streams Support] for more information.
[[using-the-inboundchanneladapter-annotation]]
== Using the `@InboundChannelAdapter` Annotation
Version 4.0 introduced the `@InboundChannelAdapter` method-level annotation.
It produces a `SourcePollingChannelAdapter` integration component based on a `MethodInvokingMessageSource` for the annotated method.
This annotation is an analogue of the `<int:inbound-channel-adapter>` XML component and has the same restrictions: The method cannot have parameters, and the return type must not be `void`.
It has two attributes: `value` (the required `MessageChannel` bean name) and `poller` (an optional `@Poller` annotation, as xref:configuration/annotations.adoc#configuration-using-poller-annotation[described earlier]).
If you need to provide some `MessageHeaders`, use a `Message<?>` return type and use a `MessageBuilder` to build the `Message<?>`.
Using a `MessageBuilder` lets you configure the `MessageHeaders`.
The following example shows how to use an `@InboundChannelAdapter` annotation:
[source,java]
----
@InboundChannelAdapter("counterChannel")
public Integer count() {
return this.counter.incrementAndGet();
}
@InboundChannelAdapter(value = "fooChannel", poller = @Poller(fixed-rate = "5000"))
public String foo() {
return "foo";
}
----
Version 4.3 introduced the `channel` alias for the `value` annotation attribute, to provide better source code readability.
Also, the target `MessageChannel` bean is resolved in the `SourcePollingChannelAdapter` by the provided name (set by the `outputChannelName` option) on the first `receive()` call, not during the initialization phase.
It allows "`late binding`" logic: The target `MessageChannel` bean from the consumer perspective is created and registered a bit later than the `@InboundChannelAdapter` parsing phase.
The first example requires that the default poller has been declared elsewhere in the application context.
Using the `@MessagingGateway` Annotation
See xref:gateway.adoc#messaging-gateway-annotation[`@MessagingGateway` Annotation].
[[using-the-integrationcomponentscan-annotation]]
== Using the `@IntegrationComponentScan` Annotation
The standard Spring Framework `@ComponentScan` annotation does not scan interfaces for stereotype `@Component` annotations.
To overcome this limitation and allow the configuration of `@MessagingGateway` (see xref:gateway.adoc#messaging-gateway-annotation[`@MessagingGateway` Annotation]), we introduced the `@IntegrationComponentScan` mechanism.
This annotation must be placed with a `@Configuration` annotation and be customized to define its scanning options,
such as `basePackages` and `basePackageClasses`.
In this case, all discovered interfaces annotated with `@MessagingGateway` are parsed and registered as `GatewayProxyFactoryBean` instances.
All other class-based components are parsed by the standard `@ComponentScan`.

View File

@@ -0,0 +1,71 @@
[[global-properties]]
= Global Properties
Certain global framework properties can be overridden by providing a properties file on the classpath.
The default properties can be found in `org.springframework.integration.context.IntegrationProperties` class.
The following listing shows the default values:
[source]
----
spring.integration.channels.autoCreate=true <1>
spring.integration.channels.maxUnicastSubscribers=0x7fffffff <2>
spring.integration.channels.maxBroadcastSubscribers=0x7fffffff <3>
spring.integration.taskScheduler.poolSize=10 <4>
spring.integration.messagingTemplate.throwExceptionOnLateReply=false <5>
spring.integration.readOnly.headers= <6>
spring.integration.endpoints.noAutoStartup= <7>
spring.integration.channels.error.requireSubscribers=true <8>
spring.integration.channels.error.ignoreFailures=true <9>
----
<1> When true, `input-channel` instances are automatically declared as `DirectChannel` instances when not explicitly found in the application context.
<2> Sets the default number of subscribers allowed on, for example, a `DirectChannel`.
It can be used to avoid inadvertently subscribing multiple endpoints to the same channel.
You can override it on individual channels by setting the `max-subscribers` attribute.
<3> This property provides the default number of subscribers allowed on, for example, a `PublishSubscribeChannel`.
It can be used to avoid inadvertently subscribing more than the expected number of endpoints to the same channel.
You can override it on individual channels by setting the `max-subscribers` attribute.
<4> The number of threads available in the default `taskScheduler` bean.
See xref:configuration/namespace-taskscheduler.adoc[Configuring the Task Scheduler].
<5> When `true`, messages that arrive at a gateway reply channel throw an exception when the gateway is not expecting a reply (because the sending thread has timed out or already received a reply).
<6> A comma-separated list of message header names that should not be populated into `Message` instances during a header copying operation.
The list is used by the `DefaultMessageBuilderFactory` bean and propagated to the `IntegrationMessageHeaderAccessor` instances (see xref:message.adoc#message-header-accessor[`MessageHeaderAccessor` API]) used to build messages via `MessageBuilder` (see xref:message.adoc#message-builder[The `MessageBuilder` Helper Class]).
By default, only `MessageHeaders.ID` and `MessageHeaders.TIMESTAMP` are not copied during message building.
Since version 4.3.2.
<7> A comma-separated list of `AbstractEndpoint` bean names patterns (`xxx*`, `*xxx`, `*xxx*` or `xxx*yyy`) that should not be started automatically during application startup.
You can manually start these endpoints later by their bean name through a `Control Bus` (see xref:groovy.adoc#groovy-control-bus[Control Bus]), by their role with the `SmartLifecycleRoleController` (see xref:endpoint.adoc#endpoint-roles[Endpoint Roles]), or by `Lifecycle` bean injection.
You can explicitly override the effect of this global property by specifying `auto-startup` XML annotation or the `autoStartup` annotation attribute or by calling `AbstractEndpoint.setAutoStartup()` in the bean definition.
Since version 4.3.12.
<8> A boolean flag to indicate that default global `errorChannel` must be configured with the `requireSubscribers` option.
Since version 5.4.3.
See xref:scatter-gather.adoc#scatter-gather-error-handling[Error Handling] for more information.
<9> A boolean flag to indicate that default global `errorChannel` must ignore dispatching errors and pass the message to the next handler.
Since version 5.5.
These properties can be overridden by adding a `/META-INF/spring.integration.properties` file to the classpath or an `IntegrationContextUtils.INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME` bean for the `org.springframework.integration.context.IntegrationProperties` instance.
You need not provide all the properties -- only those that you want to override.
Starting with version 5.1, all the merged global properties are printed in the logs after application context startup when a `DEBUG` logic level is turned on for the `org.springframework.integration` category.
The output looks like this:
[source]
----
Spring Integration global properties:
spring.integration.endpoints.noAutoStartup=fooService*
spring.integration.taskScheduler.poolSize=20
spring.integration.channels.maxUnicastSubscribers=0x7fffffff
spring.integration.channels.autoCreate=true
spring.integration.channels.maxBroadcastSubscribers=0x7fffffff
spring.integration.readOnly.headers=
spring.integration.messagingTemplate.throwExceptionOnLateReply=true
----

View File

@@ -0,0 +1,245 @@
[[message-mapping-rules]]
= Message Mapping Rules and Conventions
Spring Integration implements a flexible facility to map messages to methods and their arguments without providing extra configuration, by relying on some default rules and defining certain conventions.
The examples in the following sections articulate the rules.
[[sample-scenarios]]
== Sample Scenarios
The following example shows a single un-annotated parameter (object or primitive) that is not a `Map` or a `Properties` object with a non-void return type:
[source,java]
----
public String doSomething(Object o);
----
The input parameter is a message payload.
If the parameter type is not compatible with a message payload, an attempt is made to convert it by using a conversion service provided by Spring 3.0.
The return value is incorporated as a payload of the returned message.
The following example shows a single un-annotated parameter (object or primitive)that is not a `Map` or a `Properties` with a `Message` return type:
[source,java]
----
public Message doSomething(Object o);
----
The input parameter is a message payload.
If the parameter type is not compatible with a message payload, an attempt is made to convert it by using a conversion service provided by Spring 3.0.
The return value is a newly constructed message that is sent to the next destination.
The following example shows a single parameter that is a message (or one of its subclasses) with an arbitrary object or primitive return type:
[source,java]
----
public int doSomething(Message msg);
----
The input parameter is itself a `Message`.
The return value becomes a payload of the `Message` that is sent to the next destination.
The following example shows a single parameter that is a `Message` (or one of its subclasses) with a `Message` (or one of its subclasses) as the return type:
[source,java]
----
public Message doSomething(Message msg);
----
The input parameter is itself a `Message`.
The return value is a newly constructed `Message` that is sent to the next destination.
The following example shows a single parameter of type `Map` or `Properties` with a `Message` as the return type:
[source,java]
----
public Message doSomething(Map m);
----
This one is a bit interesting.
Although, at first, it might seem like an easy mapping straight to message headers, preference is always given to a `Message` payload.
This means that if a `Message` payload is of type `Map`, this input argument represents a `Message` payload.
However, if the `Message` payload is not of type `Map`, the conversion service does not try to convert the payload, and the input argument is mapped to message headers.
The following example shows two parameters, where one of them is an arbitrary type (an object or a primitive) that is not a `Map` or a `Properties` object and the other is of type `Map` or `Properties` type (regardless of the return):
[source,java]
----
public Message doSomething(Map h, <T> t);
----
This combination contains two input parameters where one of them is of type `Map`.
The non-`Map` parameters (regardless of the order) are mapped to a `Message` payload and the `Map` or `Properties` (regardless of the order) is mapped to message headers, giving you a nice POJO way of interacting with `Message` structure.
The following example shows no parameters (regardless of the return):
[source,java]
----
public String doSomething();
----
This message handler method is invoked based on the Message sent to the input channel to which this handler is connected.
However, no `Message` data is mapped, thus making the `Message` act as event or trigger to invoke the handler.
The output is mapped according to the rules xref:configuration/message-mapping-rules.adoc[described earlier].
The following example shows no parameters and a void return:
[source,java]
----
public void soSomething();
----
This example is the same as the previous example, but it produces no output.
[[annotation-based-mapping]]
== Annotation-based Mapping
Annotation-based mapping is the safest and least ambiguous approach to map messages to methods.
The following example shows how to explicitly map a method to a header:
[source,java]
----
public String doSomething(@Payload String s, @Header("someheader") String b)
----
As you can see later on, without an annotation this signature would result in an ambiguous condition.
However, by explicitly mapping the first argument to a `Message` payload and the second argument to a value of the `someheader` message header, we avoid any ambiguity.
The following example is nearly identical to the preceding example:
[source,java]
----
public String doSomething(@Payload String s, @RequestParam("something") String b)
----
`@RequestMapping` or any other non-Spring Integration mapping annotation is irrelevant and is therefore ignored, leaving the second parameter unmapped.
Although the second parameter could easily be mapped to a payload, there can only be one payload.
Therefore, the annotations keep this method from being ambiguous.
The following example shows another similar method that would be ambiguous were it not for annotations to clarify the intent:
[source,java]
----
public String foo(String s, @Header("foo") String b)
----
The only difference is that the first argument is implicitly mapped to the message payload.
The following example shows yet another signature that would definitely be treated as ambiguous without annotations, because it has more than two arguments:
[source,java]
----
public String soSomething(@Headers Map m, @Header("something") Map f, @Header("someotherthing") String bar)
----
This example would be especially problematic, because two of its arguments are `Map` instances.
However, with annotation-based mapping, the ambiguity is easily avoided.
In this example the first argument is mapped to all the message headers, while the second and third argument map to the values of the message headers named 'something' and 'someotherthing'.
The payload is not being mapped to any argument.
[[complex-scenarios]]
== Complex Scenarios
The following example uses multiple parameters:
Multiple parameters can create a lot of ambiguity in regards to determining the appropriate mappings.
The general advice is to annotate your method parameters with `@Payload`, `@Header`, and `@Headers`.
The examples in this section show ambiguous conditions that result in an exception being raised.
[source,java]
----
public String doSomething(String s, int i)
----
The two parameters are equal in weight.
Therefore, there is no way to determine which one is a payload.
The following example shows a similar problem, only with three parameters:
[source,java]
----
public String foo(String s, Map m, String b)
----
Although the Map could be easily mapped to message headers, there is no way to determine what to do with the two String parameters.
The following example shows another ambiguous method:
[source,java]
----
public String foo(Map m, Map f)
----
Although one might argue that one `Map` could be mapped to the message payload and the other one to the message headers, we cannot rely on the order.
TIP: Any method signature with more than one method argument that is not (`Map`, `<T>`) and with unannotated parameters results in an ambiguous condition and triggers an exception.
The next set of examples each show multiple methods that result in ambiguity.
Message handlers with multiple methods are mapped based on the same rules that are described earlier (in the examples).
However, some scenarios might still look confusing.
The following example shows multiple methods with legal (mappable and unambiguous) signatures:
[source,java]
----
public class Something {
public String doSomething(String str, Map m);
public String doSomething(Map m);
}
----
(Whether the methods have the same name or different names makes no difference).
The `Message` could be mapped to either method.
The first method would be invoked when the message payload could be mapped to `str` and the message headers could be mapped to `m`.
The second method could also be a candidate by mapping only the message headers to `m`.
To make matters worse, both methods have the same name.
At first, that might look ambiguous because of the following configuration:
[source,xml]
----
<int:service-activator input-channel="input" output-channel="output" method="doSomething">
<bean class="org.things.Something"/>
</int:service-activator>
----
It works because mappings are based on the payload first and everything else next.
In other words, the method whose first argument can be mapped to a payload takes precedence over all other methods.
Now consider an alternate example, which produces a truly ambiguous condition:
[source,java]
----
public class Something {
public String doSomething(String str, Map m);
public String doSomething(String str);
}
----
Both methods have signatures that could be mapped to a message payload.
They also have the same name.
Such handler methods will trigger an exception.
However, if the method names were different, you could influence the mapping with a `method` attribute (shown in the next example).
The following example shows the same example with two different method names:
[source,java]
----
public class Something {
public String doSomething(String str, Map m);
public String doSomethingElse(String str);
}
----
The following example shows how to use the `method` attribute to dictate the mapping:
[source,xml]
----
<int:service-activator input-channel="input" output-channel="output" method="doSomethingElse">
<bean class="org.bar.Foo"/>
</int:service-activator>
----
Because the configuration explicitly maps the `doSomethingElse` method, we have eliminated the ambiguity.

View File

@@ -0,0 +1,176 @@
[[meta-annotations]]
= Messaging Meta-Annotations
Starting with version 4.0, all messaging annotations can be configured as meta-annotations and all user-defined messaging annotations can define the same attributes to override their default values.
In addition, meta-annotations can be configured hierarchically, as the following example shows:
[source,java]
----
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@ServiceActivator(inputChannel = "annInput", outputChannel = "annOutput")
public @interface MyServiceActivator {
String[] adviceChain = { "annAdvice" };
}
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@MyServiceActivator
public @interface MyServiceActivator1 {
String inputChannel();
String outputChannel();
}
...
@MyServiceActivator1(inputChannel = "inputChannel", outputChannel = "outputChannel")
public Object service(Object payload) {
...
}
----
Configuring meta-annotations hierarchically lets users set defaults for various attributes and enables isolation of framework Java dependencies to user annotations, avoiding their use in user classes.
If the framework finds a method with a user annotation that has a framework meta-annotation, it is treated as if the method were annotated directly with the framework annotation.
[[annotations_on_beans]]
== Annotations on `@Bean` Methods
Starting with version 4.0, you can configure messaging annotations on `@Bean` method definitions in `@Configuration` classes, to produce message endpoints based on the beans, not the methods.
It is useful when `@Bean` definitions are "`out-of-the-box`" `MessageHandler` instances (`AggregatingMessageHandler`, `DefaultMessageSplitter`, and others), `Transformer` instances (`JsonToObjectTransformer`, `ClaimCheckOutTransformer`, and others), and `MessageSource` instances (`FileReadingMessageSource`, `RedisStoreMessageSource`, and others).
The following example shows how to use messaging annotations with `@Bean` annotations:
[source,java]
----
@Configuration
@EnableIntegration
public class MyFlowConfiguration {
@Bean
@InboundChannelAdapter(value = "inputChannel", poller = @Poller(fixedDelay = "1000"))
public MessageSource<String> consoleSource() {
return CharacterStreamReadingMessageSource.stdin();
}
@Bean
@Transformer(inputChannel = "inputChannel", outputChannel = "httpChannel")
public ObjectToMapTransformer toMapTransformer() {
return new ObjectToMapTransformer();
}
@Bean
@ServiceActivator(inputChannel = "httpChannel")
public HttpRequestExecutingMessageHandler httpHandler() {
HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler("https://foo/service");
handler.setExpectedResponseType(String.class);
handler.setOutputChannelName("outputChannel");
return handler;
}
@Bean
@ServiceActivator(inputChannel = "outputChannel")
public LoggingHandler loggingHandler() {
return new LoggingHandler("info");
}
}
----
Version 5.0 introduced support for a `@Bean` annotated with `@InboundChannelAdapter` that returns `java.util.function.Supplier`, which can produce either a POJO or a `Message`.
The following example shows how to use that combination:
[source,java]
----
@Configuration
@EnableIntegration
public class MyFlowConfiguration {
@Bean
@InboundChannelAdapter(value = "inputChannel", poller = @Poller(fixedDelay = "1000"))
public Supplier<String> pojoSupplier() {
return () -> "foo";
}
@Bean
@InboundChannelAdapter(value = "inputChannel", poller = @Poller(fixedDelay = "1000"))
public Supplier<Message<String>> messageSupplier() {
return () -> new GenericMessage<>("foo");
}
}
----
The meta-annotation rules work on `@Bean` methods as well (the `@MyServiceActivator` annotation xref:configuration/meta-annotations.adoc[described earlier] can be applied to a `@Bean` definition).
NOTE: When you use these annotations on consumer `@Bean` definitions, if the bean definition returns an appropriate `MessageHandler` (depending on the annotation type), you must set attributes (such as `outputChannel`, `requiresReply`, `order`, and others), on the `MessageHandler` `@Bean` definition itself.
Only the following annotation attributes are used: `adviceChain`, `autoStartup`, `inputChannel`, `phase`, and `poller`.
All other attributes are for the handler.
NOTE: The bean names are generated with the following algorithm:
* The `MessageHandler` (`MessageSource`) `@Bean` gets its own standard name from the method name or `name` attribute on the `@Bean`.
This works as though there were no messaging annotation on the `@Bean` method.
* The `AbstractEndpoint` bean name is generated with the following pattern: `[@Bean name].[decapitalizedAnnotationClassShortName]`.
For example, the `SourcePollingChannelAdapter` endpoint for the `consoleSource()` definition xref:configuration/meta-annotations.adoc#annotations_on_beans[shown earlier] gets a bean name of `consoleSource.inboundChannelAdapter`.
Unlike with POJO methods, the bean method name is not included in the endpoint bean name.
See also xref:overview.adoc#endpoint-bean-names[Endpoint Bean Names].
* If `@Bean` cannot be used directly in the target endpoint (not an instance of a `MessageSource`, `AbstractReplyProducingMessageHandler` or `AbstractMessageRouter`), a respective `AbstractStandardMessageHandlerFactoryBean` is registered to delegate to this `@Bean`.
The bean name for this wrapper is generated with the following pattern: `[@Bean name].[decapitalizedAnnotationClassShortName].[handler (or source)]`.
IMPORTANT: When using these annotations on `@Bean` definitions, the `inputChannel` must reference a declared bean.
Channels are automatically declared if not present in the application context yet.
[NOTE]
=====
With Java configuration, you can use any `@Conditional` (for example, `@Profile`) definition on the `@Bean` method level to skip the bean registration for some conditional reason.
The following example shows how to do so:
[source,java]
----
@Bean
@ServiceActivator(inputChannel = "skippedChannel")
@Profile("thing")
public MessageHandler skipped() {
return System.out::println;
}
----
Together with the existing Spring container logic, the messaging endpoint bean (based on the `@ServiceActivator` annotation), is also not registered.
=====
[[creating-a-bridge-with-annotations]]
== Creating a Bridge with Annotations
Starting with version 4.0, Java configuration provides the `@BridgeFrom` and `@BridgeTo` `@Bean` method annotations to mark `MessageChannel` beans in `@Configuration` classes.
These really exists for completeness, providing a convenient mechanism to declare a `BridgeHandler` and its message endpoint configuration:
[source,java]
----
@Bean
public PollableChannel bridgeFromInput() {
return new QueueChannel();
}
@Bean
@BridgeFrom(value = "bridgeFromInput", poller = @Poller(fixedDelay = "1000"))
public MessageChannel bridgeFromOutput() {
return new DirectChannel();
}
@Bean
public QueueChannel bridgeToOutput() {
return new QueueChannel();
}
@Bean
@BridgeTo("bridgeToOutput")
public MessageChannel bridgeToInput() {
return new DirectChannel();
}
----
You can use these annotations as meta-annotations as well.
[[advising-annotated-endpoints]]
== Advising Annotated Endpoints
See xref:handler-advice/advising-with-annotations.adoc[Advising Endpoints Using Annotations].

View File

@@ -0,0 +1,49 @@
[[namespace-taskscheduler]]
= Configuring the Task Scheduler
In Spring Integration, the `ApplicationContext` plays the central role of a message bus, and you need to consider only a couple of configuration options.
First, you may want to control the central `TaskScheduler` instance.
You can do so by providing a single bean named `taskScheduler`.
This is also defined as a constant, as follows:
[source,java]
----
IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME
----
By default, Spring Integration relies on an instance of `ThreadPoolTaskScheduler`, as described in the https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#scheduling[Task Execution and Scheduling] section of the Spring Framework reference manual.
That default `TaskScheduler` starts up automatically with a pool of ten threads, but see xref:configuration/global-properties.adoc[Global Properties].
If you provide your own `TaskScheduler` instance instead, you can set the 'autoStartup' property to `false` or provide your own pool size value.
When polling consumers provide an explicit task executor reference in their configuration, the invocation of the handler methods happens within that executor's thread pool and not the main scheduler pool.
However, when no task executor is provided for an endpoint's poller, it is invoked by one of the main scheduler's threads.
CAUTION: Do not run long-running tasks on poller threads.
Use a task executor instead.
If you have a lot of polling endpoints, you can cause thread starvation, unless you increase the pool size.
Also, polling consumers have a default `receiveTimeout` of one second.
Since the poller thread blocks for this time, we recommend that you use a task executor when many such endpoints exist, again to avoid starvation.
Alternatively, you can reduce the `receiveTimeout`.
NOTE: An endpoint is a Polling Consumer if its input channel is one of the queue-based (that is, pollable) channels.
Event-driven consumers are those having input channels that have dispatchers instead of queues (in other words, they are subscribable).
Such endpoints have no poller configuration, since their handlers are invoked directly.
[IMPORTANT]
=====
When running in a JEE container, you may need to use Spring's `TimerManagerTaskScheduler`, as described https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#scheduling-task-scheduler-implementations[here], instead of the default `taskScheduler`.
To do so, define a bean with the appropriate JNDI name for your environment, as the following example shows:
[source,xml]
----
<bean id="taskScheduler" class="org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler">
<property name="jndiName" value="tm/MyTimerManager" />
<property name="resourceRef" value="true" />
</bean>
----
=====
IMPORTANT: When a custom `TaskScheduler` is configured in the application context (like the above mentioned `DefaultManagedTaskScheduler`), it is recommended to supply it with a `MessagePublishingErrorHandler` (`integrationMessagePublishingErrorHandler` bean) to be able to handle exceptions as `ErrorMessage`s sent to the error channel, as is done with the default `TaskScheduler` bean provided by the framework.
See also xref:scatter-gather.adoc#scatter-gather-error-handling[Error Handling] for more information.

View File

@@ -0,0 +1,80 @@
[[configuration-namespace]]
= Namespace Support
You can configure Spring Integration components with XML elements that map directly to the terminology and concepts of enterprise integration.
In many cases, the element names match those of the https://www.enterpriseintegrationpatterns.com/[_Enterprise Integration Patterns_] book.
To enable Spring Integration's core namespace support within your Spring configuration files, add the following namespace reference and schema mapping in your top-level 'beans' element:
// We lose coloring here, but we want to bold the lines we're talking about...
[subs="+quotes"]
----
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
*xmlns:int="http://www.springframework.org/schema/integration"*
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
*http://www.springframework.org/schema/integration*
*https://www.springframework.org/schema/integration/spring-integration.xsd*">
----
(We have emphasized the lines that are particular to Spring Integration.)
You can choose any name after "xmlns:".
We use `int` (short for Integration) for clarity, but you might prefer another abbreviation.
On the other hand, if you use an XML editor or IDE support, the availability of auto-completion may convince you to keep the longer name for clarity.
Alternatively, you can create configuration files that use the Spring Integration schema as the primary namespace, as the following example shows:
// We lose coloring here, but we want to bold the lines we're talking about...
[subs=+quotes]
----
*<beans:beans xmlns="http://www.springframework.org/schema/integration"*
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
*http://www.springframework.org/schema/integration*
*https://www.springframework.org/schema/integration/spring-integration.xsd*">
----
(We have emphasized the lines that are particular to Spring Integration.)
When using this alternative, no prefix is necessary for the Spring Integration elements.
On the other hand, if you define a generic Spring bean within the same configuration file, the bean element requires a prefix (`<beans:bean .../>`).
Since it is generally a good idea to modularize the configuration files themselves (based on responsibility or architectural layer), you may find it appropriate to use the latter approach in the integration-focused configuration files, since generic beans are seldom necessary within those files.
For the purposes of this documentation, we assume the integration namespace is the primary.
Spring Integration provides many other namespaces.
In fact, each adapter type (JMS, file, and so on) that provides namespace support defines its elements within a separate schema.
In order to use these elements, add the necessary namespaces with an `xmlns` entry and the corresponding `schemaLocation` mapping.
For example, the following root element shows several of these namespace declarations:
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-file="http://www.springframework.org/schema/integration/file"
xmlns:int-jms="http://www.springframework.org/schema/integration/jms"
xmlns:int-mail="http://www.springframework.org/schema/integration/mail"
xmlns:int-ws="http://www.springframework.org/schema/integration/ws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
https://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/file
https://www.springframework.org/schema/integration/file/spring-integration-file.xsd
http://www.springframework.org/schema/integration/jms
https://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd
http://www.springframework.org/schema/integration/mail
https://www.springframework.org/schema/integration/mail/spring-integration-mail.xsd
http://www.springframework.org/schema/integration/ws
https://www.springframework.org/schema/integration/ws/spring-integration-ws.xsd">
...
</beans>
----
This reference manual provides specific examples of the various elements in their corresponding chapters.
Here, the main thing to recognize is the consistency of the naming for each namespace URI and schema location.

View File

@@ -1,33 +1,32 @@
[[content-enricher]]
=== Content Enricher
= Content Enricher
At times, you may have a requirement to enhance a request with more information than was provided by the target system.
The https://www.enterpriseintegrationpatterns.com/DataEnricher.html[data enricher] pattern describes various scenarios as well as the component (Enricher) that lets you address such requirements.
The Spring Integration `Core` module includes two enrichers:
* <<header-enricher,Header Enricher>>
* <<payload-enricher,Payload Enricher>>
* xref:content-enrichment.adoc#header-enricher[Header Enricher]
* xref:content-enrichment.adoc#payload-enricher[Payload Enricher]
It also includes three adapter-specific header enrichers:
* <<./xml.adoc#xml-xpath-header-enricher,XPath Header Enricher (XML Module)>>
* <<./mail.adoc#mail-namespace,Mail Header Enricher (Mail Module)>>
* <<./xmpp.adoc#xmpp-message-outbound-channel-adapter,XMPP Header Enricher (XMPP Module)>>
* xref:xml/xpath-header-enricher.adoc[XPath Header Enricher (XML Module)]
* xref:mail.adoc#mail-namespace[Mail Header Enricher (Mail Module)]
* xref:xmpp.adoc#xmpp-message-outbound-channel-adapter[XMPP Header Enricher (XMPP Module)]
See the adapter-specific sections of this reference manual to learn more about those adapters.
For more information regarding expressions support, see <<./spel.adoc#spel,Spring Expression Language (SpEL)>>.
For more information regarding expressions support, see xref:spel.adoc[Spring Expression Language (SpEL)].
[[header-enricher]]
==== Header Enricher
== Header Enricher
If you need do nothing more than add headers to a message and the headers are not dynamically determined by the message content, referencing a custom implementation of a transformer may be overkill.
For that reason, Spring Integration provides support for the header enricher pattern.
It is exposed through the `<header-enricher>` element.
The following example shows how to use it:
====
[source,xml]
----
<int:header-enricher input-channel="in" output-channel="out">
@@ -35,7 +34,6 @@ The following example shows how to use it:
<int:header name="bar" ref="someBean"/>
</int:header-enricher>
----
====
The header enricher also provides helpful sub-elements to set well known header names, as the following example shows:
@@ -54,16 +52,16 @@ The header enricher also provides helpful sub-elements to set well known header
The preceding configuration shows that, for well known headers (such as `errorChannel`, `correlationId`, `priority`, `replyChannel`, `routing-slip`, and others), instead of using generic `<header>` sub-elements where you would have to provide both header 'name' and 'value', you can use convenient sub-elements to set those values directly.
Starting with version 4.1, the header enricher provides a `routing-slip` sub-element.
See <<./router.adoc#routing-slip,Routing Slip>> for more information.
See xref:router/routing-slip.adoc[Routing Slip] for more information.
===== POJO Support
[[pojo-support]]
=== POJO Support
Often, a header value cannot be defined statically and has to be determined dynamically based on some content in the message.
That is why the header enricher lets you also specify a bean reference by using the `ref` and `method` attributes.
The specified method calculates the header value.
Consider the following configuration and a bean with a method that modifies a `String`:
====
[source,xml]
----
<int:header-enricher input-channel="in" output-channel="out">
@@ -82,11 +80,9 @@ public class MyBean {
}
}
----
====
You can also configure your POJO as an inner bean, as the following example shows:
====
[source,xml]
----
<int:header-enricher input-channel="inputChannel" output-channel="outputChannel">
@@ -95,11 +91,9 @@ You can also configure your POJO as an inner bean, as the following example show
</int:header>
</int:header-enricher>
----
====
You can similarly point to a Groovy script, as the following example shows:
====
[source,xml]
----
<int:header-enricher input-channel="inputChannel" output-channel="outputChannel">
@@ -108,9 +102,9 @@ You can similarly point to a Groovy script, as the following example shows:
</int:header>
</int:header-enricher>
----
====
===== SpEL Support
[[spel-support]]
=== SpEL Support
In Spring Integration 2.0, we introduced the convenience of the https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions[Spring Expression Language (SpEL)] to help configure many different components.
The header enricher is one of them.
@@ -131,11 +125,11 @@ By using SpEL for such simple cases, you no longer have to provide a separate cl
All you need do is configured the `expression` attribute with a valid SpEL expression.
The 'payload' and 'headers' variables are bound to the SpEL evaluation context, giving you full access to the incoming message.
===== Configuring a Header Enricher with Java Configuration
[[configuring-a-header-enricher-with-java-configuration]]
=== Configuring a Header Enricher with Java Configuration
The following two examples show how to use Java Configuration for header enrichers:
====
[source, java]
----
@Bean
@@ -160,16 +154,15 @@ public HeaderEnricher enrichHeaders() {
return enricher;
}
----
====
The first example adds a single literal header.
The second example adds two headers, a literal header and one based on a SpEL expression.
===== Configuring a Header Enricher with the Java DSL
[[configuring-a-header-enricher-with-the-java-dsl]]
=== Configuring a Header Enricher with the Java DSL
The following example shows Java DSL Configuration for a header enricher:
====
[source, java]
----
@Bean
@@ -181,10 +174,9 @@ public IntegrationFlow enrichHeadersInFlow() {
.handle(...);
}
----
====
[[header-channel-registry]]
===== Header Channel Registry
=== Header Channel Registry
Starting with Spring Integration 3.0, a new sub-element `<int:header-channels-to-string/>` is available.
It has no attributes.
@@ -205,16 +197,13 @@ The `runReaper()` method cancels the current scheduled task and runs the reaper
The task is then scheduled to run again based on the current delay.
These methods can be invoked directly by getting a reference to the registry, or you can send a message with, for example, the following content to a control bus:
====
[source]
----
"@integrationHeaderChannelRegistry.runReaper()"
----
====
This sub-element is a convenience, and is the equivalent of specifying the following configuration:
====
[source,xml]
----
<int:reply-channel
@@ -224,12 +213,10 @@ This sub-element is a convenience, and is the equivalent of specifying the follo
expression="@integrationHeaderChannelRegistry.channelToChannelName(headers.errorChannel)"
overwrite="true" />
----
====
Starting with version 4.1, you can now override the registry's configured reaper delay so that the channel mapping is retained for at least the specified time, regardless of the reaper delay.
The following example shows how to do so:
====
[source,xml]
----
<int:header-enricher input-channel="inputTtl" output-channel="next">
@@ -241,13 +228,12 @@ The following example shows how to do so:
time-to-live-expression="headers['channelTTL'] ?: 120000" />
</int:header-enricher>
----
====
In the first case, the time to live for every header channel mapping will be two minutes.
In the second case, the time to live is specified in the message header and uses an Elvis operator to use two minutes if there is no header.
[[payload-enricher]]
==== Payload Enricher
== Payload Enricher
In certain situations, the header enricher, as discussed earlier, may not be sufficient and payloads themselves may have to be enriched with additional information.
For example, order messages that enter the Spring Integration messaging system have to look up the order's customer based on the provided customer number and then enrich the original payload with that information.
@@ -274,7 +260,7 @@ In many cases, you could use a payload enricher or a generic transformer impleme
You should familiarize yourself with all transformation-capable components that are provided by Spring Integration and carefully select the implementation that semantically fits your business case best.
[[payload-enricher-configuration]]
===== Configuration
=== Configuration
The following example shows all available configuration options for the payload enricher:
@@ -355,16 +341,15 @@ Starting with version 4.1, you can also specify an optional `null-result-express
When the `enricher` returns null, it is evaluated, and the output of the evaluation is returned instead.
[[payload-enricher-examples]]
===== Examples
=== Examples
This section contains several examples of using a payload enricher in various situations.
TIP: The code samples shown here are part of the Spring Integration Samples project.
See <<./samples.adoc#samples,Spring Integration Samples>>.
See xref:samples.adoc#samples-impl[Spring Integration Samples].
In the following example, a `User` object is passed as the payload of the `Message`:
====
[source,xml]
----
<int:enricher id="findUserEnricher"
@@ -374,19 +359,18 @@ In the following example, a `User` object is passed as the payload of the `Messa
<int:property name="password" expression="payload.password"/>
</int:enricher>
----
====
The `User` has several properties, but only the `username` is set initially.
The enricher's `request-channel` attribute is configured to pass the `User` to the `findUserServiceChannel`.
Through the implicitly set `reply-channel`, a `User` object is returned and, by using the `property` sub-element, properties from the reply are extracted and used to enrich the original payload.
===== How Do I Pass Only a Subset of Data to the Request Channel?
[[how-do-i-pass-only-a-subset-of-data-to-the-request-channel?]]
=== How Do I Pass Only a Subset of Data to the Request Channel?
When using a `request-payload-expression` attribute, a single property of the payload instead of the full message can be passed on to the request channel.
In the following example, the username property is passed on to the request channel:
====
[source,xml]
----
<int:enricher id="findUserByUsernameEnricher"
@@ -397,15 +381,14 @@ In the following example, the username property is passed on to the request chan
<int:property name="password" expression="payload.password"/>
</int:enricher>
----
====
Keep in mind that, although only the username is passed, the resulting message to the request channel contains the full set of `MessageHeaders`.
====== How Can I Enrich Payloads that Consist of Collection Data?
[[how-can-i-enrich-payloads-that-consist-of-collection-data?]]
==== How Can I Enrich Payloads that Consist of Collection Data?
In the following example, instead of a `User` object, a `Map` is passed in:
====
[source,xml]
----
<int:enricher id="findUserWithMapEnricher"
@@ -415,17 +398,16 @@ In the following example, instead of a `User` object, a `Map` is passed in:
<int:property name="user" expression="payload"/>
</int:enricher>
----
====
The `Map` contains the username under the `username` map key.
Only the `username` is passed on to the request channel.
The reply contains a full `User` object, which is ultimately added to the `Map` under the `user` key.
===== How Can I Enrich Payloads with Static Information without Using a Request Channel?
[[how-can-i-enrich-payloads-with-static-information-without-using-a-request-channel?]]
=== How Can I Enrich Payloads with Static Information without Using a Request Channel?
The following example does not use a request channel at all but solely enriches the message's payload with static values:
====
[source,xml]
----
<int:enricher id="userEnricher"
@@ -436,7 +418,6 @@ The following example does not use a request channel at all but solely enriches
<int:property name="user.age" value="42"/>
</int:enricher>
----
====
Note that the word, 'static', is used loosely here.
You can still use SpEL expressions for setting those values.

View File

@@ -1,17 +1,15 @@
[[control-bus]]
=== Control Bus
= Control Bus
As described in the https://www.enterpriseintegrationpatterns.com/[_Enterprise Integration Patterns_] (EIP) book, the idea behind the control bus is that the same messaging system can be used for monitoring and managing the components within the framework as is used for "`application-level`" messaging.
In Spring Integration, we build upon the adapters described above so that you can send messages as a means of invoking exposed operations.
The following example shows how to configure a control bus with XML:
====
[source,xml]
----
<int:control-bus input-channel="operationChannel"/>
----
====
The control bus has an input channel that can be accessed for invoking operations on the beans in the application context.
It also has all the common properties of a service activating endpoint.
@@ -27,20 +25,17 @@ Resolution of any particular instance within the application context is achieved
To do so, provide the bean name with the SpEL prefix for beans (`@`).
For example, to execute a method on a Spring Bean, a client could send a message to the operation channel as follows:
====
[source,java]
----
Message operation = MessageBuilder.withPayload("@myServiceBean.shutdown()").build();
operationChannel.send(operation)
----
====
The root of the context for the expression is the `Message` itself, so you also have access to the `payload` and `headers` as variables within your expression.
This is consistent with all the other expression support in Spring Integration endpoints.
With Java annotations, you can configured the control bus as follows:
====
[source,java]
----
@Bean
@@ -49,11 +44,9 @@ public ExpressionControlBusFactoryBean controlBus() {
return new ExpressionControlBusFactoryBean();
}
----
====
Similarly, you can configure Java DSL flow definitions as follows:
====
[source,java]
----
@Bean
@@ -63,11 +56,9 @@ public IntegrationFlow controlBusFlow() {
.get();
}
----
====
If you prefer to use lambdas with automatic `DirectChannel` creation, you can create a control bus as follows:
====
[source,java]
----
@Bean
@@ -75,6 +66,5 @@ public IntegrationFlow controlBus() {
return IntegrationFlowDefinition::controlBus;
}
----
====
In this case, the channel is named `controlBus.input`.

View File

@@ -1,5 +1,6 @@
[[spring-integration-core-messaging]]
= Core Messaging
:page-section-summary-toc: 1
[[spring-integration-core-msg]]
This section covers all aspects of the core messaging API in Spring Integration.
@@ -8,14 +9,6 @@ It also covers many of the enterprise integration patterns, such as filter, rout
This section also contains material about system management, including the control bus and message history support.
[[messaging-channels-section]]
== Messaging Channels
// BE SURE TO PRECEDE ALL include:: with a blank line - see https://github.com/asciidoctor/asciidoctor/issues/1297
include::./channel.adoc[]
include::./polling-consumer.adoc[]
include::./channel-adapter.adoc[]
include::./bridge.adoc[]

View File

@@ -1,14 +1,16 @@
[[debezium]]
== Debezium Support
= Debezium Support
https://debezium.io/documentation/reference/development/engine.html[Debezium Engine], Change Data Capture (CDC) inbound channel adapter.
The `DebeziumMessageProducer` allows capturing database change events, converting them into messages and streaming later to the outbound channels.
You need to include the spring integration Debezium dependency to your project:
====
[tabs]
======
Maven::
+
[source, xml, subs="normal", role="primary"]
.Maven
----
<dependency>
<groupId>org.springframework.integration</groupId>
@@ -16,19 +18,23 @@ You need to include the spring integration Debezium dependency to your project:
<version>{project-version}</version>
</dependency>
----
Gradle::
+
[source, groovy, subs="normal", role="secondary"]
.Gradle
----
compile "org.springframework.integration:spring-integration-debezium:{project-version}"
----
====
======
You also need to include a https://debezium.io/documentation/reference/connectors/index.html[debezium connector] dependency for your input Database.
For example to use Debezium with PostgreSQL you will need the postgres debezium connector:
====
[source, xml, subs="normal", role="primary"]
.Maven
[tabs]
======
Maven::
+
[source, xml, role="primary"]
----
<dependency>
<groupId>io.debezium</groupId>
@@ -37,12 +43,14 @@ For example to use Debezium with PostgreSQL you will need the postgres debezium
</dependency>
----
[source, groovy, subs="normal", role="secondary"]
.Gradle
Gradle::
+
[source, groovy, role="secondary"]
----
compile "io.debezium:debezium-connector-postgres:{debezium-version}"
----
====
======
[NOTE]
====
@@ -50,7 +58,7 @@ Replace the `debezium-version` with the version compatible with the `spring-inte
====
[[debezium-inbound]]
=== Inbound Debezium Channel Adapter
== Inbound Debezium Channel Adapter
The Debezium adapter expects a pre-configured `DebeziumEngine.Builder<ChangeEvent<byte[], byte[]>>` instance.
@@ -61,7 +69,7 @@ The https://github.com/spring-cloud/stream-applications/tree/main/functions/supp
[TIP]
====
The <<debezium-java-dsl,Debezium Java DSL>> can create a `DebeziumMessageProducer` instance from a provided `DebeziumEngine.Builder`, as well as from a plain Debezium configuration (e.g. `java.util.Properties`).
The xref:debezium.adoc#debezium-java-dsl[Debezium Java DSL] can create a `DebeziumMessageProducer` instance from a provided `DebeziumEngine.Builder`, as well as from a plain Debezium configuration (e.g. `java.util.Properties`).
Later can be handy for some common use-cases with opinionated configuration and serialization formats.
====
@@ -82,11 +90,11 @@ By default, all headers are mapped.
The following code snippets demonstrate various configuration for this channel adapter:
==== Configuring with Java Configuration
[[configuring-with-java-configuration]]
=== Configuring with Java Configuration
The following Spring Boot application shows an example of how to configure the inbound adapter with Java configuration:
====
[source, java]
----
@SpringBootApplication
@@ -135,7 +143,6 @@ public class DebeziumJavaApplication {
<3> Like the key, the payload has a schema section and a payload value section.
The schema section contains the schema that describes the Envelope structure of the payload value section, including its nested fields.
Change events for operations that create, update or delete data all have a value payload with an envelope structure.
====
[TIP]
====
@@ -144,7 +151,6 @@ The `key.converter.schemas.enable=false` and/or `value.converter.schemas.enable=
Similarly, we can configure the `DebeziumMessageProducer` to process the incoming change events in batches:
====
[source, java]
----
@Bean
@@ -163,15 +169,13 @@ public void handler(List<ChangeEvent<Object, Object>> payload) {
System.out.println(payload);
}
----
====
[[debezium-java-dsl]]
=== Debezium Java DSL Support
== Debezium Java DSL Support
The `spring-integration-debezium` provides a convenient Java DSL fluent API via the `Debezium` factory and the `DebeziumMessageProducerSpec` implementations.
The Inbound Channel Adapter for Debezium Java DSL is:
====
[source, java]
----
DebeziumEngine.Builder<ChangeEvent<byte[], byte[]>> debeziumEngineBuilder = ...
@@ -182,11 +186,9 @@ The Inbound Channel Adapter for Debezium Java DSL is:
.enableBatch(false))
.handle(m -> System.out.println(new String((byte[]) m.getPayload())))
----
====
Or create an `DebeziumMessageProducerSpec` instance from native debezium configuration properties and default to `JSON` serialization formats.
====
[source, java]
----
Properties debeziumConfig = ...
@@ -194,11 +196,9 @@ Or create an `DebeziumMessageProducerSpec` instance from native debezium configu
.from(Debezium.inboundChannelAdapter(debeziumConfig))
.handle(m -> System.out.println(new String((byte[]) m.getPayload())))
----
====
The following Spring Boot application provides an example of configuring the inbound adapter with the Java DSL:
====
[source, java]
----
@SpringBootApplication
@@ -226,4 +226,3 @@ public class DebeziumJavaApplication {
}
----
====

View File

@@ -1,5 +1,5 @@
[[delayer]]
=== Delayer
= Delayer
A delayer is a simple endpoint that lets a message flow be delayed by a certain interval.
When a message is delayed, the original sender does not block.
@@ -9,26 +9,26 @@ On the contrary, in the typical case, a thread pool is used for the actual execu
This section contains several examples of configuring a delayer.
[[delayer-namespace]]
==== Configuring a Delayer
== Configuring a Delayer
The `<delayer>` element is used to delay the message flow between two message channels.
As with the other endpoints, you can provide the 'input-channel' and 'output-channel' attributes, but the delayer also has 'default-delay' and 'expression' attributes (and the 'expression' element) that determine the number of milliseconds by which each message should be delayed.
The following example delays all messages by three seconds:
====
[source,xml]
----
<int:delayer id="delayer" input-channel="input"
default-delay="3000" output-channel="output"/>
----
====
If you need to determine the delay for each message, you can also provide the SpEL expression by using the 'expression' attribute, as the following expression shows:
====
[tabs]
======
Java DSL::
+
[source, java, role="primary"]
.Java DSL
----
@Bean
public IntegrationFlow flow() {
@@ -41,8 +41,10 @@ public IntegrationFlow flow() {
.get();
}
----
Kotlin DSL::
+
[source, kotlin, role="secondary"]
.Kotlin DSL
----
@Bean
fun flow() =
@@ -55,8 +57,10 @@ fun flow() =
channel("output")
}
----
Java::
+
[source, java, role="secondary"]
.Java
----
@ServiceActivator(inputChannel = "input")
@Bean
@@ -68,13 +72,15 @@ public DelayHandler delayer() {
return handler;
}
----
XML::
+
[source, xml, role="secondary"]
.XML
----
<int:delayer id="delayer" input-channel="input" output-channel="output"
default-delay="3000" expression="headers['delay']"/>
----
====
======
In the preceding example, the three-second delay applies only when the expression evaluates to null for a given inbound message.
If you want to apply a delay only to messages that have a valid result of the expression evaluation, you can use a 'default-delay' of `0` (the default).
@@ -105,23 +111,20 @@ However, different results are achieved if the header is missing.
In the first case, the expression evaluates to `null`.
The second results in something similar to the following:
====
[source,java]
----
org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 8):
Field or property 'delay' cannot be found on object of type 'org.springframework.messaging.MessageHeaders'
----
====
Consequently, if there is a possibility of the header being omitted and you want to fall back to the default delay, it is generally more efficient (and recommended) using the indexer syntax instead of dot property accessor syntax, because detecting the null is faster than catching an exception.
=====
The delayer delegates to an instance of Spring's `TaskScheduler` abstraction.
The default scheduler used by the delayer is the `ThreadPoolTaskScheduler` instance provided by Spring Integration on startup.
See <<./configuration.adoc#namespace-taskscheduler,Configuring the Task Scheduler>>.
See xref:configuration/namespace-taskscheduler.adoc[Configuring the Task Scheduler].
If you want to delegate to a different scheduler, you can provide a reference through the delayer element's 'scheduler' attribute, as the following example shows:
====
[source,xml]
----
<int:delayer id="delayer" input-channel="input" output-channel="output"
@@ -130,7 +133,6 @@ If you want to delegate to a different scheduler, you can provide a reference th
<task:scheduler id="exampleTaskScheduler" pool-size="3"/>
----
====
TIP: If you configure an external `ThreadPoolTaskScheduler`, you can set `waitForTasksToCompleteOnShutdown = true` on this property.
It allows successful completion of 'delay' tasks that are already in the execution state (releasing the message) when the application is shutdown.
@@ -143,10 +145,10 @@ This handler allows processing an `Exception` from the thread of the scheduled t
By default, it uses an `org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler`, and you can see a stack trace in the logs.
You might want to consider using an `org.springframework.integration.channel.MessagePublishingErrorHandler`, which sends an `ErrorMessage` into an `error-channel`, either from the failed message's header or into the default `error-channel`.
This error handling is performed after a transaction rolls back (if present).
See <<delayer-release-failures>>.
See xref:delayer.adoc#delayer-release-failures[Release Failures].
[[delayer-message-store]]
==== Delayer and a Message Store
== Delayer and a Message Store
The `DelayHandler` persists delayed messages into the message group in the provided `MessageStore`.
(The 'groupId' is based on the required 'id' attribute of the `<delayer>` element.
@@ -168,7 +170,6 @@ You can use any custom `org.aopalliance.aop.Advice` implementation within the `<
The `<transactional>` element defines a simple advice chain that has only the transactional advice.
The following example shows an `advice-chain` within a `<delayer>`:
====
[source,xml]
----
<int:delayer id="delayer" input-channel="input" output-channel="output"
@@ -184,28 +185,25 @@ The following example shows an `advice-chain` within a `<delayer>`:
</int:advice-chain>
</int:delayer>
----
====
The `DelayHandler` can be exported as a JMX `MBean` with managed operations (`getDelayedMessageCount` and `reschedulePersistedMessages`), which allows the rescheduling of delayed persisted messages at runtime -- for example, if the `TaskScheduler` has previously been stopped.
These operations can be invoked through a `Control Bus` command, as the following example shows:
====
[source,java]
----
Message<String> delayerReschedulingMessage =
MessageBuilder.withPayload("@'delayer.handler'.reschedulePersistedMessages()").build();
controlBusChannel.send(delayerReschedulingMessage);
----
====
NOTE: For more information regarding the message store, JMX, and the control bus, see <<./system-management.adoc#system-management-chapter,System Management>>.
NOTE: For more information regarding the message store, JMX, and the control bus, see xref:system-management.adoc[System Management].
Starting with version 5.3.7, if a transaction is active when a message is stored into a `MessageStore`, the release task is scheduled in a `TransactionSynchronization.afterCommit()` callback.
This is necessary to prevent a race condition, where the scheduled release could run before the transaction has committed, and the message is not found.
In this case, the message will be released after the delay, or after the transaction commits, whichever is later.
[[delayer-release-failures]]
==== Release Failures
== Release Failures
Starting with version 5.0.8, there are two new properties on the delayer:

View File

@@ -0,0 +1,57 @@
[[java-dsl]]
= Java DSL
The Spring Integration Java configuration and DSL provides a set of convenient builders and a fluent API that lets you configure Spring Integration message flows from Spring `@Configuration` classes.
(See also xref:kotlin-dsl.adoc[Kotlin DSL].)
(See also xref:groovy-dsl.adoc[Groovy DSL].)
The Java DSL for Spring Integration is essentially a facade for Spring Integration.
The DSL provides a simple way to embed Spring Integration Message Flows into your application by using the fluent `Builder` pattern together with existing Java configuration from Spring Framework and Spring Integration.
We also use and support lambdas (available with Java 8) to further simplify Java configuration.
The https://github.com/spring-projects/spring-integration-samples/tree/main/dsl/cafe-dsl[cafe] offers a good example of using the DSL.
The DSL is presented by the `IntegrationFlow` fluent API (see `IntegrationFlowBuilder`).
This produces the `IntegrationFlow` component, which should be registered as a Spring bean (by using the `@Bean` annotation).
The builder pattern is used to express arbitrarily complex structures as a hierarchy of methods that can accept lambdas as arguments.
The `IntegrationFlowBuilder` only collects integration components (`MessageChannel` instances, `AbstractEndpoint` instances, and so on) in the `IntegrationFlow` bean for further parsing and registration of concrete beans in the application context by the `IntegrationFlowBeanPostProcessor`.
The Java DSL uses Spring Integration classes directly and bypasses any XML generation and parsing.
However, the DSL offers more than syntactic sugar on top of XML.
One of its most compelling features is the ability to define inline lambdas to implement endpoint logic, eliminating the need for external classes to implement custom logic.
In some sense, Spring Integration's support for the Spring Expression Language (SpEL) and inline scripting address this, but lambdas are easier and much more powerful.
The following example shows how to use Java Configuration for Spring Integration:
[source,java]
----
@Configuration
@EnableIntegration
public class MyConfiguration {
@Bean
public AtomicInteger integerSource() {
return new AtomicInteger();
}
@Bean
public IntegrationFlow myFlow(AtomicInteger integerSource) {
return IntegrationFlow.fromSupplier(integerSource::getAndIncrement,
c -> c.poller(Pollers.fixedRate(100)))
.channel("inputChannel")
.filter((Integer p) -> p > 0)
.transform(Object::toString)
.channel(MessageChannels.queue())
.get();
}
}
----
The result of the preceding configuration example is that it creates, after `ApplicationContext` start up, Spring Integration endpoints and message channels.
Java configuration can be used both to replace and augment XML configuration.
You need not replace all of your existing XML configuration to use Java configuration.

View File

@@ -0,0 +1,56 @@
[[integration-flow-as-gateway]]
= `IntegrationFlow` as a Gateway
The `IntegrationFlow` can start from the service interface that provides a `GatewayProxyFactoryBean` component, as the following example shows:
[source,java]
----
public interface ControlBusGateway {
void send(String command);
}
...
@Bean
public IntegrationFlow controlBusFlow() {
return IntegrationFlow.from(ControlBusGateway.class)
.controlBus()
.get();
}
----
All the proxy for interface methods are supplied with the channel to send messages to the next integration component in the `IntegrationFlow`.
You can mark the service interface with the `@MessagingGateway` annotation and mark the methods with the `@Gateway` annotations.
Nevertheless, the `requestChannel` is ignored and overridden with that internal channel for the next component in the `IntegrationFlow`.
Otherwise, creating such a configuration by using `IntegrationFlow` does not make sense.
By default, a `GatewayProxyFactoryBean` gets a conventional bean name, such as `[FLOW_BEAN_NAME.gateway]`.
You can change that ID by using the `@MessagingGateway.name()` attribute or the overloaded `IntegrationFlow.from(Class<?> serviceInterface, Consumer<GatewayProxySpec> endpointConfigurer)` factory method.
Also, all the attributes from the `@MessagingGateway` annotation on the interface are applied to the target `GatewayProxyFactoryBean`.
When annotation configuration is not applicable, the `Consumer<GatewayProxySpec>` variant can be used for providing appropriate option for the target proxy.
This DSL method is available starting with version 5.2.
With Java 8, you can even create an integration gateway with the `java.util.function` interfaces, as the following example shows:
[source,java]
----
@Bean
public IntegrationFlow errorRecovererFlow() {
return IntegrationFlow.from(Function.class, (gateway) -> gateway.beanName("errorRecovererFunction"))
.<Object>handle((p, h) -> {
throw new RuntimeException("intentional");
}, e -> e.advice(retryAdvice()))
.get();
}
----
That `errorRecovererFlow` can be used as follows:
[source,java]
----
@Autowired
@Qualifier("errorRecovererFunction")
private Function<String, String> errorRecovererFlowGateway;
----

View File

@@ -0,0 +1,50 @@
[[integration-flows-composition]]
= Integration Flows Composition
With the `MessageChannel` abstraction as a first class citizen in Spring Integration, the composition of integration flows was always assumed.
The input channel of any endpoint in the flow can be used to send messages from any other endpoint and not only from the one which has this channel as an output.
Furthermore, with a `@MessagingGateway` contract, Content Enricher components, composite endpoints like a `<chain>`, and now with `IntegrationFlow` beans (e.g. `IntegrationFlowAdapter`), it is straightforward enough to distribute the business logic between shorter, reusable parts.
All that is needed for the final composition is knowledge about a `MessageChannel` to send to or receive from.
Starting with version `5.5.4`, to abstract more from `MessageChannel` and hide implementation details from the end-user, the `IntegrationFlow` introduces the `from(IntegrationFlow)` factory method to allow starting the current `IntegrationFlow` from the output of an existing flow:
[source,java]
----
@Bean
IntegrationFlow templateSourceFlow() {
return IntegrationFlow.fromSupplier(() -> "test data")
.channel("sourceChannel")
.get();
}
@Bean
IntegrationFlow compositionMainFlow(IntegrationFlow templateSourceFlow) {
return IntegrationFlow.from(templateSourceFlow)
.<String, String>transform(String::toUpperCase)
.channel(c -> c.queue("compositionMainFlowResult"))
.get();
}
----
On the other hand, the `IntegrationFlowDefinition` has added a `to(IntegrationFlow)` terminal operator to continue the current flow at the input channel of some other flow:
[source,java]
----
@Bean
IntegrationFlow mainFlow(IntegrationFlow otherFlow) {
return f -> f
.<String, String>transform(String::toUpperCase)
.to(otherFlow);
}
@Bean
IntegrationFlow otherFlow() {
return f -> f
.<String, String>transform(p -> p + " from other flow")
.channel(c -> c.queue("otherFlowResultChannel"));
}
----
The composition in the middle of the flow is simply achievable with an existing `gateway(IntegrationFlow)` EIP-method.
This way we can build flows with any complexity by composing them from simpler, reusable logical blocks.
For example, you may add a library of `IntegrationFlow` beans as a dependency, and it is just enough to have their configuration classes imported to the final project and autowired for your `IntegrationFlow` definitions.

View File

@@ -0,0 +1,41 @@
[[java-dsl-aggregators]]
= Aggregators and Resequencers
An `Aggregator` is conceptually the opposite of a `Splitter`.
It aggregates a sequence of individual messages into a single message and is necessarily more complex.
By default, an aggregator returns a message that contains a collection of payloads from incoming messages.
The same rules are applied for the `Resequencer`.
The following example shows a canonical example of the splitter-aggregator pattern:
[source,java]
----
@Bean
public IntegrationFlow splitAggregateFlow() {
return IntegrationFlow.from("splitAggregateInput")
.split()
.channel(MessageChannels.executor(this.taskExecutor()))
.resequence()
.aggregate()
.get();
}
----
The `split()` method splits the list into individual messages and sends them to the `ExecutorChannel`.
The `resequence()` method reorders messages by sequence details found in the message headers.
The `aggregate()` method collects those messages.
However, you can change the default behavior by specifying a release strategy and correlation strategy, among other things.
Consider the following example:
[source,java]
----
.aggregate(a ->
a.correlationStrategy(m -> m.getHeaders().get("myCorrelationKey"))
.releaseStrategy(g -> g.size() > 10)
.messageStore(messageStore()))
----
The preceding example correlates messages that have `myCorrelationKey` headers and releases the messages once at least ten have been accumulated.
Similar lambda configurations are provided for the `resequence()` EIP method.

View File

@@ -0,0 +1,95 @@
[[java-dsl-basics]]
= DSL Basics
The `org.springframework.integration.dsl` package contains the `IntegrationFlowBuilder` API mentioned earlier and a number of `IntegrationComponentSpec` implementations, which are also builders and provide the fluent API to configure concrete endpoints.
The `IntegrationFlowBuilder` infrastructure provides common https://www.enterpriseintegrationpatterns.com/[enterprise integration patterns] (EIP) for message-based applications, such as channels, endpoints, pollers, and channel interceptors.
IMPORTANT:: The `IntegrationComponentSpec` is a `FactoryBean` implementation, therefore its `getObject()` method must not be called from bean definitions.
The `IntegrationComponentSpec` implementation must be left as is for bean definitions and the framework will manage its lifecycle.
Bean method parameter injection for the target `IntegrationComponentSpec` type (a `FactoryBean` value) must be used for `IntegrationFlow` bean definitions instead of bean method references.
Endpoints are expressed as verbs in the DSL to improve readability.
The following list includes the common DSL method names and the associated EIP endpoint:
* transform -> `Transformer`
* filter -> `Filter`
* handle -> `ServiceActivator`
* split -> `Splitter`
* aggregate -> `Aggregator`
* route -> `Router`
* bridge -> `Bridge`
Conceptually, integration processes are constructed by composing these endpoints into one or more message flows.
Note that EIP does not formally define the term 'message flow', but it is useful to think of it as a unit of work that uses well known messaging patterns.
The DSL provides an `IntegrationFlow` component to define a composition of channels and endpoints between them, but now `IntegrationFlow` plays only the configuration role to populate real beans in the application context and is not used at runtime.
However, the bean for `IntegrationFlow` can be autowired as a `Lifecycle` to control `start()` and `stop()` for the whole flow which is delegated to all the Spring Integration components associated with this `IntegrationFlow`.
The following example uses the `IntegrationFlow` fluent API to define an `IntegrationFlow` bean by using EIP-methods from `IntegrationFlowBuilder`:
[source,java]
----
@Bean
public IntegrationFlow integerFlow() {
return IntegrationFlow.from("input")
.<String, Integer>transform(Integer::parseInt)
.get();
}
----
The `transform` method accepts a lambda as an endpoint argument to operate on the message payload.
The real argument of this method is a `GenericTransformer<S, T>` instance.
Consequently, any of the provided transformers (`ObjectToJsonTransformer`, `FileToStringTransformer`, and other) can be used here.
Under the covers, `IntegrationFlowBuilder` recognizes the `MessageHandler` and the endpoint for it, with `MessageTransformingHandler` and `ConsumerEndpointFactoryBean`, respectively.
Consider another example:
[source,java]
----
@Bean
public IntegrationFlow myFlow() {
return IntegrationFlow.from("input")
.filter("World"::equals)
.transform("Hello "::concat)
.handle(System.out::println)
.get();
}
----
The preceding example composes a sequence of `Filter -> Transformer -> Service Activator`.
The flow is "'one way'".
That is, it does not provide a reply message but only prints the payload to STDOUT.
The endpoints are automatically wired together by using direct channels.
[[java-dsl-class-cast]]
.Lambdas And `Message<?>` Arguments
[IMPORTANT]
====
When using lambdas in EIP methods, the "input" argument is generally the message payload.
If you wish to access the entire message, use one of the overloaded methods that take a `Class<?>` as the first parameter.
For example, this won't work:
[source, java]
----
.<Message<?>, Foo>transform(m -> newFooFromMessage(m))
----
This will fail at runtime with a `ClassCastException` because the lambda doesn't retain the argument type and the framework will attempt to cast the payload to a `Message<?>`.
Instead, use:
[source, java]
----
.(Message.class, m -> newFooFromMessage(m))
----
====
[[bean-definitions-override]]
.Bean Definitions override
[IMPORTANT]
====
The Java DSL can register beans for the object defined in-line in the flow definition, as well as can reuse existing, injected beans.
In case of the same bean name defined for in-line object and existing bean definition, a `BeanDefinitionOverrideException` is thrown indicating that such a configuration is wrong.
However, when you deal with `prototype` beans, there is no way to detect from the integration flow processor an existing bean definition because every time we call a `prototype` bean from the `BeanFactory` we get a new instance.
This way a provided instance is used in the `IntegrationFlow` as is without any bean registration and any possible check against existing `prototype` bean definition.
However `BeanFactory.initializeBean()` is called for this object if it has an explicit `id` and bean definition for this name is in `prototype` scope.
====

View File

@@ -0,0 +1,89 @@
[[java-dsl-channels]]
= Message Channels
In addition to the `IntegrationFlowBuilder` with EIP methods, the Java DSL provides a fluent API to configure `MessageChannel` instances.
For this purpose the `MessageChannels` builder factory is provided.
The following example shows how to use it:
[source,java]
----
@Bean
public PriorityChannelSpec priorityChannel() {
return MessageChannels.priority(this.mongoDbChannelMessageStore, "priorityGroup")
.interceptor(wireTap());
}
----
The same `MessageChannels` builder factory can be used in the `channel()` EIP method from `IntegrationFlowBuilder` to wire endpoints, similar to wiring an `input-channel`/`output-channel` pair in the XML configuration.
By default, endpoints are wired with `DirectChannel` instances where the bean name is based on the following pattern: `[IntegrationFlow.beanName].channel#[channelNameIndex]`.
This rule is also applied for unnamed channels produced by inline `MessageChannels` builder factory usage.
However, all `MessageChannels` methods have a variant that is aware of the `channelId` that you can use to set the bean names for `MessageChannel` instances.
The `MessageChannel` references and `beanName` can be used as bean-method invocations.
The following example shows the possible ways to use the `channel()` EIP method:
[source,java]
----
@Bean
public QueueChannelSpec queueChannel() {
return MessageChannels.queue();
}
@Bean
public PublishSubscribeChannelSpec<?> publishSubscribe() {
return MessageChannels.publishSubscribe();
}
@Bean
public IntegrationFlow channelFlow() {
return IntegrationFlow.from("input")
.fixedSubscriberChannel()
.channel("queueChannel")
.channel(publishSubscribe())
.channel(MessageChannels.executor("executorChannel", this.taskExecutor))
.channel("output")
.get();
}
----
* `from("input")` means "'find and use the `MessageChannel` with the "input" id, or create one'".
* `fixedSubscriberChannel()` produces an instance of `FixedSubscriberChannel` and registers it with a name of `channelFlow.channel#0`.
* `channel("queueChannel")` works the same way but uses an existing `queueChannel` bean.
* `channel(publishSubscribe())` is the bean-method reference.
* `channel(MessageChannels.executor("executorChannel", this.taskExecutor))` is the `IntegrationFlowBuilder` that exposes `IntegrationComponentSpec` to the `ExecutorChannel` and registers it as `executorChannel`.
* `channel("output")` registers the `DirectChannel` bean with `output` as its name, as long as no beans with this name already exist.
Note: The preceding `IntegrationFlow` definition is valid, and all of its channels are applied to endpoints with `BridgeHandler` instances.
IMPORTANT: Be careful to use the same inline channel definition through `MessageChannels` factory from different `IntegrationFlow` instances.
Even if the DSL parser registers non-existent objects as beans, it cannot determine the same object (`MessageChannel`) from different `IntegrationFlow` containers.
The following example is wrong:
[source,java]
----
@Bean
public IntegrationFlow startFlow() {
return IntegrationFlow.from("input")
.transform(...)
.channel(MessageChannels.queue("queueChannel"))
.get();
}
@Bean
public IntegrationFlow endFlow() {
return IntegrationFlow.from(MessageChannels.queue("queueChannel"))
.handle(...)
.get();
}
----
The result of that bad example is the following exception:
```
Caused by: java.lang.IllegalStateException:
Could not register object [queueChannel] under bean name 'queueChannel':
there is already object [queueChannel] bound
at o.s.b.f.s.DefaultSingletonBeanRegistry.registerSingleton(DefaultSingletonBeanRegistry.java:129)
```
To make it work, you need to declare `@Bean` for that channel and use its bean method from different `IntegrationFlow` instances.

View File

@@ -0,0 +1,46 @@
[[java-dsl-endpoints]]
= DSL and Endpoint Configuration
All `IntegrationFlowBuilder` EIP methods have a variant that applies the lambda parameter to provide options for `AbstractEndpoint` instances: `SmartLifecycle`, `PollerMetadata`, `request-handler-advice-chain`, and others.
Each of them has generic arguments, so it lets you configure an endpoint and even its `MessageHandler` in the context, as the following example shows:
[source,java]
----
@Bean
public IntegrationFlow flow2() {
return IntegrationFlow.from(this.inputChannel)
.transformWith(t -> t
.transformer(new PayloadSerializingTransformer())
.autoStartup(false)
.id("payloadSerializingTransformer"))
.transformWith(t -> t
.transformer((Integer p) -> p * 2)
.advice(expressionAdvice()))
.get();
}
----
In addition, the `EndpointSpec` provides an `id()` method to let you register an endpoint bean with a given bean name, rather than a generated one.
If the `MessageHandler` is referenced as a bean, then any existing `adviceChain` configuration will be overridden if the `.advice()` method is present in the DSL definition:
[source,java]
----
@Bean
public TcpOutboundGateway tcpOut() {
TcpOutboundGateway gateway = new TcpOutboundGateway();
gateway.setConnectionFactory(cf());
gateway.setAdviceChain(Collections.singletonList(fooAdvice()));
return gateway;
}
@Bean
public IntegrationFlow clientTcpFlow() {
return f -> f
.handle(tcpOut(), e -> e.advice(testAdvice()))
.transform(Transformers.objectToString());
}
----
They are not merged, only the `testAdvice()` bean is used in this case.

View File

@@ -0,0 +1,56 @@
[[java-dsl-extensions]]
= DSL Extensions
Starting with version 5.3, an `IntegrationFlowExtension` has been introduced to allow extension of the existing Java DSL with custom or composed EIP-operators.
All that is needed is an extension of this class that provides methods which can be used in the `IntegrationFlow` bean definitions.
The extension class can also be used for custom `IntegrationComponentSpec` configuration; for example, missed or default options can be implemented in the existing `IntegrationComponentSpec` extension.
The sample below demonstrates a composite custom operator and usage of an `AggregatorSpec` extension for a default custom `outputProcessor`:
[source,java]
----
public class CustomIntegrationFlowDefinition
extends IntegrationFlowExtension<CustomIntegrationFlowDefinition> {
public CustomIntegrationFlowDefinition upperCaseAfterSplit() {
return split()
.transform("payload.toUpperCase()");
}
public CustomIntegrationFlowDefinition customAggregate(Consumer<CustomAggregatorSpec> aggregator) {
return register(new CustomAggregatorSpec(), aggregator);
}
}
public class CustomAggregatorSpec extends AggregatorSpec {
CustomAggregatorSpec() {
outputProcessor(group ->
group.getMessages()
.stream()
.map(Message::getPayload)
.map(String.class::cast)
.collect(Collectors.joining(", ")));
}
}
----
For a method chain flow the new DSL operator in these extensions must return the extension class.
This way a target `IntegrationFlow` definition will work with new and existing DSL operators:
[source,java]
----
@Bean
public IntegrationFlow customFlowDefinition() {
return
new CustomIntegrationFlowDefinition()
.log()
.upperCaseAfterSplit()
.channel("innerChannel")
.customAggregate(customAggregatorSpec ->
customAggregatorSpec.expireGroupsUponCompletion(true))
.logAndReply();
}
----

View File

@@ -0,0 +1,79 @@
[[java-dsl-flow-adapter]]
= `IntegrationFlowAdapter`
The `IntegrationFlow` interface can be implemented directly and specified as a component for scanning, as the following example shows:
[source,java]
----
@Component
public class MyFlow implements IntegrationFlow {
@Override
public void configure(IntegrationFlowDefinition<?> f) {
f.<String, String>transform(String::toUpperCase);
}
}
----
It is picked up by the `IntegrationFlowBeanPostProcessor` and correctly parsed and registered in the application context.
For convenience and to gain the benefits of loosely coupled architecture, we provide the `IntegrationFlowAdapter` base class implementation.
It requires a `buildFlow()` method implementation to produce an `IntegrationFlowDefinition` by using one of `from()` methods, as the following example shows:
[source,java]
----
@Component
public class MyFlowAdapter extends IntegrationFlowAdapter {
private final AtomicBoolean invoked = new AtomicBoolean();
public Instant nextExecutionTime(TriggerContext triggerContext) {
return this.invoked.getAndSet(true) ? null : Instant.now();
}
@Override
protected IntegrationFlowDefinition<?> buildFlow() {
return fromSupplier(this::messageSource,
e -> e.poller(p -> p.trigger(this::nextExecutionTime)))
.split(this)
.transform(this)
.aggregate(this)
.enrichHeaders(Collections.singletonMap("thing1", "THING1"))
.filter(this)
.handle(this)
.channel(c -> c.queue("myFlowAdapterOutput"));
}
public String messageSource() {
return "T,H,I,N,G,2";
}
@Splitter
public String[] split(String payload) {
return StringUtils.commaDelimitedListToStringArray(payload);
}
@Transformer
public String transform(String payload) {
return payload.toLowerCase();
}
@Aggregator
public String aggregate(List<String> payloads) {
return payloads.stream().collect(Collectors.joining());
}
@Filter
public boolean filter(@Header Optional<String> thing1) {
return thing1.isPresent();
}
@ServiceActivator
public String handle(String payload, @Header String thing1) {
return payload + ":" + thing1;
}
}
----

View File

@@ -0,0 +1,43 @@
[[java-dsl-flows]]
= Working With Message Flows
`IntegrationFlowBuilder` provides a top-level API to produce integration components wired to message flows.
When your integration may be accomplished with a single flow (which is often the case), this is convenient.
Alternately `IntegrationFlow` instances can be joined via `MessageChannel` instances.
By default, `MessageFlow` behaves as a "`chain`" in Spring Integration parlance.
That is, the endpoints are automatically and implicitly wired by `DirectChannel` instances.
The message flow is not actually constructed as a chain, which offers much more flexibility.
For example, you may send a message to any component within the flow, if you know its `inputChannel` name (that is, if you explicitly define it).
You may also reference externally defined channels within a flow to allow the use of channel adapters (to enable remote transport protocols, file I/O, and so on), instead of direct channels.
As such, the DSL does not support the Spring Integration `chain` element, because it does not add much value in this case.
Since the Spring Integration Java DSL produces the same bean definition model as any other configuration options and is based on the existing Spring Framework `@Configuration` infrastructure, it can be used together with XML definitions and wired with Spring Integration messaging annotation configuration.
You can also define direct `IntegrationFlow` instances by using a lambda.
The following example shows how to do so:
[source,java]
----
@Bean
public IntegrationFlow lambdaFlow() {
return f -> f.filter("World"::equals)
.transform("Hello "::concat)
.handle(System.out::println);
}
----
The result of this definition is the same set of integration components that are wired with an implicit direct channel.
The only limitation here is that this flow is started with a named direct channel - `lambdaFlow.input`.
Also, a Lambda flow cannot start from `MessageSource` or `MessageProducer`.
Starting with version 5.1, this kind of `IntegrationFlow` is wrapped to the proxy to expose lifecycle control and provide access to the `inputChannel` of the internally associated `StandardIntegrationFlow`.
Starting with version 5.0.6, the generated bean names for the components in an `IntegrationFlow` include the flow bean followed by a dot (`.`) as a prefix.
For example, the `ConsumerEndpointFactoryBean` for the `.transform("Hello "::concat)` in the preceding sample results in a bean name of `lambdaFlow.o.s.i.config.ConsumerEndpointFactoryBean#0`.
(The `o.s.i` is a shortened from `org.springframework.integration` to fit on the page.)
The `Transformer` implementation bean for that endpoint has a bean name of `lambdaFlow.transformer#0` (starting with version 5.1), where instead of a fully qualified name of the `MethodInvokingTransformer` class, its component type is used.
The same pattern is applied for all the `NamedComponent` s when the bean name has to be generated within the flow.
These generated bean names are prepended with the flow ID for purposes such as parsing logs or grouping components together in some analysis tool, as well as to avoid a race condition when we concurrently register integration flows at runtime.
See xref:dsl/java-runtime-flows.adoc[Dynamic and Runtime Integration Flows] for more information.

Some files were not shown because too many files have changed in this diff Show More