24 Ocak 2019 Perşembe

Bean Validation API - JSR 303 + JSR 380

Giriş
JSR 303 ilk sürüm. JSR 380 tarafından geçersiz kılındı. JSR 380 yani Bean Validation 2.0 olarak ta bilinir

Maven
Örnek - Eski
Sadece Contraint'lerin yani anotasyonların bulunduğu jar için şöyle yaparız
<dependency>
  <groupId>javax.validation</groupId>
  <artifactId>validation-api</artifactId>
  <version>1.1.0.Final</version>
</dependency>
Ancak bu yetersiz, çünkü esasında bize bir gerçekleştirim (implementation) lazım. 

Örnek - Yeni Jakarta
Sadece Contraint'lerin yani anotasyonların bulunduğu jar için şöyle yaparız
<dependency>
  <groupId>jakarta.validation</groupId>
  <artifactId>jakarta.validation-api</artifactId>
  <version>3.0.0</version>
</dependency>
Ancak bu yetersiz, çünkü esasında bize bir gerçekleştirim (implementation) lazım. 

Hibernate
Açıklaması şöyle.
You can use oracle Validation API JSR-303, it is independent framework which can be use in web-based and none web-based applications, Hibernate provides implementation for that JSR-303. you can include the dependencies as follow in you pom.xml file
Hibernate kullanmak için şöyle yaparız
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-validator</artifactId>
  <version>5.2.1.Final</version>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-validator-annotation-processor</artifactId>
  <version>5.2.1.Final</version>
</dependency>
Expression Language kullanmak için şöyle yaparız
<dependency>
   <groupId>javax.el</groupId>
   <artifactId>el-api</artifactId>
   <version>2.2</version>
</dependency>
Açıklaması şöyle
Expression Language is required in order to use the interpolation in the validation messages
Glassfish
Java SE ortamında şöyle yaparız
<dependency>
   <groupId>org.glassfish</groupId>
   <artifactId>javax.el</artifactId>
</dependency>
Anotasyon Listesi
Liste şöyle. Standarttaki bu anotasyonlar dışında kütüphaneler kendi anotasyonlarını da sağlıyorlar.
@AssertFalse
@AssertTrue
@DecimalMax(value=, inclusive=)
@DecimalMin(value=, inclusive=)
@Digits(integer=, fraction=)
@Email
@Future
@FutureOrPresent
@Max(value=)
@Min(value=)
@NotBlank
@NotEmpty
@NotNull
@Negative
@NegativeOrZero
@Null
@Past
@PastOrPresent
@Pattern(regex=, flags=)
@Positive
@PositiveOrZero
@Size(min=, max=)
Açıklaması şöyle
@Positive : Requires the value applicable to numeric values to be positive.

@PositiveOrZero : Requires the value applicable to numeric values to be positive or zero.

@Negative : Requires negative value applicable to numeric values.

@NegativeOrZero : Requires the value applicable to numeric values to be negative or zero.

@Past : Requires the value applicable to date fields to be a past date. It can also be applied to Date types coming in Java 8.

@PastOrPresent : Requires the value applicable to date fields to be a past date or present. It can also be applied to Date types coming in Java 8.

@Future : Requires the value applicable to date fields to be a future date. It can also be applied to Date types coming in Java 8.

@FutureOrPresent : Requires the value applicable to date fields to be a future date or now. It can also be applied to Date types coming in Java 8.
Bu anotasyonları kullanınca kod biraz kirleniyor ancak bence o kadar kötü değil. Açıklaması şöyle
I use JSR-303 validation because it keeps the code of my controllers cleaner. The downside is that I have to rely on “annotation magic” but I can live with it.
Kullanım
Normalde nesnenin kullanıldığı yeri @Valid anotasyonu ile işaretleriz. Mesela elimizde şöyle bir kod olsun
public class User {

  @NotBlank(message = "Name is mandatory")
  private String name;

  @NotBlank(message = "Email is mandatory")
  private String email;
  ...
}
SpringBoot ile şöyle yaparız
@RestController
public class UserController {
  @PostMapping("/users")
  ResponseEntity<String> addUser(@Valid @RequestBody User user) {
    ...
  }
}
Eğer hata varsa şu metod çağrılır. org.springframework.web.bind.MethodArgumentNotValidException sınıfı hataları içerir.
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public Map<String, String> handleValidationExceptions(MethodArgumentNotValidException ex) {

  Map<String, String> errors = new HashMap<>();
  ex.getBindingResult().getAllErrors().forEach((error) -> {
    String fieldName = ((FieldError) error).getField();
    String errorMessage = error.getDefaultMessage();
    errors.put(fieldName, errorMessage);
  });
  return errors;
}
Ancak eğer kullandığımız altyapı @Valid anotasyonunu otomatik işlemiyorsa, kodla yapmak gerekir.
1. Validation nesnesi aracılığıyla bir ValidatorFactory elde edilir.
2. ValidatorFactory aracılığıyla bir Validator elde edilir.
3. Validator belirtilen nesneyi doğrulayan bir bir sonuç döner.
Örnek
Şöyle yaparız
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<Foo>> violations = validator.validate(foo);
    
for (ConstraintViolation<Foo> violation : violations) {
  System.out.println(violation.getMessage());
}

Hiç yorum yok:

Yorum Gönder