/java-bean-validation-extension

A library that extends the Java Bean Validation with additional @Annotations.

Primary LanguageJavaApache License 2.0Apache-2.0

java-bean-validation-extension (JBVExt)

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:

Installing the library

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'

Who is using jbvext ?

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.

Additional supported annotations

@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.

@After

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".

Example

@Data
class AfterBean {
    @After(value = "2018-01-01", format = "yyyy-MM-dd")
    private Date isAfter = new Date(1522399999911L); // Passes // Date = 2018-03-30
}

@Alpha

Check if the String contains only unicode letters.

Behavior:

Value Result
null ❌ Fails
"" ❌ Fails
" " ❌ Fails
"abc" ✅ Passes
"ab2c" ❌ Fails
"ab-c" ❌ Fails

Example

@Data
class TestAlpha {
    @Alpha
    private String alpha = "abc";

    @Alpha /** Will fail */
    private String nonAlpha = "pr�s-*";
}

@Alphanumeric

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

@AlphanumericSpace

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

@AlphaSpace

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

@AsciiPrintable

Checks if the String is printable (ASCII printable characters).

Behavior:

Value Result
null ❌ Fails
"" ✅ Passes
" " ✅ Passes
"\u0020" ✅ Passes
"\u007e" ❌ Fails
"G\u00fclc\u00fc" ❌ Fails

@Before

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".

Example

@Data
class BeforeBean {
    @Before(value = "2018-12-01", format = "yyyy-MM-dd")
    private Date isBefore = new Date(1522399999911L); // Passes // Date = 2018-03-30
}

@Blank

Checks if the String is empty "", null or whitespace(s) " " only.

Behavior:

Value Result
null ✅ Passes
"" ✅ Passes
" " ✅ Passes
"abc" ❌ Fails
" abc " ❌ Fails

@CC

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.

Example

@Data
class Account {
    @CC({ AMEX, VISA }) // AMEX or VISA
    private String ccNumber;
}

Multiple credit card types can be used.

@EndsWith

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

Example

@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.

@InstanceOf

Tests if an object is instance of the supplied classes.

Examples

@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());

@IPv4

Checks if the given string is a valid IPv4 address.

This is implemented using InetAddressValidator.class from Apache Common Validator.

@IPv6

Checks if the given string is a valid IPv6 address.

This is implemented using InetAddressValidator.class from Apache Common Validator.

@IsDate

Checks if the given string is formatted as a date.

Example

@Data
class IsDateBean {
    @IsDate("yyyy-MM-dd")
    private String isDate = "2018-12-01"; // Passes
}

@LowerCase

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

@MinDigits

Checks whether the annotated value is higher than or equal to the specified minimum.

Example

@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
}

Supported data types

Double

TODO Add support for more types

@MaxDigits

Checks whether the annotated value is less than or equal to the specified maximum.

Example

@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
}

Supported data types

Double

TODO Add support for more types

@NotInstanceOf

Test if an object is not an instance of any of the supplied classes.

Example

@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;
}

@Numeric

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

@Parseable

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_SHORT
  • TO_INT
  • TO_LONG
  • TO_FLOAT
  • TO_DOUBLE

@Password

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;

@OneOfChars

Checks if the Character is contained in a given array (char[]) of values.

Example

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;
}

@OneOfDoubles

Check if the Double is contained in a given array (double[]) of values.

Example

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;
}

@OneOfIntegers

Check if the Integer is contained in a given array (int[]) of values.

Example

In the following example we test if the field value is either 1 or 2.

@Data
class {
    @OneOfIntegers({1, 2})
    private Integer value;
}

@OneOfLongs

Check if the Long is contained in a given array (long[]) of values.

@OneOfStrings

Checks if the String is contained in a given array (String[]) of values.

Example

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 /***/ }
}

@StartsWith

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

Example

@Data
class Starters {
    private List< @StartsWith("1", "2") String> starts;
} 

@UpperCase

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