2016-10-25 10 views
2

У меня возникла ситуация, когда перед обработкой входного файла я хочу проверить, установлена ​​ли в базе данных определенная информация. В данном конкретном случае это имя клиента и параметры, используемые для обработки. Если эта информация не настроена, импорт файла невозможен.Как вы обрабатываете EmptyResultDataAccessException с интеграцией Spring?

На многих страницах StackOverflow пользователи разрешают обработку исключений EmptyResultDataAccessException, сгенерированных queryForObject, не возвращая строк, перехватывая их в Java-коде.

Проблема заключается в том, что 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 ожидает ряд должен быть возвращен и будет если в противном случае было исключено исключение , поэтому вам нужно h и за исключением или используйте другой запрос, который возвращает строку.
  2. Spring Integration контролирует исключения и захватывает их до мой собственный код может передать их.

То, что я хочу быть в состоянии сделать:

  • Выгоду очень специфическое состояние и зарегистрировать ее или позволить конечному пользователю знать, что им нужно сделать, чтобы решить эту проблему.

правка 10/26/2016 по рекомендации от @Artem:

Изменено мой существующий входной канал весной при условии Handler совет:

@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(); 
} 

У меня изначально возникли проблемы с подключением этой функции, но в конце я понял, что он создает еще другой канал, который необходимо будет контролировать для ошибок и обрабатывать соответствующим образом. Для простоты я решил не использовать другой канал в это время.

ответ

1

Spring Integration Service Activator может поставляться с ExpressionEvaluatingRequestHandlerAdvice, который работает как try...catch и позволяют выполнить некоторую логику onFailureExpression: http://docs.spring.io/spring-integration/reference/html/messaging-endpoints-chapter.html#expression-advice

Ваша проблема может быть, что вы catch (EmptyResultDataAccessException e), но это cause, а не корень по вызову this.namedParameterJdbcTemplate.queryForObject().

+0

Обновленные исходные вопросы с стеком ошибок, чтобы исключения можно было пересмотреть в ответ на последний абзац выше. –

+0

ОК. Отзыв. И в чем вопрос? Вот как это работает. «ClientDaoJDBC» выбрасывает «EmptyResultDataAccessException». Он завернут в «MessageHandlingException», а затем в «MessageTransformationException», поскольку вы используете 'MemberFileMessageToJobRequest.messageToRequest()' как функцию 'transformer'. –

+0

Я имел в виду комментарий @Artem Bilan о проблеме между причиной, а не причиной. Я просто хотел убедиться, что он задокументирован. Я попытался поймать все 3 исключения, но Spring Integration по-прежнему получает исключение. –

2

Хотя потенциально это не лучшее решение, я переключился на проверку количества строк вместо того, чтобы возвращать фактические данные. В этой ситуации исключение данных исключается.

Основной код выше переехал:

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 которые могут быть полезны в более поздний момент времени.

+1

В основном я чувствую, что на этот вопрос есть несколько ответов в зависимости от потребностей вашей организации.Spring Integration предоставляет методы для обработки ошибок и хорошо согласуется с документированными шаблонами проектирования. Чтобы этот проект был доказательством концепции, я пошел с вышеупомянутым подходом и изменил запрос. Поступая таким образом, я точно знаю, когда произошла ошибка, и может ответить соответствующим образом. Решение Артема также справедливо ниже. –

Смежные вопросы