Search code examples
javahibernate-validator

Passing Class Name as Argument to Method


I've built a REST Service with Spring Boot. In one request method I'm validating the incoming request vs. an Object that I have annotated for validation (@NotNull etc.) using Hibernate Validator. The code for the REST endpoint looks like this:

@GetMapping(value = "/parameter-dates")
    public ResponseEntity getParameterDates(ParameterDateRequest parameterDateRequest) {

        Set<ConstraintViolation<ParameterDateRequest>> inputErrors = validator.validate(parameterDateRequest);

        if (!inputErrors.isEmpty()) {

            objectValidationErrorMessages = new ArrayList<>();
            for (ConstraintViolation<ParameterDateRequest> constraintViolation : inputErrors) {
                objectValidationErrorMessage = new ObjectValidationErrorMessage();
                log.info("Error for user: " + loggedInUser.getUserEmail() +
                        " field: " + constraintViolation.getPropertyPath() + " with value: " + parameterDate.getParameterDateUnadjusted() +
                        " has error: " + constraintViolation.getMessage());
                objectValidationErrorMessage.setFieldWithError(constraintViolation.getPropertyPath().toString());
                objectValidationErrorMessage.setErrorMessage(constraintViolation.getMessage());
                objectValidationErrorMessages.add(objectValidationErrorMessage);
            }

            return (new ResponseEntity(objectValidationErrorMessages, headers, HttpStatus.BAD_REQUEST));

        }
//The rest of the code that is used when there is not validation errors

I would like to move the creation of the validation error messages to a metod of it's own like this:

public List<ObjectValidationErrorMessage> getErrorMessages(Class<?> clazz, Object model) {

        List<ObjectValidationErrorMessage> objectValidationErrorMessages = new ArrayList<>();
        Set<ConstraintViolation<?>> inputErrors = validator.validate(model);

        if (!inputErrors.isEmpty()) {
            for (ConstraintViolation<?> constraintViolation : inputErrors) {
                objectValidationErrorMessage = new ObjectValidationErrorMessage();
                objectValidationErrorMessage.setFieldWithError(constraintViolation.getPropertyPath().toString());
                objectValidationErrorMessage.setErrorMessage(constraintViolation.getMessage());
                objectValidationErrorMessages.add(objectValidationErrorMessage);
            }
        }
        return objectValidationErrorMessages;
    }

With the code as it is now I get the following error Unknow class: validateClass for Set<ConstraintViolation<validatedClass>>. How do I pass a Class name, in this case ParameterDateRequest as an argument to a method?

Update: I manged to pass the Class as Class<?> clazz. I also realised that I need to pass the Object as an Object but I get this error:

validate (T, Class<?>...) in Validator cannot be applied
to (java.lang.Object) 
reason: Incompatible equality constraint: ? and T

Solution

  • You can generify your method:

    public <T> List<ObjectValidationErrorMessage> getErrorMessages(Class<T> clazz, T model) {
    

    This will ensure that your Class<?> token and your Object have matching types.

    Then pass the arguments as such:

    validator.validate(model, clazz)
    

    Note I could be misreading the error (I couldn't find the javadocs for the validator), so it's also possible that validator has a class-level generic (e.g. Validator<MyType>). If that's the case, then the T/Object you pass to validator#validate must match the type of the Validator, but the second parameter seems to accept any classtype (Class<?>). You also wouldn't need to generify the method as well, you would just have to match the type for the validator.