Spring Boot

Spring Boot Bean Validation Uygulama Örneği

Spring Boot Dersleri‘ne devam ediyorum.

Bu yazıda Spring Boot Uygulamasında Java Bean Validation’un nasıl kullanıldığına ve bu validasyon sonucunda kullancıya gerekli uyarı mesajlarının nasılverildiriğine bakacağız.

Java Bean Validator’un ne olduğuna aşağıdaki yazıdan bakabilirsiniz.

İlgini Çekebilir: Java Bean Validation Annotation Nedir?

Bir öğrenci bilgilerini kaydeden bir rest apimiz olacak ve öğrenci entitymizdeki alanlarımızın belirli bir validasyon kuralları koyacağız ve buradan çıkacak olan hata mesajlarını kullanıcıya göstereceğiz.

Uygulama


Uygulamamızdaki bağımlıklar şunlar olacaktır.

  • Spring Boot Starter Validation
  • Spring Boot Starter Web
  • H2
  • Lombok
  • Spring Data JPA

Projemizde validasyon işlemlerini Starter Boot Starer Validation sağlayacaktır.

Maven projemizin bağımlılıkları;

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

Student modelimizi oluşturalım.

@Data
@Entity
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NotNull
    @Size(min = 2, message = "Must be not null")
    private String nameSurname;

    @Max(value = 99999)
    @Positive
    private int studentNumber;

    @NotBlank(message = "Must be not blank")
    private String schoolName;

    @Email(message = "Email should be valid")
    private String email;

    @Min(value = 18, message = "Cannot be younger than 18 years old.")
    private int age;

    @Pattern(regexp = "[0-9\\s]{12}")
    private String phone;
}

Entitymizi oluştururken kullandığımız validasyonlara dikkat edelim ve bu validasyonların isteğe göre message parametresine değer verebilmekteyiz.

  • Email
  • Pattern
  • Min
  • NotBlank
  • NotNull
  • Size

Şimdi repositorymizi oluşturalım.

public interface   StudentRepository extends JpaRepository<Student,Long> {
}

Servis katmanımızı oluşturalım H2 veritabanımıza kayıt edeceğimiz metotlarımızı yazalım. Bunun için ise StudentRepository kullanacağız.

@Service
public class StudentService {

    @Autowired
    StudentRepository studentRepository;

    public void save(Student student){
        studentRepository.save(student);
    }
}

Controllerimizi oluşturalım, controllerimizde rest api üzerinden erişim sağlanacak bir endpointimiz olacaktır.

@RestController
public class StudentController {

    @Autowired
    StudentService studentService;

    @PostMapping("/save")
    ResponseEntity<String> addStudent(@Valid @RequestBody Student student) {
        studentService.save(student);
        return ResponseEntity.ok("Student Saved");
    }

}

Controller’ımızın addStudent metodunda @Valid anotasyonu olduğuna dikkat edin. @Valid anotasyonu ekleyerek apimize gelen alanlara belirlediğimiz kriterlerin doğruluğu kontrol edilmektedir. Bu anotasyon ile birlikte iş alanlarımızda belirlediğimiz alanların istediğimiz kritere ve doğruluğa olduğu takdirde metotumuza girer aksi takdirde servsimiz hata verir.

İstek atalım.

Spring Bean Validation
Spring Bean Validation

Postman üzerinden gelen isteğe bakalım.

Spring Bean Validation
Spring Bean Validation

Api’yi kullanan kişiye sadece bu mesaj gitmektedir. Bizim yazmış olduğumuz mesajlar gitmiyor, ancak yazılımımızın konsol çıktısına baktığımızda hata mesajları gözükmektedir.

Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in org.springframework.http.ResponseEntity<java.lang.String> com.burakkutbay.springbootbeanvalidation.controller.StudentController.addStudent(com.burakkutbay.springbootbeanvalidation.model.Student) with 4 errors: [Field error in object 'student' on field 'schoolName': rejected value [null]; codes [NotBlank.student.schoolName,NotBlank.schoolName,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [student.schoolName,schoolName]; arguments []; default message [schoolName]]; default message [Must be not blank]] [Field error in object 'student' on field 'age': rejected value [0]; codes [Min.student.age,Min.age,Min.int,Min]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [student.age,age]; arguments []; default message [age],18]; default message [Cannot be younger than 18 years old.]] [Field error in object 'student' on field 'studentNumber': rejected value [0]; codes [Positive.student.studentNumber,Positive.studentNumber,Positive.int,Positive]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [student.studentNumber,studentNumber]; arguments []; default message [studentNumber]]; default message [must be greater than 0]] [Field error in object 'student' on field 'nameSurname': rejected value [null]; codes [NotNull.student.nameSurname,NotNull.nameSurname,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [student.nameSurname,nameSurname]; arguments []; default message [nameSurname]]; default message [must not be null]] ]
....
...
..

Şeklinde uzayıp giden ve bizim valid mesajlarımızı içeren hata mesajlarınızı yazılım konsolunda görmekteyiz.

Peki neden api kullanıcımız bu mesajlarımızı göremiyor?

Yazılımlarımızda oluşan bu hataları handle ederek yakalacağız.

@ControllerAdvice Kullanımı

Controller Advice anotasyonu başlı başına ayrı bir konu olsa da kısaca bahsedelim. Spring uygulamalarımızın içerisinde oluşabilecek tüm hataları yakalamamıza olanak sağlayan bir anotasyondur. Bu anotasyon sayesinde uygulamalarımızda oluşan hataları handle ederek response’unu kontrol edebiliriz.

Bean validasyon uygulamamızın içerisinde oluşan hataların kullanıcıya gösterilmesi evresinde @ControllerAdvice‘dan yararlanarak oluşan tüm hataların ResponseEntity olarak response’da cevap olarak verilmesini sağlamaktayız.

@ControllerAdvice
public class ValidationHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
                             HttpHeaders headers, HttpStatus status, WebRequest request) {

        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getAllErrors().forEach((error) ->{
            String fieldName = ((FieldError) error).getField();
            String message = error.getDefaultMessage();
            errors.put(fieldName, message);
        });
        return new ResponseEntity<Object>(errors, HttpStatus.BAD_REQUEST);
    }
}

Yukarıdaki kod bloğunda ise ResponseEntity’lerinden oluşabilecek tüm hataların yakalanıp hata mesajlarının cevap olarak geri döndürülmesini sağlıyoruz. Bu sayede ise bizim entitymizdeki yazdığımız hata mesajlarımız da kullanıcıya cevap olarak döndürülmesini sağlamış oluyoruz.

Tekrar istek atalım ve cevabına bakalım.

Spring Boot Dersleri Bean Validation
Spring Boot Dersleri Bean Validation

Bean validasyon üzerinde bulunan hata mesajlarımız da Controller Advice kullanarak göstermiş olduk.


Projenin Kaynak Kodlarına Ulaş


Önceki Ders: Spring Boot ile Apache Kafka Uygulaması
Spring Boot Dersleri
Sonraki Ders:

DAHA FAZLASI:Spring Boot

İlgini Çekebilir

YORUM YAP

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir