Hystrix: HystrixBadRequestException for failed validations

3.9k Views Asked by At

I am trying to understand how Hystrix works with non-fault errors and the HystrixBadRequestException, particularly in the area of validation. I use JSR-303 bean validation (Hibernate validator) for all my beans:

public class User {
    @Min(1L)
    private Long id;

    @NotNull
    @Email      
    private String email;
}

public class UserValidator {
    private Validator validator;

    // Throw exception if the user is invalid; return void otherwise.
    public void validateUser(User user) {
        Set<ConstraintViolation<User>> violations = validator.validate(user);
        if(!violations.isEmpty()) {
            return new BadEntityException(violations);
        }
    }
}

// Hystrix command.
public class SaveUserCommand extends HystrixCommand<User> {
    public User user;

    public void doSaveUser(User user) {
        this.user = user;
        execute();
    }

    @Override
    protected User run() {
        // Save 'user' somehow
    }

    @Override
    protected User getFallback() {
        return null;
    }
}

// My service client that uses my Hystrix command.
public class UserClient {
    private SaveUserCommandFactory factory = new SaveUserCommandFactory();
    private UserValidator validator = new UserValidator();

    public User saveUser(User user) {
        SaveUserCommand saveUserCommand = factory.newSaveUserCommand();
        validator.validate(user);
        user = saveUserCommand.doSaveUser(user);

        return user;
    }
}

While this should work, I feel like the HystrixBadRequestException was created for this purpose, and I could somehow be putting the validator inside the command (not outside of it). According to the docs, this exception was intended for non-fault exceptions, including illegal arguments. I'm just not seeing how I could put my validation inside the command and leverage it (such that failed validations don't count against my metrics/stats).

1

There are 1 best solutions below

0
On BEST ANSWER

It turns out you need to throw the HystrixBadRequestException inside the HystrixCommand impl. In my case, the solution was to move the validator into the SaveUserCommand#run() method:

@Override
protected void run() {
    try {
        validator.validate(user);
        // Save user somehow
    } catch(BadEntityException bexc) {
        log.error(bexc);
        throw new HystrixBadRequestException("Hystrix caught a bad request.", bexc);
    }
}

Now, if validation fails, the outer exception is a HystrixBadRequestException and it will not count against circuit breaker stats or published metrics.