Start version 6.3.0

* Upgrade supported dependencies to their latest versions or `alpha`, `RC`
* Migrate to `com.github.spotbugs` plugin
* Upgrade to GraalVM `23.1.1`, which includes `org.graalvm.polyglot:js` migration
* Remove `spring-integration-security` module
* Fix Debezium tests according to the latest changes in the Debezium library
* Fix deprecations and incompatibility for latest Smack and Spring AMQP
This commit is contained in:
Artem Bilan
2023-12-21 17:39:34 -05:00
parent 075613c4a1
commit 23c792e11b
19 changed files with 338 additions and 443 deletions

View File

@@ -1,5 +1,5 @@
buildscript {
ext.kotlinVersion = '1.9.10'
ext.kotlinVersion = '1.9.22'
ext.isCI = System.getenv('GITHUB_ACTION')
repositories {
gradlePluginPortal()
@@ -19,9 +19,10 @@ plugins {
id 'io.spring.nohttp' version '0.0.11' apply false
id 'org.ajoberstar.grgit' version '5.2.1'
id 'io.spring.dependency-management' version '1.1.4'
id 'org.jetbrains.dokka' version "$kotlinVersion"
id 'org.jetbrains.dokka' version '1.9.10'
id 'org.antora' version '1.0.0'
id 'io.spring.antora.generate-antora-yml' version '0.0.1'
id 'com.github.spotbugs' version '6.0.4'
}
if (isCI) {
@@ -58,24 +59,23 @@ ext {
assertkVersion = '0.28.0'
avroVersion = '1.11.3'
awaitilityVersion = '4.2.0'
camelVersion = '4.2.0'
camelVersion = '4.3.0'
commonsDbcp2Version = '2.11.0'
commonsIoVersion = '2.15.1'
commonsNetVersion = '3.10.0'
curatorVersion = '5.5.0'
debeziumVersion = '2.4.2.Final'
debeziumVersion = '2.5.0.CR1'
derbyVersion = '10.16.1.1'
findbugsVersion = '3.0.1'
ftpServerVersion = '1.2.0'
graalvmVersion = '23.0.2'
graalvmVersion = '23.1.1'
greenmailVersion = '2.1.0-alpha-3'
groovyVersion = '4.0.16'
groovyVersion = '5.0.0-alpha-3'
hamcrestVersion = '2.2'
hazelcastVersion = '5.3.6'
hibernateVersion = '6.4.1.Final'
hsqldbVersion = '2.7.2'
h2Version = '2.2.224'
jacksonVersion = '2.15.3'
jacksonVersion = '2.16.0'
jaxbVersion = '4.0.4'
jcifsVersion = '2.1.37'
jeroMqVersion = '0.5.4'
@@ -89,30 +89,30 @@ ext {
kotlinCoroutinesVersion = '1.7.3'
kryoVersion = '5.5.0'
lettuceVersion = '6.3.0.RELEASE'
log4jVersion = '2.21.1'
log4jVersion = '2.22.0'
mailVersion = '2.0.2'
micrometerTracingVersion = '1.2.1'
micrometerVersion = '1.12.1'
mockitoVersion = '5.7.0'
micrometerTracingVersion = '1.3.0-SNAPSHOT'
micrometerVersion = '1.13.0-SNAPSHOT'
mockitoVersion = '5.8.0'
mongoDriverVersion = '4.11.1'
mysqlVersion = '8.0.33'
mysqlVersion = '8.2.0'
oracleVersion = '23.3.0.23.09'
pahoMqttClientVersion = '1.2.5'
postgresVersion = '42.6.0'
protobufVersion = '3.25.1'
postgresVersion = '42.7.1'
protobufVersion = '4.0.0-rc-2'
r2dbch2Version = '1.0.0.RELEASE'
reactorVersion = '2023.0.1'
resilience4jVersion = '2.1.0'
resilience4jVersion = '2.2.0'
romeToolsVersion = '2.1.0'
rsocketVersion = '1.1.4'
servletApiVersion = '6.0.0'
smackVersion = '4.4.7'
springAmqpVersion = '3.1.1'
springDataVersion = '2023.1.1'
springGraphqlVersion = '1.2.4'
springKafkaVersion = '3.1.1'
smackVersion = '4.5.0-alpha2'
springAmqpVersion = '3.1.2-SNAPSHOT'
springDataVersion = '2023.2.0-SNAPSHOT'
springGraphqlVersion = '1.2.5-SNAPSHOT'
springKafkaVersion = '3.1.2-SNAPSHOT'
springRetryVersion = '2.0.5'
springSecurityVersion = '6.2.1'
springSecurityVersion = '6.3.0-SNAPSHOT'
springVersion = '6.1.2'
springWsVersion = '4.0.9'
testcontainersVersion = '1.19.3'
@@ -256,9 +256,8 @@ configure(javaProjects) { subproject ->
api project(':spring-integration-core')
}
// JSR-305 only used for non-required meta-annotations
compileOnly "com.google.code.findbugs:annotations:$findbugsVersion"
testImplementation "com.google.code.findbugs:annotations:$findbugsVersion"
compileOnly "com.github.spotbugs:spotbugs-annotations:${spotbugs.toolVersion.get()}"
testImplementation("org.awaitility:awaitility:$awaitilityVersion") {
exclude group: 'org.hamcrest'
}
@@ -703,7 +702,7 @@ project('spring-integration-jdbc') {
testImplementation "org.apache.derby:derbytools:$derbyVersion"
testImplementation "org.apache.derby:derbyclient:$derbyVersion"
testImplementation "org.postgresql:postgresql:$postgresVersion"
testImplementation "mysql:mysql-connector-java:$mysqlVersion"
testImplementation "com.mysql:mysql-connector-j:$mysqlVersion"
testImplementation("org.apache.commons:commons-dbcp2:$commonsDbcp2Version") {
exclude group: 'commons-logging'
}
@@ -833,7 +832,7 @@ project('spring-integration-scripting') {
dependencies {
optionalApi 'org.jetbrains.kotlin:kotlin-scripting-jsr223'
providedImplementation "org.graalvm.sdk:graal-sdk:$graalvmVersion"
providedImplementation "org.graalvm.js:js:$graalvmVersion"
providedImplementation "org.graalvm.polyglot:js:$graalvmVersion"
testImplementation "org.jruby:jruby-complete:$jrubyVersion"
testImplementation 'org.apache.groovy:groovy-jsr223'
@@ -848,13 +847,6 @@ project('spring-integration-scripting') {
}
}
project('spring-integration-security') {
description = 'Spring Integration Security Support'
dependencies {
api 'org.springframework.security:spring-security-messaging'
}
}
project('spring-integration-sftp') {
description = 'Spring Integration SFTP Support'
dependencies {

View File

@@ -1,4 +1,4 @@
version=6.2.2-SNAPSHOT
version=6.3.0-SNAPSHOT
org.gradle.jvmargs=-Xmx1536M -Dfile.encoding=UTF-8
kotlin.jvm.target.validation.mode=IGNORE
org.gradle.caching=true

View File

@@ -16,7 +16,7 @@ antora {
'@antora/atlas-extension': '1.0.0-alpha.2',
'@antora/collector-extension': '1.0.0-alpha.3',
'@asciidoctor/tabs': '1.0.0-beta.6',
'@springio/antora-extensions': '1.8.0',
'@springio/antora-extensions': '1.8.1',
'@springio/asciidoctor-extensions': '1.0.0-alpha.9',
]
}
@@ -47,7 +47,7 @@ dependencies {
}
def observationInputDir = file('spring-integration-core/src/main/java/org/springframework/integration/support/management/observation').absolutePath
def generatedDocsDir = file("$buildDir/reference/generated").absolutePath
def generatedDocsDir = file('build/reference/generated').absolutePath
tasks.register('generateObservabilityDocs', JavaExec) {
inputs.dir(observationInputDir)

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2022 the original author or authors.
* Copyright 2014-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import java.util.Collection;
import java.util.Set;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import org.junit.After;
import org.junit.ClassRule;
@@ -134,12 +135,13 @@ public class ChannelTests {
private void waitForNewConsumer(PublishSubscribeAmqpChannel channel, BlockingQueueConsumer consumer)
throws Exception {
final Object consumersMonitor = TestUtils.getPropertyValue(channel, "container.consumersMonitor");
Lock consumersLock = TestUtils.getPropertyValue(channel, "container.consumersLock", Lock.class);
int n = 0;
while (n++ < 100) {
Set<BlockingQueueConsumer> consumers = TestUtils
.getPropertyValue(channel, "container.consumers", Set.class);
synchronized (consumersMonitor) {
consumersLock.lock();
try {
if (!consumers.isEmpty()) {
BlockingQueueConsumer newConsumer = consumers.iterator().next();
if (newConsumer != consumer && newConsumer.getConsumerTags().size() > 0) {
@@ -147,6 +149,9 @@ public class ChannelTests {
}
}
}
finally {
consumersLock.unlock();
}
Thread.sleep(100);
}
assertThat(n < 100).as("Failed to restart consumer").isTrue();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2018-2022 the original author or authors.
* Copyright 2018-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -145,7 +145,7 @@ class FunctionsTests {
val gateways = this.monoFunctionGateway.gateways
assertThat(gateways).size().isEqualTo(3)
val methodNames = gateways.keys.stream().map { it.name }.collect(Collectors.toList())
assertThat(methodNames).containsAll("apply", "andThen", "compose")
assertThat(methodNames).containsAtLeast("apply", "andThen", "compose")
}
@Autowired

View File

@@ -67,7 +67,7 @@ public class DebeziumDslTests implements DebeziumMySqlTestContainer {
config.headerKeys.forEach(keys -> {
assertThat(keys).contains("debezium_destination", "id", "contentType", "debezium_key", "timestamp");
if (keys.size() > 5) {
assertThat(keys).contains("__name", "__db", "__table", "__op");
assertThat(keys).contains("__name", "__db", "__table");
}
});
}
@@ -86,7 +86,7 @@ public class DebeziumDslTests implements DebeziumMySqlTestContainer {
config.batchHeaderKeys.stream()
.filter(headerNames -> !CollectionUtils.isEmpty(headerNames))
.forEach(headerNames -> {
assertThat(headerNames).contains("__name", "__db", "__table", "__op");
assertThat(headerNames).contains("__name", "__db", "__table");
});
}

View File

@@ -18,7 +18,6 @@ package org.springframework.integration.debezium.it;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import io.debezium.engine.ChangeEvent;
import io.debezium.engine.DebeziumEngine;
@@ -58,6 +57,7 @@ public class DebeziumBatchTests implements DebeziumMySqlTestContainer {
@Autowired
@Qualifier("queueChannel")
private QueueChannel queueChannel;
private int batchCount = 0;
@Test
@@ -73,11 +73,11 @@ public class DebeziumBatchTests implements DebeziumMySqlTestContainer {
List<String> headerKeys = changeEvent.headers()
.stream()
.map(Header::getKey)
.collect(Collectors.toList());
.toList();
assertThat(changeEvent.destination()).startsWith("my-topic");
if (i < 16) {
assertThat(headerKeys).isEmpty();
assertThat(headerKeys).hasSize(3).contains("__name", "__db", "__table");
}
else {
assertThat(changeEvent.destination()).contains(".inventory");

View File

@@ -60,7 +60,7 @@ public class DebeziumStreamTests implements DebeziumMySqlTestContainer {
assertThat(message).isNotNull();
if (message.getHeaders().size() > 5) {
assertThat(message.getHeaders()).containsKeys("__name", "__db", "__op", "__table");
assertThat(message.getHeaders()).containsKeys("__name", "__db", "__table");
foundDebeziumHeaders = true;
}
}

View File

@@ -21,14 +21,7 @@ import groovy.transform.stc.ClosureParams
import groovy.transform.stc.SimpleType
import org.reactivestreams.Publisher
import org.springframework.integration.core.MessageSource
import org.springframework.integration.dsl.GatewayProxySpec
import org.springframework.integration.dsl.IntegrationFlow
import org.springframework.integration.dsl.IntegrationFlowBuilder
import org.springframework.integration.dsl.IntegrationFlowDefinition
import org.springframework.integration.dsl.MessageProducerSpec
import org.springframework.integration.dsl.MessageSourceSpec
import org.springframework.integration.dsl.MessagingGatewaySpec
import org.springframework.integration.dsl.SourcePollingChannelAdapterSpec
import org.springframework.integration.dsl.*
import org.springframework.integration.endpoint.MessageProducerSupport
import org.springframework.integration.gateway.MessagingGatewaySupport
import org.springframework.messaging.Message
@@ -47,224 +40,226 @@ import java.util.function.Supplier
@CompileStatic
class IntegrationGroovyDsl {
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL.
* @param flow the {@link Closure} for {@link IntegrationFlowDefinition}
*/
static IntegrationFlow integrationFlow(
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL.
* @param flow the {@link Closure} for {@link IntegrationFlowDefinition}
*/
static IntegrationFlow integrationFlow(
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
{ IntegrationFlowDefinition flowDefinition ->
def delegate = new GroovyIntegrationFlowDefinition(flowDefinition)
flow.delegate = delegate
flow.resolveStrategy = Closure.DELEGATE_FIRST
flow(delegate)
} as IntegrationFlow
}
{ IntegrationFlowDefinition flowDefinition ->
def delegate = new GroovyIntegrationFlowDefinition(flowDefinition)
flow.delegate = delegate
flow.resolveStrategy = Closure.DELEGATE_FIRST
flow(delegate)
} as IntegrationFlow
}
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(Class, Consumer)} factory method.
*/
static IntegrationFlow integrationFlow(
Class<?> serviceInterface,
@DelegatesTo(value = GatewayProxySpec, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.dsl.GatewayProxySpec')
Closure<?> gatewaySpec = null,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(Class, Consumer)} factory method.
*/
static IntegrationFlow integrationFlow(
Class<?> serviceInterface,
@DelegatesTo(value = GatewayProxySpec, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.dsl.GatewayProxySpec')
Closure<?> gatewaySpec = null,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
Consumer<GatewayProxySpec> configurer = GroovyIntegrationFlowDefinition.createConfigurerIfAny(gatewaySpec)
buildIntegrationFlow(IntegrationFlow.from(serviceInterface, configurer), flow)
}
Consumer<GatewayProxySpec> configurer = GroovyIntegrationFlowDefinition.createConfigurerIfAny(gatewaySpec)
buildIntegrationFlow(IntegrationFlow.from(serviceInterface, configurer), flow)
}
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(String, boolean)} factory method.
*/
static IntegrationFlow integrationFlow(
String channelName,
Boolean fixedSubscriber = false,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(String, boolean)} factory method.
*/
static IntegrationFlow integrationFlow(
String channelName,
Boolean fixedSubscriber = false,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
buildIntegrationFlow(IntegrationFlow.from(channelName, fixedSubscriber), flow)
}
buildIntegrationFlow(IntegrationFlow.from(channelName, fixedSubscriber), flow)
}
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(MessageChannel)} factory method.
*/
static IntegrationFlow integrationFlow(
MessageChannel channel,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(MessageChannel)} factory method.
*/
static IntegrationFlow integrationFlow(
MessageChannel channel,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
buildIntegrationFlow(IntegrationFlow.from(channel), flow)
}
buildIntegrationFlow(IntegrationFlow.from(channel), flow)
}
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(MessageSource, Consumer)} factory method.
*/
static IntegrationFlow integrationFlow(
MessageSource<?> messageSource,
@DelegatesTo(value = SourcePollingChannelAdapterSpec, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = "org.springframework.integration.dsl.SourcePollingChannelAdapterSpec")
Closure<?> adapterSpec = null,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(MessageSource, Consumer)} factory method.
*/
static IntegrationFlow integrationFlow(
MessageSource<?> messageSource,
@DelegatesTo(value = SourcePollingChannelAdapterSpec, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = "org.springframework.integration.dsl.SourcePollingChannelAdapterSpec")
Closure<?> adapterSpec = null,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
Consumer<SourcePollingChannelAdapterSpec> configurer =
GroovyIntegrationFlowDefinition.createConfigurerIfAny(adapterSpec)
buildIntegrationFlow(IntegrationFlow.from(messageSource, configurer), flow)
}
Consumer<SourcePollingChannelAdapterSpec> configurer =
GroovyIntegrationFlowDefinition.createConfigurerIfAny(adapterSpec)
buildIntegrationFlow(IntegrationFlow.from(messageSource, configurer), flow)
}
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(org.springframework.integration.dsl.MessageSourceSpec, Consumer)} factory method.
*/
static IntegrationFlow integrationFlow(
MessageSourceSpec messageSourceSpec,
@DelegatesTo(value = SourcePollingChannelAdapterSpec, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = "org.springframework.integration.dsl.SourcePollingChannelAdapterSpec")
Closure<?> adapterSpec = null,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(org.springframework.integration.dsl.MessageSourceSpec, Consumer)} factory method.
*/
static IntegrationFlow integrationFlow(
MessageSourceSpec messageSourceSpec,
@DelegatesTo(value = SourcePollingChannelAdapterSpec, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = "org.springframework.integration.dsl.SourcePollingChannelAdapterSpec")
Closure<?> adapterSpec = null,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
Consumer<SourcePollingChannelAdapterSpec> configurer =
GroovyIntegrationFlowDefinition.createConfigurerIfAny(adapterSpec)
buildIntegrationFlow(IntegrationFlow.from(messageSourceSpec, configurer), flow)
}
Consumer<SourcePollingChannelAdapterSpec> configurer =
GroovyIntegrationFlowDefinition.createConfigurerIfAny(adapterSpec)
buildIntegrationFlow(IntegrationFlow.from(messageSourceSpec, configurer), flow)
}
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#fromSupplier(Supplier, Consumer)} factory method.
*/
static IntegrationFlow integrationFlow(
Closure<Object> source,
@DelegatesTo(value = SourcePollingChannelAdapterSpec, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.dsl.SourcePollingChannelAdapterSpec')
Closure<?> adapterSpec = null,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#fromSupplier(Supplier, Consumer)} factory method.
*/
static IntegrationFlow integrationFlow(
Closure<Object> source,
@DelegatesTo(value = SourcePollingChannelAdapterSpec, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.dsl.SourcePollingChannelAdapterSpec')
Closure<?> adapterSpec = null,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
Consumer<SourcePollingChannelAdapterSpec> configurer =
GroovyIntegrationFlowDefinition.createConfigurerIfAny(adapterSpec)
buildIntegrationFlow(IntegrationFlow.fromSupplier(source, configurer), flow)
}
Consumer<SourcePollingChannelAdapterSpec> configurer =
GroovyIntegrationFlowDefinition.createConfigurerIfAny(adapterSpec)
buildIntegrationFlow(IntegrationFlow.fromSupplier(source, configurer), flow)
}
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(Publisher)} factory method.
*/
static IntegrationFlow integrationFlow(
Publisher<? extends Message<?>> publisher,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(Publisher)} factory method.
*/
static IntegrationFlow integrationFlow(
Publisher<? extends Message<?>> publisher,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
buildIntegrationFlow(IntegrationFlow.from(publisher), flow)
}
buildIntegrationFlow(IntegrationFlow.from(publisher), flow)
}
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(MessagingGatewaySupport)} factory method.
*/
static IntegrationFlow integrationFlow(
MessagingGatewaySupport gateway,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(MessagingGatewaySupport)} factory method.
*/
static IntegrationFlow integrationFlow(
MessagingGatewaySupport gateway,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
buildIntegrationFlow(IntegrationFlow.from(gateway), flow)
}
buildIntegrationFlow(IntegrationFlow.from(gateway), flow)
}
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(org.springframework.integration.dsl.MessagingGatewaySpec)} factory method.
*/
static IntegrationFlow integrationFlow(
MessagingGatewaySpec gatewaySpec,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(org.springframework.integration.dsl.MessagingGatewaySpec)} factory method.
*/
static IntegrationFlow integrationFlow(
MessagingGatewaySpec gatewaySpec,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
buildIntegrationFlow(IntegrationFlow.from(gatewaySpec), flow)
}
buildIntegrationFlow(IntegrationFlow.from(gatewaySpec), flow)
}
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(MessageProducerSupport)} factory method.
*/
static IntegrationFlow integrationFlow(
MessageProducerSupport producer,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(MessageProducerSupport)} factory method.
*/
static IntegrationFlow integrationFlow(
MessageProducerSupport producer,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
buildIntegrationFlow(IntegrationFlow.from(producer), flow)
}
buildIntegrationFlow(IntegrationFlow.from(producer), flow)
}
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(org.springframework.integration.dsl.MessageProducerSpec)} factory method.
*/
static IntegrationFlow integrationFlow(
MessageProducerSpec producerSpec,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(org.springframework.integration.dsl.MessageProducerSpec)} factory method.
*/
static IntegrationFlow integrationFlow(
MessageProducerSpec producerSpec,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
buildIntegrationFlow(IntegrationFlow.from(producerSpec), flow)
}
buildIntegrationFlow(IntegrationFlow.from(producerSpec), flow)
}
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(IntegrationFlow)} factory method.
*/
static IntegrationFlow integrationFlow(
IntegrationFlow sourceFlow,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
/**
* Functional {@link IntegrationFlow} definition in Groovy DSL for
* {@link IntegrationFlow#from(IntegrationFlow)} factory method.
*/
static IntegrationFlow integrationFlow(
IntegrationFlow sourceFlow,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
@ClosureParams(value = SimpleType,
options = 'org.springframework.integration.groovy.dsl.GroovyIntegrationFlowDefinition')
Closure<?> flow) {
buildIntegrationFlow(IntegrationFlow.from(sourceFlow), flow)
}
buildIntegrationFlow(IntegrationFlow.from(sourceFlow), flow)
}
private static IntegrationFlow buildIntegrationFlow(IntegrationFlowBuilder flowBuilder, Closure<?> flow) {
flow.delegate = new GroovyIntegrationFlowDefinition(flowBuilder)
flow.resolveStrategy = Closure.DELEGATE_FIRST
flow()
flowBuilder.get()
}
private static IntegrationFlow buildIntegrationFlow(
IntegrationFlowBuilder flowBuilder,
@DelegatesTo(value = GroovyIntegrationFlowDefinition, strategy = Closure.DELEGATE_FIRST)
Closure<?> flow) {
flow.delegate = new GroovyIntegrationFlowDefinition(flowBuilder)
flow()
flowBuilder.get()
}
private IntegrationGroovyDsl() {
}
private IntegrationGroovyDsl() {
}
}

View File

@@ -1,100 +0,0 @@
/*
* Copyright 2015-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.security.channel;
import org.springframework.aop.support.AopUtils;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.interceptor.ThreadStatePropagationChannelInterceptor;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* The {@link org.springframework.messaging.support.ExecutorChannelInterceptor}
* implementation responsible for
* the {@link SecurityContext} propagation from one message flow's thread to another
* through the {@link MessageChannel}s involved in the flow.
* <p>
* In addition this interceptor cleans up (restores) the {@link SecurityContext}
* in the containers Threads for channels like
* {@link org.springframework.integration.channel.ExecutorChannel}
* and {@link org.springframework.integration.channel.QueueChannel}.
*
* @author Artem Bilan
* @author Gary Russell
*
* @since 4.2
*
* @see ThreadStatePropagationChannelInterceptor
*
* @deprecated since 6.2 in favor of {@link org.springframework.security.messaging.context.SecurityContextPropagationChannelInterceptor}
*/
@Deprecated(since = "6.2", forRemoval = true)
public class SecurityContextPropagationChannelInterceptor
extends ThreadStatePropagationChannelInterceptor<Authentication> {
private static final SecurityContext EMPTY_CONTEXT = SecurityContextHolder.createEmptyContext();
private static final ThreadLocal<SecurityContext> ORIGINAL_CONTEXT = new ThreadLocal<>();
@Override
public void afterMessageHandled(Message<?> message, MessageChannel channel, MessageHandler handler, Exception ex) {
cleanup();
}
@Override
protected Authentication obtainPropagatingContext(Message<?> message, MessageChannel channel) {
if (!DirectChannel.class.isAssignableFrom(AopUtils.getTargetClass(channel))) {
return SecurityContextHolder.getContext().getAuthentication();
}
return null;
}
@Override
protected void populatePropagatedContext(Authentication authentication, Message<?> message,
MessageChannel channel) {
if (authentication != null) {
SecurityContext currentContext = SecurityContextHolder.getContext();
ORIGINAL_CONTEXT.set(currentContext);
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context);
}
}
private void cleanup() {
SecurityContext originalContext = ORIGINAL_CONTEXT.get();
try {
if (originalContext == null || EMPTY_CONTEXT.equals(originalContext)) {
SecurityContextHolder.clearContext();
ORIGINAL_CONTEXT.remove();
}
else {
SecurityContextHolder.setContext(originalContext);
}
}
catch (Throwable t) { //NOSONAR
SecurityContextHolder.clearContext();
}
}
}

View File

@@ -1,4 +0,0 @@
/**
* Provides classes related to secured channels.
*/
package org.springframework.integration.security.channel;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,8 +22,8 @@ import java.util.Map;
import org.jivesoftware.smack.StanzaListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.XmlElement;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
@@ -133,15 +133,16 @@ public class ChatMessageListeningEndpoint extends AbstractXmppConnectionAwareEnd
if (ChatMessageListeningEndpoint.this.payloadExpression != null) {
EvaluationContext evaluationContextToUse = ChatMessageListeningEndpoint.this.evaluationContext;
List<ExtensionElement> extensions = xmppMessage.getExtensions();
List<XmlElement> extensions = xmppMessage.getExtensions();
if (extensions.size() == 1) {
ExtensionElement extension = extensions.get(0);
XmlElement extension = extensions.get(0);
evaluationContextToUse = ExpressionUtils.createStandardEvaluationContext(getBeanFactory());
evaluationContextToUse.setVariable("extension", extension);
}
messageBody = ChatMessageListeningEndpoint.this.payloadExpression
.getValue(evaluationContextToUse, xmppMessage);
messageBody =
ChatMessageListeningEndpoint.this.payloadExpression
.getValue(evaluationContextToUse, xmppMessage);
}
if (messageBody != null) {

View File

@@ -82,7 +82,7 @@ public class ChatMessageInboundChannelAdapterParserTests {
assertThat(TestUtils.getPropertyValue(adapter, "payloadExpression.expression")).isEqualTo("#root");
adapter.start();
Map asyncRecvListeners = TestUtils.getPropertyValue(connection, "asyncRecvListeners", Map.class);
assertThat(asyncRecvListeners.size()).isEqualTo(5);
assertThat(asyncRecvListeners.size()).isEqualTo(6);
Object lastListener = asyncRecvListeners.values().stream().reduce((first, second) -> second).get();
assertThat(TestUtils.getPropertyValue(lastListener, "packetFilter")).isSameAs(stanzaFilter);
adapter.stop();

View File

@@ -38,4 +38,4 @@ runtime:
format: pretty
ui:
bundle:
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.7/ui-bundle.zip
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.10/ui-bundle.zip

View File

@@ -254,6 +254,7 @@
* xref:samples.adoc[]
* xref:resources.adoc[]
* xref:history.adoc[]
** xref:changes-6.1-6.2.adoc[]
** xref:changes-6.0-6.1.adoc[]
** xref:changes-5.5-6.0.adoc[]
** xref:changes-5.4-5.5.adoc[]

View File

@@ -0,0 +1,77 @@
[[migration-6.1-6.2]]
= Changes between 6.1 and 6.2
[[x6.2-new-components]]
== New Components
[[x6.2-debezium]]
=== Debezium Inbound Channel Adapter
The Debezium Engine based Change Data Capture (CDC) channel adapter, that allows capturing database change events, converting them into Messages and streaming those to the outbound channels.
See xref:debezium.adoc[Debezium Support] for more information.
[[x6.2-general]]
== General Changes
- The XML configuration for `<poller>` and `@Poller` annotation now support ISO 8601 duration format for `fixed-delay`, `fixed-rate` and `initial-delay` options.
See xref:endpoint.adoc#endpoint-pollingconsumer[Polling Consumer] for more information.
- Java, Groovy and Kotlin DSLs have now context-specific methods in the `IntegrationFlowDefinition` with a single `Consumer` argument to configure an endpoint and its handler with one builder and readable options.
See, for example, `transformWith()`, `splitWith()` in xref:dsl.adoc#java-dsl[Java DSL Chapter].
- A new `spring.integration.endpoints.defaultTimeout` global property has been introduced to override the default 30 seconds timeout for all the endpoints in the application.
See xref:configuration/global-properties.adoc[Global Properties] for more information.
- The `@MessagingGateway` and `GatewayEndpointSpec` provided by the Java DSL now expose the `errorOnTimeout` property of the internal `MethodInvocationGateway` extension of the `MessagingGatewaySupport`.
See xref:gateway.adoc#gateway-no-response[Gateway Behavior When No response Arrives] for more information.
- The `LockRegistry` provides template-like API to execute provided task while locked.
See xref:distributed-locks.adoc[Distributed Locks] for more information.
- The default trigger for polling endpoint is now a `PeriodicTrigger` instance with a 1 second fixed delay period; previously, the default was 10 milliseconds.
See xref:endpoint.adoc#endpoint-pollingconsumer[Polling Consumer] for more information.
[[x6.2-websockets]]
== WebSockets Changes
- For the server and client WebSocket containers, the send buffer overflow strategy is now configurable in `IntegrationWebSocketContainer` and in XML via `send-buffer-overflow-strategy`.
This strategy determines the behavior when a session's outbound message buffer has reached the configured limit.
See xref:web-sockets.adoc#websocket-client-container-attributes[WebSockets Support] for more information.
[[x6.2-kafka]]
== Apache Kafka Support Changes
The `KafkaMessageSource` now extracts an `ErrorHandlingDeserializer` configuration from the consumer properties and re-throws `DeserializationException` extracted from failed record headers.
See xref:kafka.adoc#kafka-inbound-pollable[Kafka Inbound Channel Adapter] for more information.
[[x6.2-jdbc]]
== JDBC Support Changes
The `JdbcMessageStore`, `JdbcChannelMessageStore`, `JdbcMetadataStore`, and `DefaultLockRepository` implement `SmartLifecycle` and perform a `SELECT COUNT` query, on their respective tables, in the `start()` method to ensure that the required table (according to the provided prefix) is present in the target database.
The `PostgresChannelMessageStoreQueryProvider` now provides single `DELETE...RETURNING` statement for polling queries.
For this purpose the `ChannelMessageStoreQueryProvider` exposes `isSingleStatementForPoll` option which is consulted from the `JdbcChannelMessageStore`.
See xref:jdbc/message-store.adoc[JDBC Message Store] for more information.
[[x6.2-mongodb]]
== MongoDB Support Changes
A new option `setCreateIndexes(boolean)` has been introduced in `AbstractConfigurableMongoDbMessageStore` to disable the auto indexes creation.
See xref:mongodb.adoc#mongodb-message-store[MongoDB Message Store] for an example.
[[x6.2-remote-files]]
== Remote Files Support Changes
`FtpLastModifiedFileListFilter`, `SftpLastModifiedFileListFilter` and `SmbLastModifiedFileListFilter` have been introduced to allow files filtering based on a last-modified strategy respectively for `FTP`, `SFTP` and `SMB`.
See xref:ftp/inbound.adoc#ftp-inbound[FTP Inbound Channel Adapter], xref:sftp/inbound.adoc#sftp-inbound[SFTP Inbound Channel Adapter], and xref:smb.adoc#smb-inbound[SMB Inbound Channel Adapter] for more information.
[[x6.2-sftp-changes]]
== SFTP Support Changes
A new `DefaultSftpSessionFactory.createSftpClient(...)` method has been introduced to support a custom `SftpClient` when overridden.
See xref:sftp/session-factory.adoc#sftp-session-factory[SFTP Session Factory] for more information.
[[x6.2-security-changes]]
== Security Support Changes
The last class in `spring-integration-security` module `SecurityContextPropagationChannelInterceptor` has been deprecated in favor of similar class moved to `spring-security-messaging` module.
See xref:security.adoc[Security in Spring Integration] for more information.

View File

@@ -6,14 +6,7 @@ Moreover, it is critical for distributed systems, such as those built on Enterpr
Messaging independence and loose coupling let target systems communicate with each other with any type of data in the message's `payload`.
We can either trust all those messages or secure our service against "`infecting`" messages.
Spring Integration, together with https://projects.spring.io/spring-security/[Spring Security], provides a simple and comprehensive way to secure message channels, as well as other part of the integration solution.
Starting with version 6.0, the `ChannelSecurityInterceptor` as well as its configuration via `@SecuredChannel` annotation and XML `<secured-channels>` have been deprecation in favor of using `AuthorizationChannelInterceptor` from the `spring-security-messaging` module.
The respective `AuthorizationManager` infrastructure fully covers the previously supported role-based authentication, plus it allows the configuration of any other possible authorization strategies.
The only remaining Spring Integration `SecurityContextPropagationChannelInterceptor` class has been deprecated and promoted to the mentioned `spring-security-messaging` module as an `org.springframework.security.messaging.context.SecurityContextPropagationChannelInterceptor` class.
Therefore, starting with version `6.2` the whole `spring-integration-security` module is considered as deprecated in favor of an API proposed by the more common `spring-security-messaging` library.
This module is scheduled for removal in the next `6.3` version.
NOTE: Starting with version `6.3` the whole `spring-integration-security` module is removed in favor of an API proposed by the more common `spring-security-messaging` library.
[[securing-channels]]
== Securing channels

View File

@@ -2,90 +2,25 @@
= What's New?
[[spring-integration-intro-new]]
For those who are already familiar with Spring Integration, this chapter provides a brief overview of the new features of version 6.2.
For those who are already familiar with Spring Integration, this chapter provides a brief overview of the new features of version 6.3.
If you are interested in the changes and features that were introduced in earlier versions, see the xref:history.adoc[Change History].
[[whats-new]]
[[what-s-new-in-spring-integration-6-3]]
== What's New in Spring Integration 6.3?
[[what-s-new-in-spring-integration-6-2]]
== What's New in Spring Integration 6.2?
If you are interested in more details, see the Issue Tracker tickets that were resolved as part of the 6.2 development process.
If you are interested in more details, see the Issue Tracker tickets that were resolved as part of the 6.3 development process.
In general the project has been moved to the latest dependency versions.
[[x6.2-new-components]]
[[x6.3-new-components]]
=== New Components
[[x6.2-debezium]]
==== Debezium Inbound Channel Adapter
The Debezium Engine based Change Data Capture (CDC) channel adapter, that allows capturing database change events, converting them into Messages and streaming those to the outbound channels.
See xref:debezium.adoc[Debezium Support] for more information.
[[x6.2-general]]
[[x6.3-general]]
=== General Changes
- The XML configuration for `<poller>` and `@Poller` annotation now support ISO 8601 duration format for `fixed-delay`, `fixed-rate` and `initial-delay` options.
See xref:endpoint.adoc#endpoint-pollingconsumer[Polling Consumer] for more information.
- Java, Groovy and Kotlin DSLs have now context-specific methods in the `IntegrationFlowDefinition` with a single `Consumer` argument to configure an endpoint and its handler with one builder and readable options.
See, for example, `transformWith()`, `splitWith()` in xref:dsl.adoc#java-dsl[Java DSL Chapter].
- A new `spring.integration.endpoints.defaultTimeout` global property has been introduced to override the default 30 seconds timeout for all the endpoints in the application.
See xref:configuration/global-properties.adoc[Global Properties] for more information.
- The `@MessagingGateway` and `GatewayEndpointSpec` provided by the Java DSL now expose the `errorOnTimeout` property of the internal `MethodInvocationGateway` extension of the `MessagingGatewaySupport`.
See xref:gateway.adoc#gateway-no-response[Gateway Behavior When No response Arrives] for more information.
- The `LockRegistry` provides template-like API to execute provided task while locked.
See xref:distributed-locks.adoc[Distributed Locks] for more information.
- The default trigger for polling endpoint is now a `PeriodicTrigger` instance with a 1 second fixed delay period; previously, the default was 10 milliseconds.
See xref:endpoint.adoc#endpoint-pollingconsumer[Polling Consumer] for more information.
[[x6.2-websockets]]
=== WebSockets Changes
- For the server and client WebSocket containers, the send buffer overflow strategy is now configurable in `IntegrationWebSocketContainer` and in XML via `send-buffer-overflow-strategy`.
This strategy determines the behavior when a session's outbound message buffer has reached the configured limit.
See xref:web-sockets.adoc#websocket-client-container-attributes[WebSockets Support] for more information.
[[x6.2-kafka]]
=== Apache Kafka Support Changes
The `KafkaMessageSource` now extracts an `ErrorHandlingDeserializer` configuration from the consumer properties and re-throws `DeserializationException` extracted from failed record headers.
See xref:kafka.adoc#kafka-inbound-pollable[Kafka Inbound Channel Adapter] for more information.
[[x6.2-jdbc]]
=== JDBC Support Changes
The `JdbcMessageStore`, `JdbcChannelMessageStore`, `JdbcMetadataStore`, and `DefaultLockRepository` implement `SmartLifecycle` and perform a `SELECT COUNT` query, on their respective tables, in the `start()` method to ensure that the required table (according to the provided prefix) is present in the target database.
The `PostgresChannelMessageStoreQueryProvider` now provides single `DELETE...RETURNING` statement for polling queries.
For this purpose the `ChannelMessageStoreQueryProvider` exposes `isSingleStatementForPoll` option which is consulted from the `JdbcChannelMessageStore`.
See xref:jdbc/message-store.adoc[JDBC Message Store] for more information.
[[x6.2-mongodb]]
=== MongoDB Support Changes
A new option `setCreateIndexes(boolean)` has been introduced in `AbstractConfigurableMongoDbMessageStore` to disable the auto indexes creation.
See xref:mongodb.adoc#mongodb-message-store[MongoDB Message Store] for an example.
[[x6.2-remote-files]]
=== Remote Files Support Changes
`FtpLastModifiedFileListFilter`, `SftpLastModifiedFileListFilter` and `SmbLastModifiedFileListFilter` have been introduced to allow files filtering based on a last-modified strategy respectively for `FTP`, `SFTP` and `SMB`.
See xref:ftp/inbound.adoc#ftp-inbound[FTP Inbound Channel Adapter], xref:sftp/inbound.adoc#sftp-inbound[SFTP Inbound Channel Adapter], and xref:smb.adoc#smb-inbound[SMB Inbound Channel Adapter] for more information.
[[x6.2-sftp-changes]]
=== SFTP Support Changes
A new `DefaultSftpSessionFactory.createSftpClient(...)` method has been introduced to support a custom `SftpClient` when overridden.
See xref:sftp/session-factory.adoc#sftp-session-factory[SFTP Session Factory] for more information.
[[x6.2-security-changes]]
[[x6.3-security-changes]]
=== Security Support Changes
The last class in `spring-integration-security` module `SecurityContextPropagationChannelInterceptor` has been deprecated in favor of similar class moved to `spring-security-messaging` module.
The `spring-integration-security` module is completely removed (being deprecated previously) in favor of API from `spring-security-messaging` module.
See xref:security.adoc[Security in Spring Integration] for more information.

View File

@@ -177,9 +177,9 @@ You can also set the header by using the XMPP header-enricher support, as the fo
----
Starting with version 4.3, the packet extension support has been added to the `ChatMessageSendingMessageHandler` (the `<int-xmpp:outbound-channel-adapter>` in XML configuration).
Along with the regular `String` and `org.jivesoftware.smack.packet.Message` payload, now you can send a message with a payload of `org.jivesoftware.smack.packet.ExtensionElement` (which is populated to the `org.jivesoftware.smack.packet.Message.addExtension()`) instead of `setBody()`.
Along with the regular `String` and `org.jivesoftware.smack.packet.Message` payload, now you can send a message with a payload of `org.jivesoftware.smack.packet.XmlElement` (which is populated to the `org.jivesoftware.smack.packet.Message.addExtension()`) instead of `setBody()`.
For convenience, we added an `extension-provider` option for the `ChatMessageSendingMessageHandler`.
It lets you inject `org.jivesoftware.smack.provider.ExtensionElementProvider`, which builds an `ExtensionElement` against the payload at runtime.
It lets you inject `org.jivesoftware.smack.provider.ExtensionElementProvider`, which builds an `XmlElement` against the payload at runtime.
For this case, the payload must be a string in JSON or XML format, depending on the XEP protocol.
[[xmpp-presence]]