簡體   English   中英

spring-integration jdbc 用於處理空結果集的出站網關建議

[英]spring-integration jdbc outbound-gateway advice for handling empty result-sets

我正在接受@gary-russel 的建議並提出一個新問題 w.r.t 這個老問題( 使用 jdbc 時出現問題:當查詢返回空結果集時出站網關)關於 spring-integration JDBC outbound-gateway calls on requests that return一個空的結果集。

我嘗試使用處理程序建議來獲取返回空數組的請求,而不是拋出異常。

你能告訴我為什么這個建議不對嗎?

<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是因為AdviceChain運行后JdbcOutboundGateway拋出null結果失敗異常。

這個JdbcOutboundGateway問題最令人驚訝的部分是方法handleRequestMessage()確實從 JDBC 調用接收到一個空列表,這看起來完全有效,但它隨后繼續明確地將其設置為null

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

我想你的意思是按原樣返回一個空列表,而不是null ,因為它默認存在於JdbcOutboundGateway中。

null是 AOP 通知中Joinpoint執行的有效結果。 ExpressionEvaluatingRequestHandlerAdvice中的邏輯是這樣的:

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

由於null可以返回,所以只需將 go 傳遞給evaluateSuccessExpression()即可,根本不需要它的結果。 所以,最后我們只返回null

這個 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以忽略查詢執行中的空列表。 我們可能會修改我們的“空列表”邏輯,但現在它直接轉換為nullhttps://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;
    }
}

現在可以像這樣設置建議鏈:

    <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>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM