簡體   English   中英

Spring Integration如何處理EmptyResultDataAccessException?

[英]How do you handle EmptyResultDataAccessException with Spring Integration?

我有一種情況,在處理輸入文件之前,我想檢查數據庫中是否設置了某些信息。 在這種特殊情況下,它是用於處理的客戶名稱和參數。 如果未設置此信息,則文件導入將失敗。

在許多StackOverflow頁面中,用戶通過在Java代碼中捕獲行,從而解決了對queryForObject生成的EmptyResultDataAccessException異常的處理,該異常不返回任何行。

問題是Spring Integration在我的代碼捕獲到異常之前就已經很好地捕獲了異常,從理論上講,我無法從任何數量的EmptyResultDataAccessException異常中分辨出該錯誤,該異常可能與代碼中的其他查詢一起拋出。

示例代碼段顯示try ... catch與queryForObject:

    MapSqlParameterSource mapParameters = new MapSqlParameterSource();

    // Step 1 check if client exists at all
    mapParameters.addValue("clientname", clientName);
    try {
        clientID = this.namedParameterJdbcTemplate.queryForObject(FIND_BY_NAME, mapParameters, Long.class);
    } catch (EmptyResultDataAccessException e) {
        SQLException sqle = (SQLException) e.getCause();
        logger.debug("No client was found");
        logger.debug(sqle.getMessage());
        return null;
    }

    return clientID;

在上面的代碼中,沒有返回任何行,我想正確處理它(我尚未對該部分進行編碼)。 取而代之的是,從不觸發catch塊,而是觸發了我的通用錯誤處理程序和關聯的錯誤通道。

文件BatchIntegrationConfig.java中的片段:

    @Bean
    @ServiceActivator(inputChannel="errorChannel")
    public DefaultErrorHandlingServiceActivator errorLauncher(JobLauncher jobLauncher){
        logger.debug("====> Default Error Handler <====");
        return new DefaultErrorHandlingServiceActivator();
    }

文件DefaultErrorHandlingServiceActivator.java中的片段:

public class DefaultErrorHandlingServiceActivator {
    @ServiceActivator 
    public void handleThrowable(Message<Throwable> errorMessage) throws Throwable {
        // error handling code should go here
    }
}

經過測試的事實:

  1. queryForObject期望返回一行,否則將引發異常,因此您必須處理該異常或使用其他查詢來返回一行。
  2. Spring Integration正在監視異常並在我自己的代碼可以處理它們之前捕獲它們。

我想要做的是:

  • 捕獲非常具體的情況並記錄下來,或者讓最終用戶知道他們需要采取什么措施來解決問題。

根據@Artem的推薦於2016年10月26日編輯:

將我現有的輸入通道更改為Spring提供的處理程序建議:

@Transformer(inputChannel = "memberInputChannel", outputChannel = "commonJobGateway", adviceChain="handleAdvice")  

為建議添加了支持Bean和方法:

    @Bean
ExpressionEvaluatingRequestHandlerAdvice handleAdvice() {
    ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice();
    advice.setOnFailureExpression("payload");
    advice.setFailureChannel(customErrorChannel());
    advice.setReturnFailureExpressionResult(true);
    advice.setTrapException(true);
    return advice;
}

private QueueChannel customErrorChannel() {
    return new DirectChannel();
}

起初,我在連接此功能時遇到了一些問題,但是最后,我意識到它正在創建另一個通道,需要對其進行監視以檢查錯誤並進行適當的處​​理。 為簡單起見,我選擇了此時不使用其他渠道。

盡管可能不是最佳解決方案,但我改用檢查行數而不是返回實際數據。 在這種情況下,可以避免數據異常。

上面的主要代碼移至:

    MapSqlParameterSource mapParameters = new MapSqlParameterSource();
    mapParameters.addValue("clientname", clientName);

    // Step 1 check if client exists at all; if exists, continue
    // Step 2 check if client enrollment rules are available
    if (this.namedParameterJdbcTemplate.queryForObject(COUNT_BY_NAME, mapParameters, Integer.class) == 1) {
        if (this.namedParameterJdbcTemplate.queryForObject(CHECK_RULES_BY_NAME, mapParameters, Integer.class) != 1) return null;
    } else return null;

    return findClientByName(clientName);

然后,我在返回Spring Batch的調用方法時檢查數據:

        if (clientID != null) {
        logger.info("Found client ID ====> " + clientID);
    }
    else {
        throw new ClientSetupJobExecutionException("Client " + 
                fileNameParts[1] + " does not exist or is improperly setup in the database.");
    }

盡管不是必需的,但我創建了一個自定義Java Exception,它在以后的某個時間可能會很有用。

Spring Integration Service Activator可以與ExpressionEvaluatingRequestHandlerAdvice一起提供,它像try...catch並允許您對onFailureExpression執行一些邏輯: http : //docs.spring.io/spring-integration/reference/html/messaging-endpoints -chapter.html#表達,意見

您的問題可能是您catch (EmptyResultDataAccessException e) ,但這是一個cause ,而不是this.namedParameterJdbcTemplate.queryForObject()調用的根本cause

暫無
暫無

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

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