Honor Emission result in FluxMessageChannel
* Implement `Emission` handling in the `FluxMessageChannel` and `IntegrationReactiveUtils` * Upgrade to Spring Kafka `2.6.0` * Fix R2DBC components for deprecation in the Spring Data R2DBC * Implement `StatementMapper.SelectSpec` for query expression * Clean up for some sporadic test failures
This commit is contained in:
@@ -16,19 +16,18 @@
|
||||
|
||||
package org.springframework.integration.r2dbc.inbound;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
|
||||
import org.springframework.data.r2dbc.convert.EntityRowMapper;
|
||||
import org.springframework.data.r2dbc.core.R2dbcEntityOperations;
|
||||
import org.springframework.data.r2dbc.core.ReactiveDataAccessStrategy;
|
||||
import org.springframework.data.r2dbc.core.StatementMapper;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.TypeLocator;
|
||||
import org.springframework.expression.common.LiteralExpression;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardTypeLocator;
|
||||
import org.springframework.integration.endpoint.AbstractMessageSource;
|
||||
import org.springframework.integration.expression.ExpressionUtils;
|
||||
import org.springframework.r2dbc.core.ColumnMapRowMapper;
|
||||
@@ -40,6 +39,7 @@ import io.r2dbc.spi.Row;
|
||||
import io.r2dbc.spi.RowMetadata;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
|
||||
/**
|
||||
* An instance of {@link org.springframework.integration.core.MessageSource} which returns
|
||||
* a {@link org.springframework.messaging.Message} with a payload which is the result of
|
||||
@@ -59,9 +59,11 @@ import reactor.core.publisher.Mono;
|
||||
*/
|
||||
public class R2dbcMessageSource extends AbstractMessageSource<Publisher<?>> {
|
||||
|
||||
private final R2dbcEntityOperations r2dbcEntityOperations;
|
||||
|
||||
private final DatabaseClient databaseClient;
|
||||
|
||||
private final ReactiveDataAccessStrategy dataAccessStrategy;
|
||||
private final StatementMapper statementMapper;
|
||||
|
||||
private final Expression queryExpression;
|
||||
|
||||
@@ -97,20 +99,22 @@ public class R2dbcMessageSource extends AbstractMessageSource<Publisher<?>> {
|
||||
* It assumes that the {@link R2dbcEntityOperations} is fully initialized and ready to be used.
|
||||
* The 'queryExpression' will be evaluated on every call to the {@link #receive()} method.
|
||||
* @param r2dbcEntityOperations The reactive for performing database calls.
|
||||
* @param queryExpression The query expression.
|
||||
* @param queryExpression The query expression. The root object for evaluation context is a {@link StatementMapper}
|
||||
* for its {@link StatementMapper#createSelect} fluent API.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public R2dbcMessageSource(R2dbcEntityOperations r2dbcEntityOperations, Expression queryExpression) {
|
||||
Assert.notNull(r2dbcEntityOperations, "'r2dbcEntityOperations' must not be null");
|
||||
Assert.notNull(queryExpression, "'queryExpression' must not be null");
|
||||
this.r2dbcEntityOperations = r2dbcEntityOperations;
|
||||
this.databaseClient = r2dbcEntityOperations.getDatabaseClient();
|
||||
this.dataAccessStrategy = r2dbcEntityOperations.getDataAccessStrategy();
|
||||
this.statementMapper = r2dbcEntityOperations.getDataAccessStrategy().getStatementMapper();
|
||||
this.queryExpression = queryExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a way to set the type of the entityClass that will be passed to the
|
||||
* {@link org.springframework.data.r2dbc.core.DatabaseClient#execute(String)}
|
||||
* method.
|
||||
* {@link DatabaseClient#sql(String)} method.
|
||||
* @param payloadType The t class.
|
||||
*/
|
||||
public void setPayloadType(Class<?> payloadType) {
|
||||
@@ -120,8 +124,7 @@ public class R2dbcMessageSource extends AbstractMessageSource<Publisher<?>> {
|
||||
|
||||
/**
|
||||
* Provide a way to set update query that will be passed to the
|
||||
* {@link org.springframework.data.r2dbc.core.DatabaseClient#execute(String)}
|
||||
* method.
|
||||
* {@link DatabaseClient#sql(String)} method.
|
||||
* @param updateSql Update query string.
|
||||
*/
|
||||
public void setUpdateSql(String updateSql) {
|
||||
@@ -163,15 +166,8 @@ public class R2dbcMessageSource extends AbstractMessageSource<Publisher<?>> {
|
||||
@Override
|
||||
protected void onInit() {
|
||||
this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory());
|
||||
TypeLocator typeLocator = this.evaluationContext.getTypeLocator();
|
||||
if (typeLocator instanceof StandardTypeLocator) {
|
||||
/*
|
||||
* Register the R2dbc Query DSL package so they don't need a FQCN for QueryBuilder, for example.
|
||||
*/
|
||||
((StandardTypeLocator) typeLocator).registerImport("org.springframework.data.relational.core.query");
|
||||
}
|
||||
if (!Map.class.isAssignableFrom(this.payloadType)) {
|
||||
this.rowMapper = this.dataAccessStrategy.getRowMapper(this.payloadType);
|
||||
this.rowMapper = new EntityRowMapper<>(this.payloadType, this.r2dbcEntityOperations.getConverter());
|
||||
}
|
||||
this.initialized = true;
|
||||
}
|
||||
@@ -189,7 +185,8 @@ public class R2dbcMessageSource extends AbstractMessageSource<Publisher<?>> {
|
||||
protected Object doReceive() {
|
||||
Assert.isTrue(this.initialized, "This class is not yet initialized. Invoke its afterPropertiesSet() method");
|
||||
Mono<RowsFetchSpec<?>> queryMono =
|
||||
Mono.fromSupplier(() -> this.queryExpression.getValue(this.evaluationContext))
|
||||
Mono.fromSupplier(() ->
|
||||
this.queryExpression.getValue(this.evaluationContext, this.statementMapper))
|
||||
.map(this::prepareFetch);
|
||||
if (this.expectSingleResult) {
|
||||
return queryMono.flatMap(RowsFetchSpec::one)
|
||||
@@ -213,18 +210,20 @@ public class R2dbcMessageSource extends AbstractMessageSource<Publisher<?>> {
|
||||
}
|
||||
|
||||
private RowsFetchSpec<?> prepareFetch(Object queryObject) {
|
||||
String queryString = evaluateQueryObject(queryObject);
|
||||
return this.databaseClient
|
||||
.sql(queryString)
|
||||
Supplier<String> query = evaluateQueryObject(queryObject);
|
||||
return this.databaseClient.sql(query)
|
||||
.map(this.rowMapper);
|
||||
}
|
||||
|
||||
private String evaluateQueryObject(Object queryObject) {
|
||||
private Supplier<String> evaluateQueryObject(Object queryObject) {
|
||||
if (queryObject instanceof String) {
|
||||
return (String) queryObject;
|
||||
return () -> (String) queryObject;
|
||||
}
|
||||
else if (queryObject instanceof StatementMapper.SelectSpec) {
|
||||
return this.statementMapper.getMappedObject((StatementMapper.SelectSpec) queryObject);
|
||||
}
|
||||
throw new IllegalStateException("'queryExpression' must evaluate to String " +
|
||||
"or org.springframework.data.relational.core.query.Query, but not: " + queryObject);
|
||||
"or org.springframework.data.r2dbc.core.StatementMapper.SelectSpec, but not: " + queryObject);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@ public class R2dbcMessageHandler extends AbstractReactiveMessageHandler {
|
||||
* {@link R2dbcEntityOperations}
|
||||
* @param r2dbcEntityOperations The R2dbcEntityOperations implementation.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public R2dbcMessageHandler(R2dbcEntityOperations r2dbcEntityOperations) {
|
||||
Assert.notNull(r2dbcEntityOperations, "'r2dbcEntityOperations' must not be null");
|
||||
this.r2dbcEntityOperations = r2dbcEntityOperations;
|
||||
|
||||
Reference in New Issue
Block a user