2017-02-23 106 views
0

У меня есть служба dropwizard, которая принимает PUT документа JSON, представляющего компонент. Я использую ограничения аннотаций в реализации компоненты и использовать @Valid аннотаций в моем методе ресурсов:Dropwizard и проверка списков объектов

@PUT 
public Response write(@Valid MyBean bean); 

и все работает довольно хорошо.

Теперь, однако, я хочу передать массив объектов в JSON. Я просто изменил метод подписи

@PUT 
public Response write(@Valid List<MyBean> beans); 

и она обычно работает, но если есть ошибки проверки, то ответ не очень дружественным к пользователю. Например, если я отправляю в 100 бобов в массиве, и один из них отсутствует свойство «имя», то ответ

{"errors":["name may not be empty"]} 

без указания который боб в запросе есть проблема.

Есть ли способ преодолеть это?

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

ответ

0

Как вы хотите, это может быть невозможно. Вот автономный тест того, что происходит и как Hibernate пустошь, как для вас, чтобы вклиниться в него:

public class ListBeanValidationTest { 

    public static void main(String[] args) { 
     List<Bean> asList = Arrays.asList(new Bean("test"), new Bean("test2")); 

     Validator v = Validators.newConfiguration().messageInterpolator(new MsgInterpolator()).buildValidatorFactory().getValidator(); 

     // this is what DW does but i am lazy so you get the main version 
     if(asList instanceof Iterable) { 
      Iterable values = (Iterable) asList; 
      Set<ConstraintViolation<Object>> violations = new HashSet<>(); 
      for(Object value : values) { 
       violations.addAll(v.validate(value)); 
      } 

      violations.forEach(System.out::println); 
     } 
    } 

    public static class Bean { 

     Bean(String name) { 
      this.name = name; 
     } 

     String name; 

     @NotEmpty(message="bean not empty ${name}") 
     String wrong; 
    } 

    public static class MsgInterpolator implements MessageInterpolator { 

     @Override 
     public String interpolate(String messageTemplate, Context context) { 
      return interpolate(messageTemplate, context, Locale.getDefault()); 
     } 

     @Override 
     public String interpolate(String messageTemplate, Context context, Locale locale) { 
      Object validatedValue = context.getValidatedValue(); 


      return null; 
     } 

    } 
} 

MessageInterpolator является вопрос здесь. У него нет экземпляра компонента во время интерполяции сообщения для вас, поэтому, к сожалению, вы не можете использовать ссылку на него. Это означает, что вам придется делать это по-другому.

Вы можете получить ссылку на ваш validator (как вы это делаете, вы можете найти его в среде DW. Я использую DI через Guice).

Если вы хотите сделать это способом DW, вы можете изучить расширение: JacksonMessageBodyProvider - это класс, который выполняет валидацию ресурсов DW.

Я надеюсь, что помогает

Вы также можете прочитать о настройках проверки, которые доступны для вас здесь: https://docs.jboss.org/hibernate/validator/5.1/reference/en-US/html/chapter-message-interpolation.html#section-custom-message-interpolation

- Артуру

+0

Спасибо - я просто в конечном итоге делает это сам (не знаю, почему я думал, что инъекция валидатора будет сложной) –

+0

Интересно, будет ли это хорошим дополнением. хотя опять же, если ваше сообщение проверки зависит от другого свойства одного и того же компонента, как вы его проверяете? Вы получите проверку зависимостей до того места, где весь ваш bean-элемент является нулевым, в этот момент интерполятор сообщений будет NPE при проверке, который не будет действительно хорош. Я могу представить, что это была их мотивация, не делая этого. Кроме того: проверка Hibernate не поддерживает списки или массивы по умолчанию, поэтому это, возможно, никогда не было проблемой. DW взламывает это сами по себе :) – pandaadb