Você está manipulando apenas MySQLIntegrityConstraintViolationException e não outras exceções:NestedServletException e DuplicateKeyException e, portanto, você está obtendo o stacktrace e seu try/catch não está funcionando.
BTW, por que não simplesmente criar um método extra para verificar se o nome de usuário já está presente e, se sim, exibir a mensagem de erro, caso contrário, adicione o usuário.
class UserRepositoryImpl implements UserRepository{
//.....
public int isUsernameExist(String username){
String sql = "SELECT COUNT(*) FROM users WHERE username=?";
return jdbcTemplate.queryForObject(sql, new Object[] { username }, String.class);
}
//....
}
@RequestMapping(value="/register", method=RequestMethod.POST)
public String processRegisterUser(@ModelAttribute("user") User user, BindingResult result){
int status = userRepository.isUserExist(user.getUsername());
if(status==1){
//Username exist... redirect and display error msg.
} else {
userRepository.addUser(user);
}
//.....
}