Mensajes de excepción personalizados con Spring Framework

Estoy usando Spring e Hibernate en mi aplicación, hay un escenario en el que inserto los mismos registros más de una vez, por lo que la aplicación arroja correctamente la excepción de restricción porque apliqué la restricción única en una de las columnas db. Hasta ahora todo está bien.

Pero tengo que mostrar un mensaje personalizado como "el registro ya existe" en lugar de mostrar la excepción de hibernación.

¿Cómo puedo hacer con Spring Framework.

Cualquier sugerencia o ejemplo muy apreciado.

Saludos,

Raju

preguntado el 27 de agosto de 11 a las 22:08

3 Respuestas

Sí, puede hacer una excepción en el controlador:

  @ExceptionHandler(Exception.class)
      public ModelAndView handleMyException(Exception  exception) {
         ModelAndView mv = new ModelAndView("error");
         mv.addObject("message"."record already exists");
         return mv;
              } 

Por supuesto, puede detectar cualquier tipo de excepción, simplemente insértelo como parámetro para @ExceptionHandler

Espero eso ayude.

Respondido 28 ago 11, 14:08

Estoy enfrentando el mismo problema, pero en mi caso se pueden duplicar uno o varios campos (nombre de usuario o correo electrónico). Por lo tanto, la org.hibernate.exception.ConstraintViolationException no es lo suficientemente específico como para decir si el nombre de usuario o el correo electrónico causaron que se lanzara esta excepción y qué mensaje mostrar en consecuencia.

Solo miré respuesta de danny.lesnik pero no es genial, ya que simplemente redirige a una página "dedicada". Suponiendo que simplemente redirigir a la página en la que estaba el usuario evitaría la creación de una nueva página, diría. Sin embargo, supongo que ya tienes un Validador de primavera haciendo algún trabajo de validación de formularios. Es por eso que en mi caso decidí simplemente hacer mis controles de duplicación de campos (nombre de usuario y correo electrónico) en el mismo lugar (en el Validador). Parece una solución más adecuada, consistente (ubicada con el resto de la validación) y más limpia.

Aquí hay un código para ilustrar:

Mi controlador

@Controller
public class WebController {

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private CustomUserDetailsValidator customUserDetailsValidator;

    ...
    @RequestMapping(value = "/login/create-account", method = RequestMethod.POST)
    public String createAccount(@ModelAttribute("user") CustomUserDetails user, BindingResult result, Model model, SessionStatus status) {

        customUserDetailsValidator.validate(user, result);

        if(result.hasErrors()){
            model.addAttribute("user", user);

            // Print the errors to the console - FIXME: log error instead
                System.out.println("Validation errors:");
                for (FieldError error : result.getFieldErrors()) {
                    System.out.println(error.getField() + " - " + error.getDefaultMessage());
            }

            return "login/create-account";
        }
        else{
            userService.registerUser(user);             
            return "redirect:/login/create-account-success";
        }
    }
    ...
}

Mi validador

public class CustomUserDetailsValidator implements Validator {

    @Autowired
    private UserServiceImpl userService;
    ...

    @Override
    public void validate(Object target, Errors errors) {

        // some simple validations

        // and here some complex validation (is username or email used duplicated?)
        if(errors.getAllErrors().size() == 0){

            if ( userService.doesUsernameAlreadyExist( user.getUsername() ) )
                errors.rejectValue(usernameFieldName, "duplicate.username","username already exists");

            if ( userService.doesEmailAlreadyExist( user.getEmail() ) )
                errors.rejectValue(emailFieldName, "duplicate.email","email already exists");

        }
    }
}

No estoy seguro de si esa es la mejor manera de hacer esto, pero pensé que mi solución permitiría más extensión (puede agregar varias verificaciones en cualquier otra restricción).

Espero que ayude a otros y también sería interesante que más desarrolladores pensaran en esta solución.

contestado el 23 de mayo de 17 a las 15:05

puede detectar la excepción lanzada por spring / hibernate y lanzar una de sus propias excepciones que contendría el mensaje 'el registro ya existe', incluso podría buscar un mensaje localizado de un paquete de recursos y mostrar este mensaje en su capa de presentación (por ejemplo, jsp)

Respondido 28 ago 11, 02:08

Incluso estoy pensando lo mismo al extender la excepción, crearé una excepción. Pero ¿cómo puedo mostrar el mismo mensaje en la capa de preestablecimiento de Spring? - Raj

cuando un usuario intenta agregar un registro duplicado, puede detectar la excepción de hibernación, luego, en su capa de servicio (es decir, donde llama a su lógica de backend), intentaría insertar el registro y detectar la excepción y luego reenviar a una página de error, algo como eso - eternidad

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.