Blog'a Dön
Spring Boot Hata Yönetimi- Exception Handling

Spring Boot Hata Yönetimi- Exception Handling

4 dk okuma
Java Spring Boot

Bu yazımızda bir Spring Boot projesinde temel hata yönetimi nasıl olur.
Hangi anotasyonlar ve yöntemler kullanılıyor kısaca bahsedeceğiz.

Exception Nedir?

Exception (İstisna) programımızda bir hata meydana geldiğinde fırlatılan olaydır.
Eğer projede iyi bir hata yönetimi yoksa beklenmeyen davranışlar programımızın çökmesine sebep olabilir.

İşte bu durumları engellemek adına exception handling (hata yönetimi) mekanizmaları kullanılır.

Java’da tüm exceptionlar Throwable sınıfından türemiştir ve iki ana başlığa ayrılır:

  • Checked Exception
  • Unchecked Exception

Kısaca bunlara da değinelim.

1. Checked Exception

Derleme yani programımız build edilirken ortaya çıkan hatalardır.
Bize görev düşen try-catch bloklarıyla hatayı yakalamak veya throws anahtar kelimesiyle hatayı üst metoda devretmektir.

Örnekler: IOException, SQLException, FileNotFoundException

try { FileReader file = new FileReader("dosya.txt"); } catch (FileNotFoundException e) { System.out.println("Dosya bulunamadı: " + e.getMessage()); }

2. Unchecked Exception

Program çalışmasını sürdürürken ortaya çıkan hatalardır.
Derleme aşamasında yakalanmaz, bu yüzden bizim kontrol etmemiz gerekir.

Örnekler: NullPointerException, ArrayIndexOutOfBoundsException, ArithmeticException

int[] sayilar = {1, 2, 3}; try { System.out.println(sayilar[5]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Hatalı index: " + e.getMessage()); }

Eğer try-catch içine almasaydık program çalışmayı durdurup çökecekti.
Biz kontrol altına alarak kullanıcıyı hata konusunda bilgilendirdik.

Spring Boot’da Hata Yönetimi

Temel seviyede 2 başlıkta inceleyebiliriz:

  1. Metot Bazında Hata Yönetimi (@ExceptionHandler)
  2. Global Hata Yönetimi (@ControllerAdvice)

1. Metot Bazında Hata Yönetimi

Spring Boot’ta @ExceptionHandler anotasyonu, sadece ilgili controller sınıfında meydana gelen hataları yakalamak için kullanılır.
Bu yöntem daha çok belirli controller’a özel hataları yakalamak istediğimizde tercih edilir.

Aşağıda IllegalArgumentException hatasını yakalayan basit bir örnek gösteriyorum:

@RestController @RequestMapping("/api/users") public class UserController { @GetMapping("/{id}") public String getUser(@PathVariable int id) { if (id <= 0) { throw new IllegalArgumentException("ID sıfırdan büyük olmalı"); } return "User: " + id; } // Bu controller içindeki IllegalArgumentException'ı yakalar @ExceptionHandler(IllegalArgumentException.class) public ResponseEntity<String> handleIllegalArgument(IllegalArgumentException ex) { return ResponseEntity.badRequest().body("Hata: " + ex.getMessage()); } }

Yukarıdaki örnekte getUser metodunda IllegalArgumentException fırlatıldığında,
@ExceptionHandler ile belirttiğimiz metod çalışır ve hatayı yönetir.

Burada dikkat edilmesi gereken nokta: Eğer başka bir controller’da aynı hata olursa, bu metod devreye girmez.
İşte bu yüzden daha kapsamlı bir çözüm için Global Hata Yönetimi (@ControllerAdvice) tercih edilir.

2. Global Hata Yönetimi (@ControllerAdvice)

@ExceptionHandler sadece o sınıfta belirtilen hataları yakalar.
Daha profesyonel bir yaklaşım için @ControllerAdvice kullanılır.
Böylece tüm controller’larda oluşabilecek hataları merkezi olarak yönetebiliriz.

Önce basit bir custom exception oluşturalım:

@ResponseStatus(HttpStatus.NOT_FOUND) // otomatik 404 döndürür public class UserNotFoundException extends RuntimeException { public UserNotFoundException(String message) { super(message); } }

Ardından global hata sınıfımızı oluşturalım:

@ControllerAdvice public class GlobalExceptionHandler { // Kendi yazdığımız custom exception @ExceptionHandler(UserNotFoundException.class) public ResponseEntity<String> handleUserNotFound(UserNotFoundException ex) { return new ResponseEntity<>("Hata: " + ex.getMessage(), HttpStatus.NOT_FOUND); } // Genel hata davranışı @ExceptionHandler(Exception.class) public ResponseEntity<String> handleGeneric(Exception ex) { return new ResponseEntity<>("Bir hata oluştu: " + ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } }

Şimdi bu hatayı controller’da fırlatalım.
Burada @ControllerAdvice anotasyonu sayesinde bu hata yakalanacak:

@RestController @RequestMapping("/api/users") public class UserController { private final Map<Integer, String> users = Map.of( 1, "Ali", 2, "Baran" ); @GetMapping("/{id}") public String getUser(@PathVariable int id) { String user = users.get(id); if (user == null) { throw new UserNotFoundException("Kullanıcı bulunamadı: " + id); } return user; } }

Genel hata yönetimi sayesinde projemizi try-catch bloklarına boğmaktan çıkarıp merkezi bir davranış ortaya koyabiliyoruz.
Ben örnekte Controller’da kullanımına yer verdim fakat servis içinde kullanımı daha da kullanışlıdır.
Mantık yine aynı: Sen hatayı fırlat, @ControllerAdvice ile belirttiğin sınıf o hatayı yakalasın.

Sonuç

Bu yazıda Spring Boot projelerinde hata yönetiminin (exception handling) nasıl yapılabileceğini ele aldık.
İleride bu yazıyı daha detaylı örneklerle genişleteceğim.

O zamana kadar takipte kalıp paylaşım yaparsanız çok sevinirim.
Her zaman daha ileriye!