Clean up and improve Java DSL for JDBC

Follow up for: https://github.com/spring-projects/spring-integration/pull/10081

* Rename `StoredProcExecutorConfigurer` to `StoredProcExecutorSpec`
* Add `Jdbc.storedProcExecutorSpec()` factory
* Improve logic of `StoredProcExecutor`-based Java DSL classes to handle an external `StoredProcExecutor` as well
* Add `package-info.java` into the `jdbc/dsl` package
* Add `/jdbc/dsl.adoc` and respective `What's New` entry
This commit is contained in:
Artem Bilan
2025-06-06 14:11:34 -04:00
parent cd15675734
commit b8116d59a9
15 changed files with 508 additions and 270 deletions

View File

@@ -26,6 +26,7 @@ import org.springframework.jdbc.core.JdbcTemplate;
* Factory class for JDBC components.
*
* @author Jiandong Ma
* @author Artem Bilan
*
* @since 7.0
*/
@@ -109,7 +110,9 @@ public final class Jdbc {
* @param selectQuery the select query to build on
* @return the {@link JdbcOutboundGatewaySpec} instance
*/
public static JdbcOutboundGatewaySpec outboundGateway(JdbcOperations jdbcOperations, String updateQuery, String selectQuery) {
public static JdbcOutboundGatewaySpec outboundGateway(JdbcOperations jdbcOperations, String updateQuery,
String selectQuery) {
return new JdbcOutboundGatewaySpec(jdbcOperations, updateQuery, selectQuery);
}
@@ -119,7 +122,18 @@ public final class Jdbc {
* @return the {@link JdbcStoredProcInboundChannelAdapterSpec} instance
*/
public static JdbcStoredProcInboundChannelAdapterSpec storedProcInboundAdapter(DataSource dataSource) {
return new JdbcStoredProcInboundChannelAdapterSpec(new StoredProcExecutor(dataSource));
return new JdbcStoredProcInboundChannelAdapterSpec(storedProcExecutorSpec(dataSource));
}
/**
* The factory to produce a {@link JdbcStoredProcInboundChannelAdapterSpec}.
* @param storedProcExecutor the {@link StoredProcExecutor} to use
* @return the {@link JdbcStoredProcInboundChannelAdapterSpec} instance
*/
public static JdbcStoredProcInboundChannelAdapterSpec storedProcInboundAdapter(
StoredProcExecutor storedProcExecutor) {
return new JdbcStoredProcInboundChannelAdapterSpec(storedProcExecutor);
}
/**
@@ -128,7 +142,18 @@ public final class Jdbc {
* @return the {@link JdbcStoredProcOutboundChannelAdapterSpec} instance
*/
public static JdbcStoredProcOutboundChannelAdapterSpec storedProcOutboundAdapter(DataSource dataSource) {
return new JdbcStoredProcOutboundChannelAdapterSpec(new StoredProcExecutor(dataSource));
return new JdbcStoredProcOutboundChannelAdapterSpec(storedProcExecutorSpec(dataSource));
}
/**
* The factory to produce a {@link JdbcStoredProcOutboundChannelAdapterSpec}.
* @param storedProcExecutor the {@link StoredProcExecutor} to use
* @return the {@link JdbcStoredProcOutboundChannelAdapterSpec} instance
*/
public static JdbcStoredProcOutboundChannelAdapterSpec storedProcOutboundAdapter(
StoredProcExecutor storedProcExecutor) {
return new JdbcStoredProcOutboundChannelAdapterSpec(storedProcExecutor);
}
/**
@@ -137,7 +162,25 @@ public final class Jdbc {
* @return the {@link JdbcStoredProcOutboundGatewaySpec} instance
*/
public static JdbcStoredProcOutboundGatewaySpec storedProcOutboundGateway(DataSource dataSource) {
return new JdbcStoredProcOutboundGatewaySpec(new StoredProcExecutor(dataSource));
return new JdbcStoredProcOutboundGatewaySpec(storedProcExecutorSpec(dataSource));
}
/**
* The factory to produce a {@link JdbcStoredProcOutboundGatewaySpec}.
* @param storedProcExecutor the {@link StoredProcExecutor} to use
* @return the {@link JdbcStoredProcOutboundGatewaySpec} instance
*/
public static JdbcStoredProcOutboundGatewaySpec storedProcOutboundGateway(StoredProcExecutor storedProcExecutor) {
return new JdbcStoredProcOutboundGatewaySpec(storedProcExecutor);
}
/**
* The factory to produce a {@link StoredProcExecutorSpec}.
* @param dataSource the {@link DataSource} to build on
* @return the {@link StoredProcExecutorSpec} instance
*/
public static StoredProcExecutorSpec storedProcExecutorSpec(DataSource dataSource) {
return new StoredProcExecutorSpec(dataSource);
}
private Jdbc() {

View File

@@ -27,10 +27,12 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
* A {@link MessageSourceSpec} for a {@link JdbcInboundChannelAdapterSpec}.
*
* @author Jiandong Ma
* @author Artem Bilan
*
* @since 7.0
*/
public class JdbcInboundChannelAdapterSpec extends MessageSourceSpec<JdbcInboundChannelAdapterSpec, JdbcPollingChannelAdapter> {
public class JdbcInboundChannelAdapterSpec
extends MessageSourceSpec<JdbcInboundChannelAdapterSpec, JdbcPollingChannelAdapter> {
protected JdbcInboundChannelAdapterSpec(JdbcOperations jdbcOperations, String selectQuery) {
this.target = new JdbcPollingChannelAdapter(jdbcOperations, selectQuery);
@@ -43,7 +45,7 @@ public class JdbcInboundChannelAdapterSpec extends MessageSourceSpec<JdbcInbound
*/
public JdbcInboundChannelAdapterSpec rowMapper(RowMapper<?> rowMapper) {
this.target.setRowMapper(rowMapper);
return _this();
return this;
}
/**
@@ -53,7 +55,7 @@ public class JdbcInboundChannelAdapterSpec extends MessageSourceSpec<JdbcInbound
*/
public JdbcInboundChannelAdapterSpec updateSql(String updateSql) {
this.target.setUpdateSql(updateSql);
return _this();
return this;
}
/**
@@ -63,7 +65,7 @@ public class JdbcInboundChannelAdapterSpec extends MessageSourceSpec<JdbcInbound
*/
public JdbcInboundChannelAdapterSpec updatePerRow(boolean updatePerRow) {
this.target.setUpdatePerRow(updatePerRow);
return _this();
return this;
}
/**
@@ -71,9 +73,11 @@ public class JdbcInboundChannelAdapterSpec extends MessageSourceSpec<JdbcInbound
* @return the spec
* @see JdbcPollingChannelAdapter#setUpdateSqlParameterSourceFactory(SqlParameterSourceFactory)
*/
public JdbcInboundChannelAdapterSpec updateSqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
public JdbcInboundChannelAdapterSpec updateSqlParameterSourceFactory(
SqlParameterSourceFactory sqlParameterSourceFactory) {
this.target.setUpdateSqlParameterSourceFactory(sqlParameterSourceFactory);
return _this();
return this;
}
/**
@@ -83,7 +87,7 @@ public class JdbcInboundChannelAdapterSpec extends MessageSourceSpec<JdbcInbound
*/
public JdbcInboundChannelAdapterSpec selectSqlParameterSource(SqlParameterSource sqlQueryParameterSource) {
this.target.setSelectSqlParameterSource(sqlQueryParameterSource);
return _this();
return this;
}
/**
@@ -93,7 +97,7 @@ public class JdbcInboundChannelAdapterSpec extends MessageSourceSpec<JdbcInbound
*/
public JdbcInboundChannelAdapterSpec maxRows(int maxRows) {
this.target.setMaxRows(maxRows);
return _this();
return this;
}
}

View File

@@ -26,10 +26,12 @@ import org.springframework.jdbc.core.JdbcOperations;
* A {@link MessageHandlerSpec} for a {@link JdbcOutboundChannelAdapterSpec}.
*
* @author Jiandong Ma
* @author Artem Bilan
*
* @since 7.0
*/
public class JdbcOutboundChannelAdapterSpec extends MessageHandlerSpec<JdbcOutboundChannelAdapterSpec, JdbcMessageHandler> {
public class JdbcOutboundChannelAdapterSpec
extends MessageHandlerSpec<JdbcOutboundChannelAdapterSpec, JdbcMessageHandler> {
protected JdbcOutboundChannelAdapterSpec(JdbcOperations jdbcOperations, String updateQuery) {
this.target = new JdbcMessageHandler(jdbcOperations, updateQuery);
@@ -42,7 +44,7 @@ public class JdbcOutboundChannelAdapterSpec extends MessageHandlerSpec<JdbcOutbo
*/
public JdbcOutboundChannelAdapterSpec keysGenerated(boolean keysGenerated) {
this.target.setKeysGenerated(keysGenerated);
return _this();
return this;
}
/**
@@ -50,9 +52,11 @@ public class JdbcOutboundChannelAdapterSpec extends MessageHandlerSpec<JdbcOutbo
* @return the spec
* @see JdbcMessageHandler#setSqlParameterSourceFactory(SqlParameterSourceFactory)
*/
public JdbcOutboundChannelAdapterSpec sqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
public JdbcOutboundChannelAdapterSpec sqlParameterSourceFactory(
SqlParameterSourceFactory sqlParameterSourceFactory) {
this.target.setSqlParameterSourceFactory(sqlParameterSourceFactory);
return _this();
return this;
}
/**
@@ -62,7 +66,7 @@ public class JdbcOutboundChannelAdapterSpec extends MessageHandlerSpec<JdbcOutbo
*/
public JdbcOutboundChannelAdapterSpec usePayloadAsParameterSource(boolean usePayloadAsParameterSource) {
this.target.setUsePayloadAsParameterSource(usePayloadAsParameterSource);
return _this();
return this;
}
/**
@@ -70,9 +74,11 @@ public class JdbcOutboundChannelAdapterSpec extends MessageHandlerSpec<JdbcOutbo
* @return the spec
* @see JdbcMessageHandler#setPreparedStatementSetter(MessagePreparedStatementSetter)
*/
public JdbcOutboundChannelAdapterSpec preparedStatementSetter(MessagePreparedStatementSetter preparedStatementSetter) {
public JdbcOutboundChannelAdapterSpec preparedStatementSetter(
MessagePreparedStatementSetter preparedStatementSetter) {
this.target.setPreparedStatementSetter(preparedStatementSetter);
return _this();
return this;
}
}

View File

@@ -27,6 +27,7 @@ import org.springframework.jdbc.core.RowMapper;
* A {@link MessageHandlerSpec} for a {@link JdbcOutboundGatewaySpec}.
*
* @author Jiandong Ma
* @author Artem Bilan
*
* @since 7.0
*/
@@ -43,7 +44,7 @@ public class JdbcOutboundGatewaySpec extends MessageHandlerSpec<JdbcOutboundGate
*/
public JdbcOutboundGatewaySpec maxRows(Integer maxRows) {
this.target.setMaxRows(maxRows);
return _this();
return this;
}
/**
@@ -53,7 +54,7 @@ public class JdbcOutboundGatewaySpec extends MessageHandlerSpec<JdbcOutboundGate
*/
public JdbcOutboundGatewaySpec keysGenerated(boolean keysGenerated) {
this.target.setKeysGenerated(keysGenerated);
return _this();
return this;
}
/**
@@ -61,9 +62,11 @@ public class JdbcOutboundGatewaySpec extends MessageHandlerSpec<JdbcOutboundGate
* @return the spec
* @see JdbcOutboundGateway#setRequestSqlParameterSourceFactory(SqlParameterSourceFactory)
*/
public JdbcOutboundGatewaySpec requestSqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
public JdbcOutboundGatewaySpec requestSqlParameterSourceFactory(
SqlParameterSourceFactory sqlParameterSourceFactory) {
this.target.setRequestSqlParameterSourceFactory(sqlParameterSourceFactory);
return _this();
return this;
}
/**
@@ -71,9 +74,11 @@ public class JdbcOutboundGatewaySpec extends MessageHandlerSpec<JdbcOutboundGate
* @return the spec
* @see JdbcOutboundGateway#setRequestPreparedStatementSetter(MessagePreparedStatementSetter)
*/
public JdbcOutboundGatewaySpec requestPreparedStatementSetter(MessagePreparedStatementSetter preparedStatementSetter) {
public JdbcOutboundGatewaySpec requestPreparedStatementSetter(
MessagePreparedStatementSetter preparedStatementSetter) {
this.target.setRequestPreparedStatementSetter(preparedStatementSetter);
return _this();
return this;
}
/**
@@ -83,7 +88,7 @@ public class JdbcOutboundGatewaySpec extends MessageHandlerSpec<JdbcOutboundGate
*/
public JdbcOutboundGatewaySpec replySqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
this.target.setReplySqlParameterSourceFactory(sqlParameterSourceFactory);
return _this();
return this;
}
/**
@@ -93,7 +98,7 @@ public class JdbcOutboundGatewaySpec extends MessageHandlerSpec<JdbcOutboundGate
*/
public JdbcOutboundGatewaySpec rowMapper(RowMapper<?> rowMapper) {
this.target.setRowMapper(rowMapper);
return _this();
return this;
}
}

View File

@@ -20,6 +20,8 @@ import java.util.Collections;
import java.util.Map;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.springframework.integration.dsl.ComponentsRegistration;
import org.springframework.integration.dsl.MessageSourceSpec;
import org.springframework.integration.jdbc.StoredProcExecutor;
@@ -30,6 +32,7 @@ import org.springframework.util.Assert;
* A {@link MessageSourceSpec} for a {@link JdbcStoredProcInboundChannelAdapterSpec}.
*
* @author Jiandong Ma
* @author Artem Bilan
*
* @since 7.0
*/
@@ -39,11 +42,16 @@ public class JdbcStoredProcInboundChannelAdapterSpec
private final StoredProcExecutor storedProcExecutor;
private final StoredProcExecutorConfigurer storedProcExecutorConfigurer;
private @Nullable StoredProcExecutorSpec storedProcExecutorSpec;
protected JdbcStoredProcInboundChannelAdapterSpec(StoredProcExecutorSpec storedProcExecutorSpec) {
this(storedProcExecutorSpec.getObject());
this.storedProcExecutorSpec = storedProcExecutorSpec;
}
protected JdbcStoredProcInboundChannelAdapterSpec(StoredProcExecutor storedProcExecutor) {
this.storedProcExecutor = storedProcExecutor;
this.storedProcExecutorConfigurer = new StoredProcExecutorConfigurer(this.storedProcExecutor);
this.storedProcExecutorSpec = null;
this.target = new StoredProcPollingChannelAdapter(this.storedProcExecutor);
}
@@ -52,10 +60,14 @@ public class JdbcStoredProcInboundChannelAdapterSpec
* @param configurer the configurer.
* @return the spec
*/
public JdbcStoredProcInboundChannelAdapterSpec configurerStoredProcExecutor(Consumer<StoredProcExecutorConfigurer> configurer) {
public JdbcStoredProcInboundChannelAdapterSpec configurerStoredProcExecutor(
Consumer<StoredProcExecutorSpec> configurer) {
Assert.notNull(configurer, "'configurer' must not be null");
configurer.accept(this.storedProcExecutorConfigurer);
return _this();
Assert.notNull(this.storedProcExecutorSpec,
"The externally provided 'StoredProcExecutor' cannot be mutated in this spec");
configurer.accept(this.storedProcExecutorSpec);
return this;
}
/**
@@ -65,11 +77,12 @@ public class JdbcStoredProcInboundChannelAdapterSpec
*/
public JdbcStoredProcInboundChannelAdapterSpec expectSingleResult(boolean expectSingleResult) {
this.target.setExpectSingleResult(expectSingleResult);
return _this();
return this;
}
@Override
public Map<Object, String> getComponentsToRegister() {
return Collections.singletonMap(this.storedProcExecutor, null);
}
}

View File

@@ -20,6 +20,8 @@ import java.util.Collections;
import java.util.Map;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.springframework.integration.dsl.ComponentsRegistration;
import org.springframework.integration.dsl.MessageHandlerSpec;
import org.springframework.integration.jdbc.StoredProcExecutor;
@@ -30,6 +32,7 @@ import org.springframework.util.Assert;
* A {@link MessageHandlerSpec} for a {@link JdbcStoredProcOutboundChannelAdapterSpec}.
*
* @author Jiandong Ma
* @author Artem Bilan
*
* @since 7.0
*/
@@ -39,11 +42,16 @@ public class JdbcStoredProcOutboundChannelAdapterSpec
private final StoredProcExecutor storedProcExecutor;
private final StoredProcExecutorConfigurer storedProcExecutorConfigurer;
private @Nullable StoredProcExecutorSpec storedProcExecutorSpec;
protected JdbcStoredProcOutboundChannelAdapterSpec(StoredProcExecutorSpec storedProcExecutorSpec) {
this(storedProcExecutorSpec.getObject());
this.storedProcExecutorSpec = storedProcExecutorSpec;
}
protected JdbcStoredProcOutboundChannelAdapterSpec(StoredProcExecutor storedProcExecutor) {
this.storedProcExecutor = storedProcExecutor;
this.storedProcExecutorConfigurer = new StoredProcExecutorConfigurer(this.storedProcExecutor);
this.storedProcExecutorSpec = null;
this.target = new StoredProcMessageHandler(this.storedProcExecutor);
}
@@ -52,14 +60,19 @@ public class JdbcStoredProcOutboundChannelAdapterSpec
* @param configurer the configurer.
* @return the spec
*/
public JdbcStoredProcOutboundChannelAdapterSpec configurerStoredProcExecutor(Consumer<StoredProcExecutorConfigurer> configurer) {
public JdbcStoredProcOutboundChannelAdapterSpec configurerStoredProcExecutor(
Consumer<StoredProcExecutorSpec> configurer) {
Assert.notNull(configurer, "'configurer' must not be null");
configurer.accept(this.storedProcExecutorConfigurer);
return _this();
Assert.notNull(this.storedProcExecutorSpec,
"The externally provided 'StoredProcExecutor' cannot be mutated in this spec");
configurer.accept(this.storedProcExecutorSpec);
return this;
}
@Override
public Map<Object, String> getComponentsToRegister() {
return Collections.singletonMap(this.storedProcExecutor, null);
}
}

View File

@@ -20,6 +20,8 @@ import java.util.Collections;
import java.util.Map;
import java.util.function.Consumer;
import org.jspecify.annotations.Nullable;
import org.springframework.integration.dsl.ComponentsRegistration;
import org.springframework.integration.dsl.MessageHandlerSpec;
import org.springframework.integration.jdbc.StoredProcExecutor;
@@ -30,6 +32,7 @@ import org.springframework.util.Assert;
* A {@link MessageHandlerSpec} for a {@link JdbcStoredProcOutboundGatewaySpec}.
*
* @author Jiandong Ma
* @author Artem Bilan
*
* @since 7.0
*/
@@ -39,11 +42,16 @@ public class JdbcStoredProcOutboundGatewaySpec
private final StoredProcExecutor storedProcExecutor;
private final StoredProcExecutorConfigurer storedProcExecutorConfigurer;
private @Nullable StoredProcExecutorSpec storedProcExecutorSpec;
protected JdbcStoredProcOutboundGatewaySpec(StoredProcExecutorSpec storedProcExecutorSpec) {
this(storedProcExecutorSpec.getObject());
this.storedProcExecutorSpec = storedProcExecutorSpec;
}
protected JdbcStoredProcOutboundGatewaySpec(StoredProcExecutor storedProcExecutor) {
this.storedProcExecutor = storedProcExecutor;
this.storedProcExecutorConfigurer = new StoredProcExecutorConfigurer(this.storedProcExecutor);
this.storedProcExecutorSpec = null;
this.target = new StoredProcOutboundGateway(this.storedProcExecutor);
}
@@ -52,10 +60,12 @@ public class JdbcStoredProcOutboundGatewaySpec
* @param configurer the configurer.
* @return the spec
*/
public JdbcStoredProcOutboundGatewaySpec configurerStoredProcExecutor(Consumer<StoredProcExecutorConfigurer> configurer) {
public JdbcStoredProcOutboundGatewaySpec configurerStoredProcExecutor(Consumer<StoredProcExecutorSpec> configurer) {
Assert.notNull(configurer, "'configurer' must not be null");
configurer.accept(this.storedProcExecutorConfigurer);
return _this();
Assert.notNull(this.storedProcExecutorSpec,
"The externally provided 'StoredProcExecutor' cannot be mutated in this spec");
configurer.accept(this.storedProcExecutorSpec);
return this;
}
/**
@@ -65,7 +75,7 @@ public class JdbcStoredProcOutboundGatewaySpec
*/
public JdbcStoredProcOutboundGatewaySpec requiresReply(boolean requiresReply) {
this.target.setRequiresReply(requiresReply);
return _this();
return this;
}
/**
@@ -75,11 +85,12 @@ public class JdbcStoredProcOutboundGatewaySpec
*/
public JdbcStoredProcOutboundGatewaySpec expectSingleResult(boolean expectSingleResult) {
this.target.setExpectSingleResult(expectSingleResult);
return _this();
return this;
}
@Override
public Map<Object, String> getComponentsToRegister() {
return Collections.singletonMap(this.storedProcExecutor, null);
}
}

View File

@@ -1,163 +0,0 @@
/*
* Copyright 2025 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.jdbc.dsl;
import java.util.List;
import java.util.Map;
import org.springframework.expression.Expression;
import org.springframework.integration.jdbc.SqlParameterSourceFactory;
import org.springframework.integration.jdbc.StoredProcExecutor;
import org.springframework.integration.jdbc.storedproc.ProcedureParameter;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
/**
* A {@link StoredProcExecutor} configurer.
*
* @author Jiandong Ma
*
* @since 7.0
*/
public class StoredProcExecutorConfigurer {
private final StoredProcExecutor storedProcExecutor;
protected StoredProcExecutorConfigurer(StoredProcExecutor storedProcExecutor) {
this.storedProcExecutor = storedProcExecutor;
}
/**
* @param ignoreColumnMetaData the ignoreColumnMetaData
* @return the storedProcExecutor
* @see StoredProcExecutor#setIgnoreColumnMetaData(boolean)
*/
public StoredProcExecutorConfigurer ignoreColumnMetaData(boolean ignoreColumnMetaData) {
this.storedProcExecutor.setIgnoreColumnMetaData(ignoreColumnMetaData);
return this;
}
/**
* @param procedureParameters the procedureParameters
* @return the storedProcExecutor
* @see StoredProcExecutor#setProcedureParameters(List)
*/
public StoredProcExecutorConfigurer procedureParameters(List<ProcedureParameter> procedureParameters) {
this.storedProcExecutor.setProcedureParameters(procedureParameters);
return this;
}
/**
* @param sqlParameters the sqlParameters
* @return the storedProcExecutor
* @see StoredProcExecutor#setSqlParameters(List)
*/
public StoredProcExecutorConfigurer sqlParameters(List<SqlParameter> sqlParameters) {
this.storedProcExecutor.setSqlParameters(sqlParameters);
return this;
}
/**
* @param sqlParameterSourceFactory the sqlParameterSourceFactory
* @return the storedProcExecutor
* @see StoredProcExecutor#setSqlParameterSourceFactory(SqlParameterSourceFactory)
*/
public StoredProcExecutorConfigurer sqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
this.storedProcExecutor.setSqlParameterSourceFactory(sqlParameterSourceFactory);
return this;
}
/**
* @param storedProcedureName the storedProcedureName
* @return the storedProcExecutor
* @see StoredProcExecutor#setStoredProcedureName(String)
*/
public StoredProcExecutorConfigurer storedProcedureName(String storedProcedureName) {
this.storedProcExecutor.setStoredProcedureName(storedProcedureName);
return this;
}
/**
* @param storedProcedureNameExpression the storedProcedureNameExpression
* @return the storedProcExecutor
* @see StoredProcExecutor#setStoredProcedureNameExpression(Expression)
*/
public StoredProcExecutorConfigurer storedProcedureNameExpression(Expression storedProcedureNameExpression) {
this.storedProcExecutor.setStoredProcedureNameExpression(storedProcedureNameExpression);
return this;
}
/**
* @param usePayloadAsParameterSource the usePayloadAsParameterSource
* @return the storedProcExecutor
* @see StoredProcExecutor#setUsePayloadAsParameterSource(boolean)
*/
public StoredProcExecutorConfigurer usePayloadAsParameterSource(boolean usePayloadAsParameterSource) {
this.storedProcExecutor.setUsePayloadAsParameterSource(usePayloadAsParameterSource);
return this;
}
/**
* @param isFunction the isFunction
* @return the storedProcExecutor
* @see StoredProcExecutor#setIsFunction(boolean)
*/
public StoredProcExecutorConfigurer isFunction(boolean isFunction) {
this.storedProcExecutor.setIsFunction(isFunction);
return this;
}
/**
* @param returnValueRequired the returnValueRequired
* @return the storedProcExecutor
* @see StoredProcExecutor#setReturnValueRequired(boolean)
*/
public StoredProcExecutorConfigurer returnValueRequired(boolean returnValueRequired) {
this.storedProcExecutor.setReturnValueRequired(returnValueRequired);
return this;
}
/**
* @param skipUndeclaredResults the skipUndeclaredResults
* @return the storedProcExecutor
* @see StoredProcExecutor#setSkipUndeclaredResults(boolean)
*/
public StoredProcExecutorConfigurer skipUndeclaredResults(boolean skipUndeclaredResults) {
this.storedProcExecutor.setSkipUndeclaredResults(skipUndeclaredResults);
return this;
}
/**
* @param returningResultSetRowMappers the returningResultSetRowMappers
* @return the storedProcExecutor
* @see StoredProcExecutor#setReturningResultSetRowMappers(Map)
*/
public StoredProcExecutorConfigurer returningResultSetRowMappers(Map<String, RowMapper<?>> returningResultSetRowMappers) {
this.storedProcExecutor.setReturningResultSetRowMappers(returningResultSetRowMappers);
return this;
}
/**
* @param jdbcCallOperationsCacheSize the jdbcCallOperationsCacheSize
* @return the storedProcExecutor
* @see StoredProcExecutor#setJdbcCallOperationsCacheSize(int)
*/
public StoredProcExecutorConfigurer jdbcCallOperationsCacheSize(int jdbcCallOperationsCacheSize) {
this.storedProcExecutor.setJdbcCallOperationsCacheSize(jdbcCallOperationsCacheSize);
return this;
}
}

View File

@@ -0,0 +1,213 @@
/*
* Copyright 2025 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.jdbc.dsl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.expression.Expression;
import org.springframework.integration.dsl.IntegrationComponentSpec;
import org.springframework.integration.jdbc.SqlParameterSourceFactory;
import org.springframework.integration.jdbc.StoredProcExecutor;
import org.springframework.integration.jdbc.storedproc.ProcedureParameter;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
/**
* A {@link StoredProcExecutor} configurer.
*
* @author Jiandong Ma
* @author Artem Bilan
*
* @since 7.0
*/
public class StoredProcExecutorSpec extends IntegrationComponentSpec<StoredProcExecutorSpec, StoredProcExecutor> {
private final List<ProcedureParameter> procedureParameters = new ArrayList<>();
private final List<SqlParameter> sqlParameters = new ArrayList<>();
private final Map<String, RowMapper<?>> returningResultSetRowMappers = new HashMap<>();
protected StoredProcExecutorSpec(DataSource dataSource) {
this.target = new StoredProcExecutor(dataSource);
this.target.setReturningResultSetRowMappers(this.returningResultSetRowMappers);
}
/**
* @param ignoreColumnMetaData the ignoreColumnMetaData
* @return the storedProcExecutor
* @see StoredProcExecutor#setIgnoreColumnMetaData(boolean)
*/
public StoredProcExecutorSpec ignoreColumnMetaData(boolean ignoreColumnMetaData) {
this.target.setIgnoreColumnMetaData(ignoreColumnMetaData);
return this;
}
/**
* Add a {@link ProcedureParameter} parameter to the target {@link StoredProcExecutor}.
* This method can be called several times adding a new parameter each time.
* @param procedureParameter the stored procedure parameter to add
* @return the storedProcExecutor spec
* @see StoredProcExecutor#setProcedureParameters(List)
*/
public StoredProcExecutorSpec procedureParameter(ProcedureParameter procedureParameter) {
this.procedureParameters.add(procedureParameter);
this.target.setProcedureParameters(this.procedureParameters);
return this;
}
/**
* @param procedureParameters the procedureParameters
* @return the storedProcExecutor
* @see StoredProcExecutor#setProcedureParameters(List)
*/
public StoredProcExecutorSpec procedureParameters(List<ProcedureParameter> procedureParameters) {
this.target.setProcedureParameters(procedureParameters);
return this;
}
/**
* Add an {@link SqlParameter} to the target {@link StoredProcExecutor}.
* This method can be called several times adding a new parameter each time.
* @param sqlParameter the {@link SqlParameter} to add
* @return the storedProcExecutor
* @see StoredProcExecutor#setSqlParameters(List)
*/
public StoredProcExecutorSpec sqlParameter(SqlParameter sqlParameter) {
this.sqlParameters.add(sqlParameter);
this.target.setSqlParameters(this.sqlParameters);
return this;
}
/**
* @param sqlParameters the sqlParameters
* @return the storedProcExecutor
* @see StoredProcExecutor#setSqlParameters(List)
*/
public StoredProcExecutorSpec sqlParameters(List<SqlParameter> sqlParameters) {
this.target.setSqlParameters(sqlParameters);
return this;
}
/**
* @param sqlParameterSourceFactory the sqlParameterSourceFactory
* @return the storedProcExecutor
* @see StoredProcExecutor#setSqlParameterSourceFactory(SqlParameterSourceFactory)
*/
public StoredProcExecutorSpec sqlParameterSourceFactory(SqlParameterSourceFactory sqlParameterSourceFactory) {
this.target.setSqlParameterSourceFactory(sqlParameterSourceFactory);
return this;
}
/**
* @param storedProcedureName the storedProcedureName
* @return the storedProcExecutor
* @see StoredProcExecutor#setStoredProcedureName(String)
*/
public StoredProcExecutorSpec storedProcedureName(String storedProcedureName) {
this.target.setStoredProcedureName(storedProcedureName);
return this;
}
/**
* @param storedProcedureNameExpression the storedProcedureNameExpression
* @return the storedProcExecutor
* @see StoredProcExecutor#setStoredProcedureNameExpression(Expression)
*/
public StoredProcExecutorSpec storedProcedureNameExpression(Expression storedProcedureNameExpression) {
this.target.setStoredProcedureNameExpression(storedProcedureNameExpression);
return this;
}
/**
* @param usePayloadAsParameterSource the usePayloadAsParameterSource
* @return the storedProcExecutor
* @see StoredProcExecutor#setUsePayloadAsParameterSource(boolean)
*/
public StoredProcExecutorSpec usePayloadAsParameterSource(boolean usePayloadAsParameterSource) {
this.target.setUsePayloadAsParameterSource(usePayloadAsParameterSource);
return this;
}
/**
* @param isFunction the isFunction
* @return the storedProcExecutor
* @see StoredProcExecutor#setIsFunction(boolean)
*/
public StoredProcExecutorSpec isFunction(boolean isFunction) {
this.target.setIsFunction(isFunction);
return this;
}
/**
* @param returnValueRequired the returnValueRequired
* @return the storedProcExecutor
* @see StoredProcExecutor#setReturnValueRequired(boolean)
*/
public StoredProcExecutorSpec returnValueRequired(boolean returnValueRequired) {
this.target.setReturnValueRequired(returnValueRequired);
return this;
}
/**
* @param skipUndeclaredResults the skipUndeclaredResults
* @return the storedProcExecutor
* @see StoredProcExecutor#setSkipUndeclaredResults(boolean)
*/
public StoredProcExecutorSpec skipUndeclaredResults(boolean skipUndeclaredResults) {
this.target.setSkipUndeclaredResults(skipUndeclaredResults);
return this;
}
/**
* Add a {@link RowMapper} for specific returning result from stored procedure execution.
* @param returningResultName the name of procedure output parameter for returning result
* @param rowMapper the {@link RowMapper} for returning result
* @return the storedProcExecutor
* @see StoredProcExecutor#setReturningResultSetRowMappers(Map)
*/
public StoredProcExecutorSpec returningResultSetRowMapper(String returningResultName, RowMapper<?> rowMapper) {
this.returningResultSetRowMappers.put(returningResultName, rowMapper);
return this;
}
/**
* @param returningResultSetRowMappers the returningResultSetRowMappers
* @return the storedProcExecutor
* @see StoredProcExecutor#setReturningResultSetRowMappers(Map)
*/
public StoredProcExecutorSpec returningResultSetRowMappers(Map<String, RowMapper<?>> returningResultSetRowMappers) {
this.target.setReturningResultSetRowMappers(returningResultSetRowMappers);
return this;
}
/**
* @param jdbcCallOperationsCacheSize the jdbcCallOperationsCacheSize
* @return the storedProcExecutor
* @see StoredProcExecutor#setJdbcCallOperationsCacheSize(int)
*/
public StoredProcExecutorSpec jdbcCallOperationsCacheSize(int jdbcCallOperationsCacheSize) {
this.target.setJdbcCallOperationsCacheSize(jdbcCallOperationsCacheSize);
return this;
}
}

View File

@@ -0,0 +1,4 @@
/**
* Java DSL classes for JDBC module.
*/
package org.springframework.integration.jdbc.dsl;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2025 the original author or authors.
* Copyright 2025 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.
@@ -24,6 +24,7 @@ import java.util.Map;
import javax.sql.DataSource;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
@@ -37,6 +38,7 @@ import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.expression.ValueExpression;
import org.springframework.integration.jdbc.BeanPropertySqlParameterSourceFactory;
import org.springframework.integration.jdbc.ExpressionEvaluatingSqlParameterSourceFactory;
import org.springframework.integration.jdbc.StoredProcExecutor;
import org.springframework.integration.jdbc.config.JdbcTypesEnum;
import org.springframework.integration.jdbc.storedproc.ClobSqlReturnType;
import org.springframework.integration.jdbc.storedproc.PrimeMapper;
@@ -48,7 +50,6 @@ import org.springframework.integration.support.json.JsonInboundMessageMapper;
import org.springframework.integration.support.json.JsonOutboundMessageMapper;
import org.springframework.integration.test.util.OnlyOnceTrigger;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.SqlReturnType;
@@ -68,12 +69,13 @@ import static org.mockito.Mockito.mock;
/**
* @author Jiandong Ma
* @author Artem Bilan
*
* @since 7.0
*/
@SpringJUnitConfig
@DirtiesContext
class JdbcTest {
class JdbcTests {
@Autowired
private JdbcTemplate h2JdbcTemplate;
@@ -123,27 +125,26 @@ class JdbcTest {
void testInboundFlow() {
Message<?> message = this.inboundFlowPollerChannel.receive(10_000);
List<?> rows = (List<?>) message.getPayload();
assertThat(rows.size()).isEqualTo(2);
assertThat(rows.get(0) instanceof Inbound).isTrue();
Inbound item = (Inbound) rows.get(0);
assertThat(item.id()).isEqualTo(1);
assertThat(item.status()).isEqualTo(2);
assertThat(rows).hasSize(2);
assertThat(rows.get(0))
.asInstanceOf(InstanceOfAssertFactories.type(Inbound.class))
.hasFieldOrPropertyWithValue("id", 1)
.hasFieldOrPropertyWithValue("status", 2);
Integer countOfStatusTwo = h2JdbcTemplate.queryForObject("select count(*) from inbound where status = 2", Integer.class);
Integer countOfStatusTwo =
h2JdbcTemplate.queryForObject("select count(*) from inbound where status = 2", Integer.class);
assertThat(countOfStatusTwo).isEqualTo(0);
Integer countOfStatusTen = h2JdbcTemplate.queryForObject("select count(*) from inbound where status = 10", Integer.class);
Integer countOfStatusTen =
h2JdbcTemplate.queryForObject("select count(*) from inbound where status = 10", Integer.class);
assertThat(countOfStatusTen).isEqualTo(2);
}
record Inbound(int id, int status) {
}
@Test
void testOutboundFlow() {
outboundFlowInputChannel.send(new GenericMessage<>("foo"));
Map<String, Object> map = h2JdbcTemplate.queryForMap("select * from outbound where id=?", 1);
assertThat(map.get("name")).isEqualTo("foo");
assertThat(map).containsEntry("name", "foo");
}
@Test
@@ -154,8 +155,9 @@ class JdbcTest {
List<?> payload = (List<?>) message.getPayload();
assertThat(payload).hasSize(1);
Object item = payload.get(0);
assertThat(item).isInstanceOf(Map.class);
assertThat(((Map<?, ?>) item).get("status")).isEqualTo(10);
assertThat(item)
.asInstanceOf(InstanceOfAssertFactories.map(String.class, Integer.class))
.containsEntry("status", 10);
}
@Test
@@ -164,8 +166,9 @@ class JdbcTest {
Message<?> message = outboundGatewayNoSelectQueryReplyChannel.receive(10_000);
assertThat(message).isNotNull();
Object payload = message.getPayload();
assertThat(payload).isInstanceOf(Map.class);
assertThat(((Map<?, ?>) payload).get("UPDATED")).isEqualTo(1);
assertThat(payload)
.asInstanceOf(InstanceOfAssertFactories.map(String.class, Integer.class))
.containsEntry("UPDATED", 1);
}
@Test
@@ -174,20 +177,17 @@ class JdbcTest {
assertThat(message).isNotNull();
Object payload = message.getPayload();
assertThat(payload).isNotNull();
assertThat(payload).isInstanceOf(List.class);
List<Integer> primeNumbers = (List<Integer>) payload;
assertThat(primeNumbers.size() == 4).isTrue();
assertThat(payload).asInstanceOf(InstanceOfAssertFactories.list(Integer.class)).hasSize(4);
}
@Test
void testStoredProcOutboundFlow() {
storedProcOutboundFlowInputChannel.send(MessageBuilder.withPayload(new User("username", "password", "email")).build());
storedProcOutboundFlowInputChannel.send(new GenericMessage<>(new User("username", "password", "email")));
Map<String, Object> map = this.derbyJdbcTemplate.queryForMap("SELECT * FROM USERS WHERE USERNAME=?", "username");
assertThat(map.get("USERNAME")).as("Wrong username").isEqualTo("username");
assertThat(map.get("PASSWORD")).as("Wrong password").isEqualTo("password");
assertThat(map.get("EMAIL")).as("Wrong email").isEqualTo("email");
assertThat(map)
.containsEntry("USERNAME", "username")
.containsEntry("PASSWORD", "password")
.containsEntry("EMAIL", "email");
}
@Test
@@ -204,7 +204,7 @@ class JdbcTest {
assertThat(resultMessage).isNotNull();
Object resultPayload = resultMessage.getPayload();
assertThat(resultPayload instanceof String).isTrue();
assertThat(resultPayload).isInstanceOf(String.class);
Message<?> message = new JsonInboundMessageMapper(String.class, new Jackson2JsonMessageParser())
.toMessage((String) resultPayload);
assertThat(message.getPayload()).isEqualTo(testMessage.getPayload());
@@ -224,7 +224,7 @@ class JdbcTest {
sqlParameterSourceFactory.setBeanFactory(mock());
return IntegrationFlow.from(Jdbc.inboundAdapter(h2DataSource, "select * from inbound")
.maxRows(2)
.rowMapper((RowMapper<Inbound>) (rs, rowNum) -> new Inbound(rs.getInt(1), rs.getInt(2)))
.rowMapper((rs, rowNum) -> new Inbound(rs.getInt(1), rs.getInt(2)))
.updateSql("update inbound set status = 10 where id in (:id)")
.updatePerRow(false)
.updateSqlParameterSourceFactory(sqlParameterSourceFactory)
@@ -237,14 +237,12 @@ class JdbcTest {
@Bean
public IntegrationFlow outboundFlow(DataSource h2DataSource) {
return flow -> flow
.handle(Jdbc.outboundAdapter(h2DataSource, "insert into outbound (id, status, name) values (1, 0, ?)")
.preparedStatementSetter((ps, requestMessage) -> {
ps.setObject(1, requestMessage.getPayload());
})
.handle(Jdbc.outboundAdapter(h2DataSource,
"insert into outbound (id, status, name) values (1, 0, ?)")
.preparedStatementSetter((ps, requestMessage) ->
ps.setObject(1, requestMessage.getPayload()))
.usePayloadAsParameterSource(false)
.sqlParameterSourceFactory(null)
.keysGenerated(false)
);
.keysGenerated(false));
}
@Bean
@@ -280,15 +278,11 @@ class JdbcTest {
.ignoreColumnMetaData(true)
.isFunction(false)
.storedProcedureName("GET_PRIME_NUMBERS")
.procedureParameters(List.of(
new ProcedureParameter("beginRange", 1, null),
new ProcedureParameter("endRange", 10, null)
))
.sqlParameters(List.of(
new SqlParameter("beginRange", Types.INTEGER),
new SqlParameter("endRange", Types.INTEGER)
))
.returningResultSetRowMappers(Map.of("out", new PrimeMapper()))
.procedureParameter(new ProcedureParameter("beginRange", 1, null))
.procedureParameter(new ProcedureParameter("endRange", 10, null))
.sqlParameter(new SqlParameter("beginRange", Types.INTEGER))
.sqlParameter(new SqlParameter("endRange", Types.INTEGER))
.returningResultSetRowMapper("out", new PrimeMapper())
),
e -> e.poller(p -> p.trigger(new OnlyOnceTrigger())))
.channel(c -> c.queue("storedProcInboundPollerChannel"))
@@ -296,19 +290,21 @@ class JdbcTest {
}
@Bean
public IntegrationFlow storedProcOutboundAdapter(DataSource derbyDataSource) {
return flow -> flow
.handle(Jdbc.storedProcOutboundAdapter(derbyDataSource)
.configurerStoredProcExecutor(configurer -> configurer
.storedProcedureName("CREATE_USER")
.sqlParameterSourceFactory(new BeanPropertySqlParameterSourceFactory())
.usePayloadAsParameterSource(true)
)
);
StoredProcExecutorSpec storedProcExecutor(DataSource derbyDataSource) {
return Jdbc.storedProcExecutorSpec(derbyDataSource)
.storedProcedureName("CREATE_USER")
.sqlParameterSourceFactory(new BeanPropertySqlParameterSourceFactory())
.usePayloadAsParameterSource(true);
}
@Bean
public IntegrationFlow storedProcOutboundGateway(DataSource derbyDataSource) throws Exception {
public IntegrationFlow storedProcOutboundAdapter(StoredProcExecutor storedProcExecutor) {
return flow -> flow
.handle(Jdbc.storedProcOutboundAdapter(storedProcExecutor));
}
@Bean
public IntegrationFlow storedProcOutboundGateway(DataSource derbyDataSource) {
return flow -> flow
.handle(Jdbc.storedProcOutboundGateway(derbyDataSource)
@@ -372,6 +368,11 @@ class JdbcTest {
public PlatformTransactionManager derbyTransactionManager() {
return new DataSourceTransactionManager(derbyDataSource());
}
}
record Inbound(int id, int status) {
}
}

View File

@@ -1,10 +1,31 @@
create table inbound(id int,status int);
insert into inbound values(1,2);
insert into inbound values(2,2);
create table inbound
(
id int,
status int
);
create table outbound(id varchar(100),status int,name varchar(20));
insert into inbound
values (1, 2);
create table outbound_gateway(id int,status int);
insert into outbound_gateway values(1,2);
insert into outbound_gateway values(2,2);
insert into inbound
values (2, 2);
create table outbound
(
id varchar(100),
status int,
name varchar(20)
);
create table outbound_gateway
(
id int,
status int
);
insert into outbound_gateway
values (1, 2);
insert into outbound_gateway
values (2, 2);

View File

@@ -184,6 +184,7 @@
** xref:jdbc/outbound-gateway.adoc[]
** xref:jdbc/message-store.adoc[]
** xref:jdbc/stored-procedures.adoc[]
** xref:jdbc/dsl.adoc[]
** xref:jdbc/lock-registry.adoc[]
** xref:jdbc/metadata-store.adoc[]
* xref:jpa.adoc[]

View File

@@ -0,0 +1,61 @@
[[jdbc-dsl]]
= Java DSL for JDBC Components
Version 7.0 introduced the Java DSL API for channel adapters in JDBC module.
The central Java DSL class (and usually starting point) is a `org.springframework.integration.jdbc.dsl.Jdbc` factory.
It provides self-explanatory method to initiate configuration for target channel adapter or gateway.
The standard `IntegrationComponentSpec` implementations for out-of-the-box channel adapters are:
* `JdbcInboundChannelAdapterSpec extends MessageSourceSpec<JdbcInboundChannelAdapterSpec, JdbcPollingChannelAdapter>`
* `JdbcOutboundChannelAdapterSpec extends MessageHandlerSpec<JdbcOutboundChannelAdapterSpec, JdbcMessageHandler>`
* `JdbcOutboundGatewaySpec extends MessageHandlerSpec<JdbcOutboundGatewaySpec, JdbcOutboundGateway>`
* `JdbcStoredProcInboundChannelAdapterSpec extends MessageSourceSpec<JdbcStoredProcInboundChannelAdapterSpec, StoredProcPollingChannelAdapter>`
* `JdbcStoredProcOutboundChannelAdapterSpec extends MessageHandlerSpec<JdbcStoredProcOutboundChannelAdapterSpec, StoredProcMessageHandler>`
* `JdbcStoredProcOutboundGatewaySpec extends MessageHandlerSpec<JdbcStoredProcOutboundGatewaySpec, StoredProcOutboundGateway>`
In addition, the `StoredProcExecutorSpec`, a convenient, builder-like component is provided for a `StoredProcExecutor` creation and configuration.
Here are some examples how `Jdbc` factory can be used for configuration an `IntegrationFlow`:
[source, java]
----
@Bean
public DataSource h2DataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScripts("classpath:dsl-h2.sql", "classpath:h2-stored-procedures.sql")
.build();
}
@Bean
public IntegrationFlow outboundFlow(DataSource h2DataSource) {
return flow -> flow
.handle(Jdbc.outboundAdapter(h2DataSource,
"insert into outbound (id, status, name) values (1, 0, ?)")
.preparedStatementSetter((ps, requestMessage) ->
ps.setObject(1, requestMessage.getPayload()))
.usePayloadAsParameterSource(false)
.keysGenerated(false));
}
@Bean
public IntegrationFlow storedProcInboundFlow(DataSource h2DataSource) {
return IntegrationFlow.from(Jdbc.storedProcInboundAdapter(h2DataSource)
.expectSingleResult(true)
.configurerStoredProcExecutor(configurer -> configurer
.ignoreColumnMetaData(true)
.isFunction(false)
.storedProcedureName("GET_PRIME_NUMBERS")
.procedureParameter(new ProcedureParameter("beginRange", 1, null))
.procedureParameter(new ProcedureParameter("endRange", 10, null))
.sqlParameter(new SqlParameter("beginRange", Types.INTEGER))
.sqlParameter(new SqlParameter("endRange", Types.INTEGER))
.returningResultSetRowMapper("out", new PrimeMapper())
),
e -> e.poller(p -> p.trigger(new OnlyOnceTrigger())))
.channel(c -> c.queue("storedProcInboundPollerChannel"))
.get();
}
----
This Java DSL API can be used as is with the xref:kotlin-dsl.adoc[Kotlin] and xref:groovy-dsl.adoc[Groovy] DSLs.

View File

@@ -17,3 +17,8 @@ Java 17 is still baseline, but Java 24 is supported.
[[x7.0-general]]
== General Changes
[[x7.0-new-components]]
== New Components
The JDBC module now provides a Java DSL API via its dedicated `org.springframework.integration.jdbc.dsl.Jdbc` factory.
The xref:jdbc/dsl.adoc[] chapter provides more details.