Sitemap

GlobalExceptionHandler in Java

3 min readApr 16, 2026

--

GlobalExceptionHandler is, as it’s called, an actual global exception handler. It picks up all the errors through the app and handles them from one place, a center. It takes them and turns them into something user can read better.

  • For example; when we send a request from Postman, it returns an error, let’s say, and the response error message has all the lines that contain, status code, error line, port, host and etc. All too long for us and our time will be wasted when we look for the error part in all this. This is where GlobalExceptionHandler comes into play, it takes the error and matches the message we want the user/developer to see. Instead of 5 or 10 lines, it just returns a line or two that explains the error simply to the client.
  • There can be same type of error for different Controller methods. GlobalExceptionHandler saves us from writing lots of try-catch methods all over in every Controller that has the same error type.
  • When exceptions are thrown, it’s usually done with where the error is, line number, if used some credentials and etc. This violates our privacy and data. Outside shouldn’t see these. Or front-end developers. They don’t need them. Actually, when using GlobalExceptionHandler, we also hide this private stuff.

Attention: Here are somethings we should be aware!

  • Don’t try to catch all the errors with only one method. If there is no error log in the background, your specific error will be gone, and you won’t what it was and where did it occur.
  • If you want to test your error and if it does not work, you cannot try your B plan or any other way, that is if you send your error up to GlobalExceptionHandler. Instead that you should use a try-catch block here.
  • Do not try to catch all your errors with only ONE exception handler file. Have a few of them and scatter them around the modules.
  • Trying to catch every error (even the not error ones), will slow down your system.

And this is how I used it in my Spring Boot project:

I have 3 files in my exception directory which are GlobalExceptionHandler, AlreadyExistsException and CountryAlreadyExistsException.

Get Ece Aslan’s stories in your inbox

Join Medium for free to get updates from this writer.

AlreadyExistsException:

public class AlreadyExistsException extends RuntimeException{
public AlreadyExistsException(String message){
super(message);
}
}
  • This class will catch all the ‘This thing already exists in the database.’ errors. Root for these errors.
  • It’s extending RuntimeException, which meaning that the error gets thrown does not need to be checked.
  • We send a message to it, the one that’s going to be displayed for the front-end of the app.

— — — — — — —

CountryAlreadyExists:

public class CountryAlreadyExistsException extends AlreadyExistsException{
public CountryAlreadyExistsException(){
super(i18nConstants.COUNTRY_ALREADY_EXISTS);
}
}
  • This class is a specialized version of AlreadyExistsException class.
  • It also takes a message to throw. BUT! This time it takes the message from a constant which we defined before. In i18n. We have defined an error sentence for each language that is in the app. So this function only takes the error variable name. Then goes to language message properties. And picks up the error message and returns it to the screen.

— — — — — — —

GlobalExceptionHandler:

@RequiredArgsConstructor
@ControllerAdvice
public class GlobalExceptionHandler {
private final I18nMessageService messageService;
@ExceptionHandler({AlreadyExistsException.class})
public ResponseEntity<GenericResponse<Object>> handleAlreadyExistsException(AlreadyExistsException exception){
String message = messageService.getMessage(exception.getMessage(), LocaleContextHolder.getLocale());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(
GenericResponse.builder().success(false).message(message).data(LocaleContextHolder.getLocale().toString()).build());
}
}
  • @ControllerAdvice annotation tells Spring that itself is the root of all Controllers, I’ll take care of the errors.
  • @ExceptionHandler({AlreadyExistsException.class}) means that if the error that’s been thrown is under this class, take it through this one and generate a proper response and return it back.

— — — — — — — — — —

When error happens in the Service layer it goes back up.

GlobalExceptionHandler catches it before it goes to Postman and after Controller. With GenericResponse it will take the matched answer and convert it to a JSON format. Then the answer will go to Postman.

--

--