Menangani Exception Secara Global dengan @ControllerAdvice dan @RestControllerAdvice di Spring Boot
Pengenalan
Dalam pengembangan aplikasi Spring Boot, penanganan error yang konsisten dan terstruktur merupakan hal yang sangat penting. Spring Framework menyediakan mekanisme yang powerful untuk menangani exception secara global menggunakan anotasi @ControllerAdvice dan @RestControllerAdvice. Artikel ini akan membahas kedua anotasi tersebut beserta implementasi praktisnya.
| Contoh RestControllerAdvice |
Apa itu @ControllerAdvice?
@ControllerAdvice adalah anotasi yang memungkinkan kita untuk menangani exception secara global di seluruh aplikasi Spring. Dengan menggunakan anotasi ini, kita tidak perlu menulis blok try-catch di setiap controller atau method. Semua exception yang terjadi akan ditangkap dan diproses di satu tempat terpusat.
Karakteristik @ControllerAdvice:
- Berlaku untuk semua controller dalam aplikasi
- Dapat menangani berbagai jenis exception
- Mendukung pembuatan response view (HTML, JSP, Thymeleaf)
- Cocok untuk aplikasi web tradisional yang mengembalikan halaman HTML
Apa itu @RestControllerAdvice?
@RestControllerAdvice adalah versi khusus dari @ControllerAdvice yang dirancang untuk RESTful API. Anotasi ini merupakan kombinasi dari @ControllerAdvice dan @ResponseBody, yang artinya setiap response akan otomatis dikonversi menjadi JSON atau XML.
Karakteristik @RestControllerAdvice:
- Khusus untuk REST API
- Response otomatis di-serialize menjadi JSON/XML
- Tidak perlu menambahkan
@ResponseBodydi setiap method handler - Cocok untuk aplikasi modern yang berbasis microservices
Perbedaan Utama
| Aspek | @ControllerAdvice | @RestControllerAdvice |
|---|---|---|
| Response Type | View (HTML, JSP) | JSON/XML |
| @ResponseBody | Perlu ditambahkan manual | Sudah included |
| Use Case | Web tradisional | REST API |
| Serialization | Manual | Otomatis |
Implementasi GlobalExceptionHandler
Berikut adalah contoh implementasi @RestControllerAdvice yang menangani exception secara global:
package com.yusuf.springmongoclean.exception;
import com.yusuf.springmongoclean.dto.ErrorResponse;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import java.time.Instant;
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(IllegalArgumentException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleIllegalArgument(
IllegalArgumentException ex,
HttpServletRequest request
) {
return new ErrorResponse(
Instant.now(),
HttpStatus.BAD_REQUEST.value(),
ex.getMessage(),
request.getRequestURI()
);
}
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorResponse handleAll(Exception ex, HttpServletRequest request) {
log.error("Unhandled exception", ex);
return new ErrorResponse(
Instant.now(),
HttpStatus.INTERNAL_SERVER_ERROR.value(),
"Internal server error",
request.getRequestURI()
);
}
}
Penjelasan Kode:
1. @RestControllerAdvice Anotasi ini menandakan bahwa class ini adalah global exception handler untuk REST API.
2. @ExceptionHandler Anotasi ini menentukan jenis exception mana yang akan ditangani oleh method tersebut. Dalam contoh di atas, ada dua handler:
handleIllegalArgument: MenanganiIllegalArgumentExceptionhandleAll: Menangani semua exception lainnya sebagai fallback
3. @ResponseStatus Anotasi ini menentukan HTTP status code yang akan dikembalikan. Contohnya:
BAD_REQUEST(400) untuk invalid argumentINTERNAL_SERVER_ERROR(500) untuk error yang tidak terduga
4. ErrorResponse Object DTO yang berisi informasi error dengan struktur konsisten:
- Timestamp: Waktu terjadinya error
- Status Code: Kode HTTP status
- Message: Pesan error
- Path: URL endpoint yang error
5. Logging
Method handleAll menggunakan logger untuk mencatat exception yang tidak tertangani, memudahkan debugging.
Contoh Class ErrorResponse
package com.yusuf.springmongoclean.dto;
import java.time.Instant;
public record ErrorResponse(
Instant timestamp,
int status,
String error,
String path
) {}
Contoh Kasus Yang Menggunakan ErrorResponse
| Kita membuat dulu sebuah user dengan nama dan email Bunny |
| Ups, saat buat lagi user yang sama maka kita akan mentrigger exception |
Contoh Response JSON
Ketika terjadi error, aplikasi akan mengembalikan response JSON seperti ini:
Best Practices
1. Tangani Exception Spesifik Terlebih Dahulu
Urutkan handler dari yang paling spesifik ke yang paling general. Exception yang lebih spesifik harus ditangani sebelum exception parent-nya.
2. Gunakan Logging yang Tepat
Log error yang serious (500) dengan level ERROR, sedangkan client error (400) bisa dengan level WARN atau tidak di-log sama sekali.
@ExceptionHandler(IllegalArgumentException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleIllegalArgument(
IllegalArgumentException ex,
HttpServletRequest request
) {
return new ErrorResponse(
Instant.now(),
HttpStatus.BAD_REQUEST.value(),
ex.getMessage(),
request.getRequestURI()
);
}
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorResponse handleAll(Exception ex, HttpServletRequest request) {
log.error("Unhandled exception", ex);
return new ErrorResponse(
Instant.now(),
HttpStatus.INTERNAL_SERVER_ERROR.value(),
"Internal server error",
request.getRequestURI()
);
}
3. Jangan Expose Informasi Sensitif
Untuk production, hindari menampilkan stack trace atau detail internal system kepada client.
4. Buat Custom Exception
Untuk business logic yang spesifik, buat custom exception yang lebih deskriptif.
Kapan Menggunakan @ControllerAdvice vs @RestControllerAdvice?
Gunakan @ControllerAdvice ketika:
- Membangun aplikasi web tradisional dengan server-side rendering
- Menggunakan template engine seperti Thymeleaf atau JSP
- Ingin redirect ke halaman error custom
Gunakan @RestControllerAdvice ketika:
- Membangun REST API
- Response berupa JSON atau XML
- Aplikasi berbasis microservices
- Frontend terpisah (SPA dengan React, Vue, Angular)
Kesimpulan
@ControllerAdvice dan @RestControllerAdvice adalah fitur powerful dalam Spring Boot untuk menangani exception secara global dan konsisten. Dengan menggunakan anotasi ini, kita dapat:
- Memisahkan logic penanganan error dari business logic
- Membuat response error yang konsisten di seluruh aplikasi
- Meningkatkan maintainability kode
- Memberikan pengalaman yang lebih baik kepada client API
Untuk aplikasi REST API modern, @RestControllerAdvice adalah pilihan yang tepat karena otomatis mengkonversi response menjadi JSON tanpa perlu konfigurasi tambahan. Pastikan untuk selalu menerapkan best practices dalam implementasinya agar aplikasi lebih robust dan mudah di-maintain.
Comments
Post a Comment