Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javax Validation Implementation

I am trying to create my custom annotation for local variables but I just don't understand how annotations like @NotNull or @Null are actually implemented in code. I looked at the actual file, here's @NotNull:

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = { })
public @interface NotNull {

    String message() default "{ javax.validation.constraints.NotNull.message }";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };

    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
    @Retention(RUNTIME)
    @Documented
    @interface List {
        NotNull[] value();
    }
}

But I don't see anywhere where it checks to see if something is null or not. Where is the actual check happening?

like image 969
Richard Avatar asked Dec 05 '22 18:12

Richard


2 Answers

Usually you need to provide validatedBy class that is used for validation

@Target(TYPE)
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {TicketPresenceValidator.class})
public @interface AtLeastOneTicket {
}


public class TicketPresenceValidator implements ConstraintValidator<AtLeastOneTicket, TicketInfo> {
 @Override
 public void initialize(TicketInfo constraintAnnotation) {
 }

 @Override
 public boolean isValid(TicketInfo ticketInfo, 
                        ConstraintValidatorContext context) {
    return ticketInfo.getSize() != 0;
 }
}

For built-in constraints (from javax.validation.* package) like NotNull validators are provided by implementation library. For example Hibernate Validator implementation, here is

NullValidator implementation

Then constraints and validators linked together in helper class

like image 96
inigo skimmer Avatar answered Dec 09 '22 14:12

inigo skimmer


Where is the actual check happening?

If you look closely at - javax.validation.constraints.@NotNull source code ( that you have pasted ) , @Constraint(validatedBy = { }) is left empty i.e. its not specified which would be implementation class. Its because javax validation jar like - validation-api-2.0.1.Final.jar etc is basically a bean validation standard ( a set of interfaces , annotations etc with no implementation ). Implementation of these constraints is provided by vendors like hibernate , Oracle etc .

This link lists three standards so you should know which version of bean validation standard you are using.

So if you have implementation jars like - hibernate-validator-6.0.10.Final.jar , you could see implementation source code too ,

/*
 * Hibernate Validator, declare and validate application constraints
 *
 * License: Apache License, Version 2.0
 * See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
 */
package org.hibernate.validator.internal.constraintvalidators.bv;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.constraints.NotNull;

/**
 * Validate that the object is not {@code null}.
 *
 * @author Emmanuel Bernard
 */
public class NotNullValidator implements ConstraintValidator<NotNull, Object> {

    @Override
    public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) {
        return object != null;
    }
}

Now , you have to understand that searching / resolving for implementation of bean validation standard is a complex task , refer - javax.validation.ValidationProviderResolver & this process has been made easy if developer is using frameworks like Spring Boot etc.

Answer by inigo skimmer also does these two things - declares an annotation for your custom validation , implements the actual validation and resolves validator by hard coding validator class in - @Constraint(validatedBy = {TicketPresenceValidator.class}) & that saves you from complex validation implementation searching logic.

The other part that you have to understand is that your validator is of type javax.validation.ConstraintValidator so read javadoc as what you need to provide to this interface

Other links to refer to ,

Creating custom constraints

Create Your Own Constraints With Bean Validation 2.0

like image 26
Sabir Khan Avatar answered Dec 09 '22 14:12

Sabir Khan