休止状態のメソッド検証が常に機能するとは限りません

Aug 23 2020

Spring-boot-starter-webを使用してSpringBootアプリ(SpringBootの最新バージョン)のmain()でHibernateの検証(ConstraintViolationException)スローされないのはなぜですか?

@Validated
@SpringBootApplication
public class Application {
public static void main(String[] args) {
   SpringApplication.run(Application.class, args);
   someService.doStuff(new Item(null);  // WHY NOT THROWN????????!!!!!! 
   // Expecting ConstraintViolationException: doStuff.item.content: must not be null
}}
// ----------------------

public class Item {
    @NotNull
    String content;  // to be validated
   //constructor, getter, setter
}

@Validated
@Service
public class SomeService {
    void doStuff(@Valid Item item) {} // should break for Item's content = null
}

不思議なことに、他の場合では、Hibernate検証は同じメソッド呼び出しで期待どおりに機能しています。

  1. コントローラーのコンストラクターに無効な呼び出しを入れると、ConstraintViolationExceptionがスローされます。
public SomeController(SomeService someService){
    this.someService = someService;
    someService.doStuff(new Item(null); // throws ConstraintViolationException  
}
  1. また、予想どおり、無効な呼び出しin a constructor methodを行ってエンドポイントをテストまたはPostmanで呼び出すと、ConstraintViolationExceptionがスローされます。
@GetMapping("item")
public String item() {
    someService.doStuff(new Item(null); // throws ConstraintViolationException
    return "You never get here.";
}

回答

2 doctore Aug 23 2020 at 17:54

someServiceインスタンスをどのように取得しているかはわかりませんApplicationが、次のコードは私にとっては機能します(異なるファイル内のすべてのクラス):

@AllArgsConstructor
@Getter
@Setter
public class Item {

  @NotNull
  String content;
}



@Validated
@Service
public class SomeService {

  public void doStuff(@Valid Item item) {
    System.out.println(format("Item.content = %s", item.getContent()));
  }
}



@SpringBootApplication
public class TestingPurposeApplication {

  public static void main(String[] args) {
    ConfigurableApplicationContext context = SpringApplication.run(TestingPurposeApplication.class, args);
    SomeService someService = context.getBean(SomeService.class);
    someService.doStuff(new Item(null));
  }
}

結果:

使用する:

ConfigurableApplicationContext context = SpringApplication.run(MyApplication.class, args);
MyClass myInstance = context.getBean(MyClass.class);

Springによって管理されるコンポーネントをmainメソッドで取得するための適切な方法です。