Search code examples
javadata-annotationsspring-annotationsjava-annotations

Java custom annotation on class as field (HAS-A relation)


Requirement - validate input as alpha numeric. I have two class are in Has-A relation

Quick help appreciate, thanks in advance.

public class Party {
    @InputContraint
    private String firstName;
    @InputContraint
    private String lastName;
    
    private Address address;
}

public class Address {
    @InputContraint
    private String countryCode;
    @InputContraint
    private String countryName;
}


@Documented
@Constraint(validatedBy = InputValidate.class)
@Target( { ElementType.METHOD, ElementType.FIELD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface InputContraint {
    String message() default "error.message";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

public class InputValidate implements ConstraintValidator<InputContraint, String> {
    @Override
    public boolean isValid(String inputVal, ConstraintValidatorContext context) {
        if (Utilities.isEmpty(inputVal))
            return true;
        //
        String regex = "^[a-zA-Z0-9]+$";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(inputVal);
        boolean valid = matcher.matches();
        return valid;
        }
}

Another way - still not working.
---
public class Address {
     @Pattern(regexp ="^[a-zA-Z0-9]+$")
     private String countryCode;
}
  1. I have created custom annotation and applied at field level

    • if field as String, it's working fine.
    • if filed as Class, is not working.
  2. Applied @Pattern(regex="^[a-zA-Z0-9]+$") at Address.countryCode


Solution

  • When you use @Valid it recurses to see if there any more valids are present and validates them all. I have also added getter methods for pojo classes, it doesn;t seems to work without getter methods. Below, I have just added how to use @Valid and did few adjustment in InputValidate. Please note that the import for @Valid comes from import javax.validation.Valid;

    Your request body for successful validation should look like this:

    {
        "firstName":"John",
        "lastName": "Doe",
        "address": {
            "countryCode":"01",
            "countryName":"United State"
        }
        
    }
    

    Controller implementation is as below:

    @RestController
    @RequestMapping("/")
    class TestController {  
    
            @PostMapping("/party")
            public String valid(@Valid @RequestBody Party party) {
                return "all valid";
            }
    }
    

    You validation class is as below:

    @Slf4j
    public class InputValidate implements ConstraintValidator<InputContraint, String> {
        @Override
        public boolean isValid(String inputVal, ConstraintValidatorContext context) {
            if(inputVal != null) {
                String regex = "^[a-zA-Z0-9]+$";
                Pattern pattern = Pattern.compile(regex);
                Matcher matcher = pattern.matcher(inputVal);
                boolean valid = matcher.matches();
                log.info("InputValidate {} is {}", inputVal, valid);
                return valid;
            } else {
                return false;
            }
        }
    }
    

    party class

    public class Address {
        @InputContraint
        private String countryCode;
    
        @InputContraint
        private String countryName;
    
        public String getCountryCode() {
            return countryCode;
        }
    
        public String getCountryName() {
            return countryName;
        }
    }
    

    Address class

    
    public class Party {
        @InputContraint
        private String firstName;
    
        @InputContraint
        private String lastName;
    
        @Valid
        private Address address;
    
        public String getFirstName() {
            return firstName;
        }
    
        public String getLastName() {
            return lastName;
        }
    
        public Address getAddress() {
            return address;
        }
    }
    

    Reference:

    https://www.sitepoint.com/java-bean-validation-object-graphs-valid-annotation/