spring集成jdbc出站网关关于处理空结果集的建议



我接受了@gary russel的建议,并打开了一个新的问题。关于spring集成的旧问题(当查询返回空结果集时使用jdbc:出站网关的问题(jdbc出站网关调用返回空结果集中的请求。

我尝试使用处理程序建议来获得返回空数组的请求,而不是抛出异常。

你能告诉我为什么这个建议不对吗?

<beans:beans xmlns:xsi      = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans    = "http://www.springframework.org/schema/beans"
xmlns:jdbc     = "http://www.springframework.org/schema/jdbc"
xmlns:int      = "http://www.springframework.org/schema/integration"
xmlns:int-jdbc = "http://www.springframework.org/schema/integration/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans            https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jdbc             https://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/integration      https://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/jdbc https://www.springframework.org/schema/integration/jdbc/spring-integration-jdbc.xsd">
<int:gateway id="getAllCustomers-Gateway"
default-request-channel="getAllCustomers"
service-interface="demo.StringInputJsonOutputGatewayMethod" />
<int:channel id="getAllCustomers" />
<int-jdbc:outbound-gateway id="getAllCustomers-OutboundGateway"
request-channel="getAllCustomers"
query="select * from Customer"
data-source="dataSource"
max-rows="0" >
<int-jdbc:request-handler-advice-chain>
<beans:bean class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice" >
<beans:property name="onSuccessExpressionString"     value="payload ?: {} " />
<beans:property name="returnFailureExpressionResult" value="#{true}"        />
<beans:property name="onFailureExpressionString"     value="{}"             />
</beans:bean>
</int-jdbc:request-handler-advice-chain>
</int-jdbc:outbound-gateway>
<beans:bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource" >
<beans:property name="driverClass" value="org.h2.Driver" />
<beans:property name="url"         value="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE" />
<beans:property name="username"    value="sa" />
<beans:property name="password"    value=""   />
</beans:bean>
<jdbc:initialize-database data-source="dataSource" >
<jdbc:script location="classpath:/schema.sql" />
</jdbc:initialize-database>
</beans:beans>

使用此脚本初始化测试数据库(schema.sql:

CREATE TABLE Customer (
ID         BIGINT      NOT NULL AUTO_INCREMENT,
FIRST_NAME VARCHAR(30) NOT NULL,
LAST_NAME  VARCHAR(30) NOT NULL,
PRIMARY KEY (ID)
);

出站网关正在引发异常:

org.springframework.integration.handler.ReplyRequiredException: No reply produced by handler 'getAllCustomers-OutboundGateway', and its 'requiresReply' property is set to true.

任何建议或建议都将不胜感激。

一些调试跟进:

我可以看到,调用ExpressionEvaluatingRequestHandlerAdvice是为了评估successExpression,但这不会改变返回结果,即使提供了成功表达式,类似于payload ?: {}。不咨询failureExpression,因为来自JdbcOutboundGatewaynull结果失败异常是在运行AdviceChain后引发的。

这个JdbcOutboundGateway问题最令人惊讶的部分是,方法handleRequestMessage()确实从JDBC调用中接收到了一个空列表,这似乎完全有效,但它随后将其显式设置为null

if (this.poller != null) {
...
list = this.poller.doPoll(sqlQueryParameterSource);
}
Object payload = list;
if (list.isEmpty()) {
return null;
}

我想您的目的是按原样返回一个空列表,而不是像默认情况下JdbcOutboundGateway中那样返回null

CCD_ 13是来自AOP建议中的CCD_ 14执行的结果。ExpressionEvaluatingRequestHandlerAdvice的逻辑是这样的:

try {
Object result = callback.execute();
if (this.onSuccessExpression != null) {
evaluateSuccessExpression(message);
}
return result;
}

由于null是OK返回,所以您只需转到evaluateSuccessExpression(),而不必期待它的结果。所以,最后我们只返回null

AbstractReplyProducingMessageHandler:中查阅该空值

if (result != null) {
sendOutputs(result, message);
}
else if (this.requiresReply && !isAsync()) {
throw new ReplyRequiredException(message, "No reply produced by handler '" +
getComponentName() + "', and its 'requiresReply' property is set to true.");
}

您可能真的考虑将requiresReply设置为false,以忽略查询执行中的空列表。我们可以修改我们的";空列表";逻辑,但目前它直接转换为null:https://jira.spring.io/browse/INT-3333.

您可以考虑实现一个自定义的AbstractRequestHandlerAdvice,并检查callback.execute()结果,然后返回一个空列表。

上面提到的ExpressionEvaluatingRequestHandlerAdvice也是可能的,但它有点涉及onSuccessExpression抛出的其他选项和异常。

感谢@artem bilan的建议。这似乎最终起到了作用。

ExpressionEvaluatingRequestHandlerAdvice:添加自定义建议处理程序扩展

package demo;
import org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice;
import org.springframework.messaging.Message;
import java.util.ArrayList;
import java.util.List;
import static java.util.Collections.unmodifiableList;
public class ReplaceNullWithEmptyListHandlerAdvice extends ExpressionEvaluatingRequestHandlerAdvice {
private static final List<Object> EMPTY_LIST = unmodifiableList(new ArrayList<>());
@Override
protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) {
final Object result = super.doInvoke(callback, target, message);
return result != null ? result : EMPTY_LIST;
}
}

现在可以这样设置advicechain:

<int-jdbc:outbound-gateway id="getAllCustomers-OutboundGateway"
request-channel="getAllCustomers"
query="select * from Customer"
data-source="dataSource"
max-rows="0" >
<int-jdbc:request-handler-advice-chain>
<beans:bean class="demo.ReplaceNullWithEmptyListHandlerAdvice" />
</int-jdbc:request-handler-advice-chain>
</int-jdbc:outbound-gateway>

最新更新