Estou trabalhando em um projeto Quarkus usando Hibernate Reactive e PostgreSQL. Tenho um método que persiste um novo usuário no banco de dados e quero lidar com o caso em que um usuário duplicado (mesmo e-mail) causa uma ConstraintViolationException devido à restrição exclusiva no campo de e-mail.
Eu configurei um bloco de tratamento de erros usando .onFailure() para capturar essa exceção e lançar uma UserAlreadyExistsException personalizada. No entanto, a exceção não está sendo capturada no bloco de falha e, em vez disso, estou vendo uma ConstraintViolationException não capturada nos logs.
@POST
@Path("/register")
@WithTransaction
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Uni<Response> registerUser(@Valid Auth authRequest) {
return authService.createUser(authRequest)
.onItem().transform(success -> Response.status(Response.Status.CREATED)
.entity(success).build())
.onFailure()
.recoverWithItem(ex -> {
log.error("Unable to create User, email: {}, Exception: {}", authRequest.getEmail(), ex.getMessage(), ex);
ErrorResponse errorResponse = new ErrorResponse(ex.getMessage(), Response.Status.INTERNAL_SERVER_ERROR);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorResponse).build();
});
}
public Uni<Auth> createUser(Auth authRequest) {
User user = new User(authRequest);
String passwordHash = Password.hash(authRequest.getPassword()).withArgon2().getResult();
user.setPasswordHash(passwordHash);
return PanacheEntityBase.persist(user).onItem().transform(success -> {
log.info("Successfully created user, email: {}", authRequest.getEmail());
return authRequest;
})
.onFailure().invoke(ex -> {
log.error("Unable to create User, email: {}, Exception: {}",
authRequest.getEmail(), ex.getMessage(), ex);
throw new RegistrationFailedException(Errors.UNABLE_TO_REGISTER_USER + ex.getMessage());
});
}
O que eu espero:
Ao tentar inserir um usuário com um e-mail existente (chave duplicada), a ConstraintViolationException deve ser capturada pelo bloco onFailure(), e uma UserAlreadyExistsException personalizada deve ser gerada.
O que acontece:
Em vez de ser capturado pelo bloco onFailure(), o seguinte erro é retornado:
org.hibernate.exception.ConstraintViolationException: error executing SQL statement
[ERROR: duplicate key value violates unique constraint "user_email_key" (23505)]
Parece que o manipulador de falhas não está capturando a exceção, e recebo uma resposta de exceção não capturada.