简体   繁体   中英

What are the best practices to handler or throw exceptions in a Spring Boot application?

I've developed a rest api using Spring Boot. In one of my service methods, I throw a ServletException , in case a specific user is not found. I am wondering if that is the best way to do that, I mean, is that the right layer to thrown the exception?

Creating a custom exception type is a better idea than using ServletException . In order to handle an exception you can use @ControllerAdvice . First create custom exception type:

public class UserNotFoundException extends RuntimeException {

  public UserNotFoundException(String message) {
    super(message);
  }
}

Assuming that your controller and service look more or less like this:

@RestController
@RequestMapping("users")
class UserController {

  private final UserService userService;

  UserController(UserService userService) {
    this.userService = userService;
  }

  @GetMapping
  List<String> users() {
    return userService.getUsers();
  }
}

@Service
class UserService {

  List<String> getUsers() {
    // ...
    throw new UserNotFoundException("User not found");
  }
}

You can handle you UserNotFoundException using @ControllerAdvice

@ControllerAdvice
class CustomExceptionHandler {

  @ExceptionHandler({UserNotFoundException.class})
  public ResponseEntity<Object> handleUserNotFoundException(UserNotFoundException exception) {
    return new ResponseEntity<>(exception.getMessage(), HttpStatus.NOT_FOUND);
  }
}

One of best way or what I do is,

  1. Check data / parameters for valid data( eg Null check sometime manually using if statement).
  2. Checking data / parameters for size (like file size)
  3. checking data or parameters for valid range also data type, do typecasting if not in valid type (like String, Long, Integer etc).
  4. Raise a message and return to that API, if the data / parameters are not valid before system raise an exception

I am assuming you are looking to catch all exceptions occured inside your application. Spring-Boot provides a Global Exception Handler to catch all the exceptions gracefully and return response according to the the specific Exception. It gives you flexibility to change the status codes, response data, headers accordingly. Few useful links to implement this feature is -

1.) Dzone

2.) Spring Boot Tutorial

Throwing exception in your @Service is okay. ServletException is not super meaningful. What I would suggest is to create your own Exception class extending RuntimeException and throw it.

So you would end up with something like that:

A Controller that only calls a service method (better not to have any logic here)

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public User getUserById(@PathVariable("id") Long id) {
        return userService.getById(id);
    }
}

A Service class that calls DAO class (extending JPARepository )

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDAO userDAO;

    @Override
    public User getById(Long id) {
        return userDAO.findById(id).orElseThrow(() -> new UserNotFoundException("No user with id = " + id + " found."));
    }
}

DAO:

@Repository
public interface UserDAO extends JpaRepository<User, Long> {
}

note: it returns Optional<Object> which is very convinient.

And finally your own Exception class.

@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException {
    public UserNotFoundException(String message) {
        super(message);
    }
}

Note: @ResponseStatus - it is going to return HTTP Status code 404 on throwing this exception.

This is imho a very clean and good way to develop your rest api.

Also take a look here: How to get spesific error instead of Internal Service Error . I answered a question providing information you might find useful

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM