Интеграция Spring и возврат ошибок проверки схемы

Мы используем Spring Integration для обработки полезной нагрузки JSON, переданной в конечную точку RESTful. В рамках этого потока мы используем фильтр для проверки JSON:

.filter(schemaValidationFilter, s -> s
    .discardFlow(f -> f
        .handle(message -> {
            throw new SchemaValidationException(message);
        }))
)

Это прекрасно работает. Однако, если проверка не пройдена, мы хотим зафиксировать ошибку синтаксического анализа и вернуть ее пользователю, чтобы он мог отреагировать на ошибку. Вот переопределенный метод accept в классе SchemaValidationFilter:

@Override
public boolean accept(Message<?> message) {
  Assert.notNull(message);
  Assert.isTrue(message.getHeaders().containsKey(TYPE_NAME));

  String historyType = (String)message.getHeaders().get(TYPE_NAME);
  JSONObject payload = (JSONObject) message.getPayload();
  String jsonString = payload.toJSONString();

  try {
      ProcessingReport report = schemaValidator.validate(historyType, payload);
      return report.isSuccess();
  } catch (IOException | ProcessingException e) {
      throw new MessagingException(message, e);
  }

}

Что мы сделали, так это то, что в блоке catch мы генерируем исключение MessageException, которое, кажется, решает проблему. Однако это, кажется, нарушает то, что должен делать фильтр (просто возвращает true или false).

Есть ли наилучшая практика для передачи сведений об ошибке от фильтра к клиенту? Является ли фильтр правильным решением для этого варианта использования?

Спасибо за вашу помощь! Джон


person flipflop    schedule 10.06.2015    source источник


Ответы (2)


Я бы сказал, что вы идете правильным путем. Пожалуйста, обратитесь к XmlValidatingMessageSelector, поэтому ваш JsonValidatingMessageSelector должен быть похожим и иметь такой же дизайн.

Поскольку у нас есть опция throwExceptionOnRejection, мы всегда можем быть уверены, что выбрасывание Exception вместо просто true/false является правильным поведением.

То, что говорит Гэри, тоже хорошо, но по существующей логике в том имплементе MessageSelector мы можем продолжить то же самое и продолжать использовать .filter(), но, конечно, уже без .discardFlow(), потому что мы не будем посылать неверное сообщение на сервер. discardChannel.

Когда ваш JsonValidatingMessageSelector будет готов, не стесняйтесь добавить его обратно в Framework!

person Artem Bilan    schedule 10.06.2015
comment
Создание JsonValidatingMessageSelector звучит как правильный подход, тем более что XmlValidatingMessageSelector можно использовать в качестве шаблона. Поскольку мы занимаемся консалтингом, нам нужно будет связаться с компанией, в которой мы работаем, чтобы узнать, можем ли мы внести свой вклад в структуру. Я спрошу! Спасибо за вашу помощь! - person flipflop; 11.06.2015

Вероятно, правильнее делать валидацию в <service-activator/>...

public Message<?> validate(Message<?> message) {

    ...

    try {
        ProcessingReport report = schemaValidator.validate(historyType, payload);
        return message;
    } 
    catch (IOException | ProcessingException e) {
        throw new MessagingException(message, e);
    }
}

...так как вы никогда не фильтруете.

person Gary Russell    schedule 10.06.2015
comment
Вы правы, мы не фильтруем. Вместо повторной генерации исключения в блоке catch мы бы вернули false. Поскольку XmlValidatingMessageSelector кажется шаблоном, мы будем использовать его для наших нужд. Спасибо за помощь! - person flipflop; 11.06.2015