6 Pola Penanganan Error di Aplikasi Java Intranet
Penanganan error yang rapi menentukan seberapa cepat tim bisa melacak masalah di aplikasi intranet. Ada enam pola penanganan error aplikasi Java yang biasa dipakai, masing-masing dengan konsekuensi berbeda pada keterbacaan kode, kemudahan audit, dan beban operasional. Pilihan terbaik bergantung pada seberapa besar aplikasi dan siapa yang membaca log saat insiden terjadi.
1. Exception kustom per domain
Alih-alih melempar RuntimeException generik, buat kelas exception yang mencerminkan kegagalan domain, misalnya DataTidakDitemukanException atau KuotaTerlampauiException. Keuntungannya muncul saat lapisan atas perlu membedakan penanganan: pengontrol bisa memetakan exception tertentu ke kode HTTP yang sesuai tanpa memeriksa pesan teks.
Buat hierarki dangkal. Satu kelas dasar per modul sudah cukup, lalu turunkan dua sampai empat varian. Hierarki dalam membuat catch menjadi tidak jelas urutannya. Untuk aplikasi yang masih kecil, exception kustom sering berlebihan; gunakan yang sudah ada di JDK sampai kebutuhan membedakan penanganan benar-benar muncul.
2. Global exception handler di lapisan web
Pasang satu penangkap error di depan semua pengontrol. Di Spring, ini berupa @ControllerAdvice; di JAX-RS, ExceptionMapper. Tujuannya agar setiap respons error punya bentuk yang konsisten: kode status, kode error internal, dan pesan yang aman ditampilkan ke pengguna.
Handler global sebaiknya tidak menelan detail. Catat exception asli beserta stack trace ke log, lalu kirim ke klien hanya informasi yang tidak membocorkan struktur internal. Untuk intranet yang dipakai banyak divisi, kode error internal memudahkan tim dukungan mencocokkan laporan pengguna dengan baris log.
Perhatikan juga jalur asinkron. Pemanggilan yang berjalan di thread terpisah tidak selalu melewati handler yang sama; bila aplikasi memakai virtual thread, pastikan exception di dalam task tetap tercatat.
3. Retry terbatas untuk kegagalan sementara
Panggilan ke layanan lain di jaringan intranet bisa gagal sesaat: koneksi putus, timeout, atau server tujuan sedang restart. Pola retry dengan batas jumlah percobaan dan jeda yang meningkat membantu melewati gangguan singkat tanpa menambah beban saat layanan tujuan benar-benar mati.
Terapkan retry hanya pada operasi idempoten. Menembak ulang permintaan yang membuat data bisa menghasilkan duplikat. Sebelum menyalahkan kode, pastikan jalur jaringan memang sehat; cara memeriksa konektivitas dari sisi server bisa dilihat pada panduan uji konektivitas jaringan.
4. Circuit breaker untuk ketergantungan eksternal
Ketika layanan tujuan gagal terus-menerus, retry hanya memperpanjang antrean. Circuit breaker memutus panggilan setelah ambang kegagalan tertentu, memberi waktu layanan tujuan pulih, dan mengembalikan respons cadangan dengan cepat. Perbandingan sederhana antara retry dan circuit breaker:
| Aspek | Retry | Circuit breaker |
|---|---|---|
| Cocok untuk | Gangguan sesaat | Layanan yang lama tidak tersedia |
| Risiko utama | Badai permintaan | Respons cadangan yang tidak akurat |
| Kompleksitas | Rendah | Sedang, butuh pemantauan status |
Keduanya bisa digabung: circuit breaker memutus lebih dulu, retry hanya dilakukan setelah sirkuit tertutup kembali.
5. Fallback yang jujur ke pengguna
Fallback bukan berarti mengembalikan data kosong seolah semuanya normal. Pengguna intranet perlu tahu bahwa sebagian data tidak tersedia agar tidak mengambil keputusan dari informasi yang salah. Tampilkan pesan yang menyebut bagian mana yang gagal dimuat, dan tandai data yang berasal dari cache atau perkiraan.
Untuk data yang sering dibaca dan jarang berubah, kombinasi strategi caching dengan fallback dapat menjaga aplikasi tetap berguna saat layanan sumber sedang bermasalah. Tetap batasi usia data cadangan supaya tidak menyesatkan.
6. Logging terpusat dengan korelasi permintaan
Satu permintaan pengguna bisa melewati beberapa layanan. Tanpa pengenal korelasi, baris log dari layanan berbeda sulit disatukan. Tambahkan ID permintaan di awal pemrosesan, teruskan lewat header, dan sertakan di setiap baris log. Di aplikasi Java, pendekatan ini bisa memanfaatkan MDC pada kerangka logging yang dipakai.
Pisahkan level log berdasarkan dampak: ERROR untuk kegagalan yang menghentikan operasi, WARN untuk fallback atau retry yang berhasil, INFO untuk peristiwa bisnis penting. Jangan mencatat data pribadi pengguna di log; bila perlu menelusuri kebocoran, ikuti langkah pada panduan pemeriksaan kebocoran data pribadi dan bersihkan log sebelum dibagikan ke tim lain.
Pola ini melengkapi pola sebelumnya. Retry dan circuit breaker menghasilkan peristiwa yang hanya berguna bila tercatat dengan rapi, dan handler global butuh log yang bisa dicari berdasarkan ID permintaan.
Ringkasan
Untuk aplikasi intranet berukuran kecil, exception kustom secukupnya plus handler global sudah memadai. Tambahkan retry dan circuit breaker ketika aplikasi mulai bergantung pada layanan lain. Logging terpusat dengan ID korelasi sebaiknya dipasang lebih awal karena biaya menambahkannya belakangan jauh lebih besar daripada menyiapkannya sejak awal.
Pertanyaan yang Sering Diajukan
Apakah semua exception harus ditangkap di lapisan web?
Tidak. Tangkap di lapisan yang bisa melakukan sesuatu terhadap kegagalan itu. Exception yang tidak bisa ditangani di tempatnya lebih baik dibiarkan naik ke handler global agar tercatat lengkap.
Berapa kali retry yang wajar?
Umumnya dua sampai tiga percobaan sudah cukup untuk gangguan jaringan singkat. Lebih dari itu, kegagalan biasanya bukan lagi bersifat sementara dan circuit breaker lebih tepat dipakai.
Apakah penanganan error berbeda antara checked dan unchecked exception?
Berbeda pada titik penangkapannya. Ringkasan perbedaan keduanya ada di artikel checked vs unchecked exception; untuk pola di atas, exception domain biasanya cukup diturunkan dari salah satu jenis tersebut sesuai kebutuhan pemanggil.









