JBVE (Java Bean Validation Extension) is a small utils library that extends the Java Bean Validation Specification with additional @Annotations.
If you are not familiar with JSR-380 (or the Java Bean Validation Specification) please follow this nice tutorial first.
If you want to see JVBExt at work please:
- read this blog article;
- check out this repository.
For versions (>=0.0.12):
<dependency> <groupId>net.andreinc</groupId> <artifactId>jbve</artifactId> <version>0.0.12</version> </dependency>Important note(s):
In the runtime environment you will an existing JSR-380 implementation in the classpath. Spring Boot started web comes by default with Hibernate Validator.
If you are using the library in another environment that doesn't provide a JSR-380 implementation you will need to add the following as dependencies:
compile group: 'org.hibernate', name: 'hibernate-validator', version: '6.0.2.Final' compile group: 'org.glassfish', name: 'javax.el', version: '3.0.1-b08'Java Bean Validation Extension was downloaded +/-450 times since October, 2017.
If you are using jbvext in your cool projects please send me a note so I can include you in this list.
| @Annotation | Supported Types | Description |
|---|---|---|
@After | Date | Check if the Date is after the given date value, with date format as parameter. |
@Alpha | String | Checks if the String contains only unicode letters. |
@Alphanumeric | String | Checks if the String contains unly unicode letters or digits |
@AlphanumericSpace | String | Checks if the String contains only unicode letters, digits, empty strings or spaces. |
@AlphaSpace | String | Checks if the String contains only Unicode letters and space " ". |
@AsciiPrintable | String | Checks if the String contains only ASCII printable characters. |
@Blank | String | Checks if the String is empty "", null or whitespace(s) " " only. |
@Before | Date | Check if the Date is before the given date value, with date format as parameter. |
@CC | String | Checks if the String is a valid credit card number. |
@EndsWith | String | Checks if the Strings ends with a specified suffix(es). |
@InstanceOf | Object | Check if the Object is an instanceof of (at least one of) the supplied value(s). |
@IPv4 | String | Checks if the String is a valid IPv4 address. |
@IPv6 | String | Checks if the String is a valid IPv6 address. |
@IsDate | String | Check if the String is in a date format. |
@LowerCase | String | Checks if the String contains only lowercase letters. |
@MinDigits | Double | Checks whether the annotated value is higher than or equal to the specified minimum. |
@MaxDigits | Double | Checks whether the annotated value is less than or equal to the specified maximum. |
@NotInstanceOf | Object | Check if the is not an instanceof of (all the) the supplied value(s). |
@Numeric | String | Checks if the String contains only unicode digits. Note: A decimal point is not considered a digit and the validation fails. Use @Parseable instead for more advanced validations. |
@OneOfChars | Character | Checks if the Character is contained in a given array (char[]) of values. |
@OneOfDoubles | Double | Check if the Double is contained in a given array (double[]) of values. |
@OneOfIntegers | Integer | Check if the Integer is contained in a given array (int[]) of values. |
@OneOfLongs | Long | Check if the Long is contained in a given array (long[]) of values. |
@OneOfStrings | String | Checks if the String is contained in a given array (String[]) of values. |
@Parseable | String | Checks if the String can be parsed to a number (Short, Integer, Long, Double, etc.). |
@Password | String | Checks if the String is a valid password. |
@StartsWith | String | Checks if the String starts with the specified prefix(es). |
@UpperCase | String | Checks if the String contains only uppercase letters. |
Note:
All the examples are using project's lombok annotations like @Data, @NoArgsConstructor, @AllArgsConstructor, etc. Those annotations are used make the examples more compact, but their use is optional.
Check if the Date is after the given date value.
The annotation supports a second property format that by default is "yyyy-MM-dd'T'HH:mm:ss.SSSZ".
@Data class AfterBean { @After(value = "2018-01-01", format = "yyyy-MM-dd") private Date isAfter = new Date(1522399999911L); // Passes // Date = 2018-03-30 }Check if the String contains only unicode letters.
Behavior:
| Value | Result |
|---|---|
null | ❌ Fails |
"" | ❌ Fails |
" " | ❌ Fails |
"abc" | ✅ Passes |
"ab2c" | ❌ Fails |
"ab-c" | ❌ Fails |
@Data class TestAlpha { @Alpha private String alpha = "abc"; @Alpha /** Will fail */ private String nonAlpha = "pr�s-*"; }Checks if the String contains only unicode letters or digits.
Behavior:
| Value | Result |
|---|---|
null | ❌ Fails |
"" | ❌ Fails |
" " | ❌ Fails |
"abc" | ✅ Passes |
"ab c" | ❌ Fails |
"ab2c" | ✅ Passes |
"ab-c" | ❌ Fails |
Checks if the String contains only unicode letters, digits, empty strings or spaces.
Behavior:
| Value | Result |
|---|---|
null | ❌ Fails |
"" | ✅ Passes |
" " | ✅ Passes |
"abc" | ✅ Passes |
"ab c" | ✅ Passes |
"ab2c" | ✅ Passes |
"ab-c" | ❌ Fails |
Checks if the String contains only Unicode letters and space (" ").
Behavior:
| Value | Result |
|---|---|
null | ❌ Fails |
"" | ✅ Passes |
" " | ✅ Passes |
"abc" | ✅ Passes |
"ab c" | ✅ Passes |
"ab1c" | ❌ Fails |
"ab-c" | ❌ Fails |
Checks if the String is printable (ASCII printable characters).
Behavior:
| Value | Result |
|---|---|
null | ❌ Fails |
"" | ✅ Passes |
" " | ✅ Passes |
"\u0020" | ✅ Passes |
"\u007e" | ❌ Fails |
"G\u00fclc\u00fc" | ❌ Fails |
Check if the Date is before the given date value.
The annotation supports a second property format that by default is "yyyy-MM-dd'T'HH:mm:ss.SSSZ".
@Data class BeforeBean { @Before(value = "2018-12-01", format = "yyyy-MM-dd") private Date isBefore = new Date(1522399999911L); // Passes // Date = 2018-03-30 }Checks if the String is empty "", null or whitespace(s) " " only.
Behavior:
| Value | Result |
|---|---|
null | ✅ Passes |
"" | ✅ Passes |
" " | ✅ Passes |
"abc" | ❌ Fails |
" abc " | ❌ Fails |
Checks if the String is a valid credit card number. Supported types are defined in the CreditCardType enum:
- AMEX:
- DINERS;
- DISCOVER;
- MASTERCARD;
- VISA;
- VPAY;
- ALL.
Multiple credit card types can be supplied to the @CC annotation.
@Data class Account { @CC({ AMEX, VISA }) // AMEX or VISA private String ccNumber; }Multiple credit card types can be used.
Checks if the String endsWith a list of given suffix(es). If multiple suffixes are supplied, the relationship between them is OR(eg.: endsWith(prefix1) OR endsWith(prefix2) OR ...).
The annotation supports a second property ignoreCase that by default is false.
Behavior (ignoreCase==false):
| Value | Suffix | Result |
|---|---|---|
null | "abc" | ❌ Fails |
"abcdef" | "def" | ✅ Passes |
"ABCDEF" | "def" | ❌ Fails |
"ABCDEF" | "" | ✅ Passes |
Behavior (ignoreCase==true)
| Value | Suffix | Result |
|---|---|---|
null | "abc" | ❌ Fails |
"abcdef" | "def" | ✅ Passes |
"ABCDEF" | "def" | ✅ Passes |
"ABCDEF" | "" | ✅ Passes |
@Data @AllArgsConstructor @NoArgsConstructor class SomeStrings { private List<@EndsWith({"1", "2"}) String> someStrings; }In the above example we validate all the contents of someStrings so that they end with either 1 or 2.
Tests if an object is instance of the supplied classes.
@Data class Animal {} @Data class Dog extends Animal {} @Data class Cat extends Animal {} @Data class Horse extends Animal {} @Data @AllArgsConstructor class Pets { /** This should contain only Cats and Dogs as pets, and doesn't contain null */ List<@NotNull @InstanceOf({Dog.class, Cat.class}) Animal> pets; }In order to test the above code we need something like this:
Animal aDog = new Dog(); Animal aCat = new Cat(); Pets pets = new Pets(asList(aDog, aCat)); ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); Set<ConstraintViolation<Pets>> validations = validator.validate(pets); // Should return 0 because the Pets class doesn't have any validation issues. System.out.println(validations.size());Checks if the given string is a valid IPv4 address.
This is implemented using InetAddressValidator.class from Apache Common Validator.
Checks if the given string is a valid IPv6 address.
This is implemented using InetAddressValidator.class from Apache Common Validator.
Checks if the given string is formatted as a date.
@Data class IsDateBean { @IsDate("yyyy-MM-dd") private String isDate = "2018-12-01"; // Passes }Checks if the String contains only lowercase letters.
Behavior:
| Value | Result |
|---|---|
null | ❌ Fails |
"" | ❌ Fails |
" " | ❌ Fails |
"abc" | ✅ Passes |
"abC" | ❌ Fails |
"ab c" | ❌ Fails |
"ab1c" | ❌ Fails |
"ab-c" | ❌ Fails |
Checks whether the annotated value is higher than or equal to the specified minimum.
@Data class MinDigitsDoubleBean { @MinDigits(value = "10.5") private Double isOk = new Double(11.0); // Passes @MinDigits(value = "10.5") private Double isKo = new Double(10.0); // Do not Pass }Double
TODO Add support for more types
Checks whether the annotated value is less than or equal to the specified maximum.
@Data class MaxDigitsDoubleBean { @MaxDigits(value = "10.5") private Double isKo = new Double(11.0); // Do not Pass @MaxDigits(value = "10.5") private Double isOk = new Double(10.0); // Passes }Double
TODO Add support for more types
Test if an object is not an instance of any of the supplied classes.
@Data class Animal {} @Data class Dog extends Animal {} @Data class Cat extends Animal {} @Data class Horse extends Animal {} @Data @AllArgsConstructor class Horses { /** This should contain only horses and doesn't contain NULL */ List<@NotNull @NotInstanceOf({Dog.class, Cat.class}) Animal> horses; }Checks if a String contains only Unicode digits. A decimal point is not an unicode digit and thus, the validation fails.
Behavior:
| Value | Result |
|---|---|
null | ❌ Fails |
"" | ❌ Fails |
" " | ❌ Fails |
"123" | ✅ Passes |
"\u0967\u0968\u0969" | ✅ Passes |
"12 3" | ❌ Fails |
"12a3" | ❌ Fails |
"12-3" | ❌ Fails |
Check if the String can be parsed to a number. The annotations accepts the type of parsing you want to perform as an input parameter.
For example if you want to parse it Integer, @Parseable(TO_INT) should be used.
All the possible parsing strategies accepted are described in the enum ParseableType. It currently supports:
TO_SHORTTO_INTTO_LONGTO_FLOATTO_DOUBLE
Check if a String is a valid password - matching a set of constraints.
containsUpperCase() default true- Needs to contain at least an Uppercase letter;boolean containsLowerCase() default true- Needs to contain at least a Lowercase letter;boolean containsSpecialChar() default true- Needs to contain at least one special character;boolean containsDigits() default true- Needs to contain at least one digit;boolean allowSpace() default false- Password can contain spaces;int minSize() default 8- The min size of the password;int maxSize() default 32- The maximum size of the password;
Checks if the Character is contained in a given array (char[]) of values.
In the following example we test if the field aOrBOrC is either 'a', 'b' or 'c'.
@Data class { @OneOfChars({'a', 'b', 'c'}) private Character aOrBOrC; }Check if the Double is contained in a given array (double[]) of values.
In the following example we test if the field value is either 1.0 or 2.0.
@Data class { @OneOfDoubles({1.0, 2.0}) private Double value; }Check if the Integer is contained in a given array (int[]) of values.
In the following example we test if the field value is either 1 or 2.
@Data class { @OneOfIntegers({1, 2}) private Integer value; }Check if the Long is contained in a given array (long[]) of values.
Checks if the String is contained in a given array (String[]) of values.
In the following example we check if the value returned by the getValue() getter is either "A", "B" or "C".
class Test { @OneOfStrings({ "A" , "B", "C"}) private String getValue() { return /***/ } }Checks if a String starts with the specified prefix(es).
The annotation supports a second property ignoreCase that by default is false.
Behavior (ignoreCase==false):
| Value | Prefix | Result |
|---|---|---|
null | "abc" | ❌ Fails |
"abcdef" | "abc" | ✅ Passes |
"ABCDEF" | "abc" | ❌ Fails |
"ABCDEF" | "" | ✅ Passes |
Behavior (ignoreCase==true):
| Value | Prefix | Result |
|---|---|---|
null | "abc" | ❌ Fails |
"abcdef" | "abc" | ✅ Passes |
"ABCDEF" | "abc" | ✅ Passes |
"ABCDEF" | "" | ✅ Passes |
@Data class Starters { private List< @StartsWith("1", "2") String> starts; } Checks if the String contains only uppercase letters.
Behavior:
| Value | Result |
|---|---|
null | ❌ Fails |
"" | ❌ Fails |
" " | ❌ Fails |
"ABC" | ✅ Passes |
"aBC" | ❌ Fails |
"A C" | ❌ Fails |
"1AB" | ❌ Fails |
"A-C" | ❌ Fails |