Java – Use Annotation to create Custom Constraint

Imagine, given a situation where you want to check if a required String field whether has emptied value or not. The simplest way is to use if keyword to check whether a given field which its type is String whether is emptied or null.

if (("").equals(userModel.getFirstName())){

In addition to the above-mentioned method, one can use annotation to do validation.

  1. Create a Custom Annotation
    import java.lang.annotation.*;
    public @interface Required {
  3. Create a Java Bean
    public class UserModel implements Serializable {
    	private static final long serialVersionUID = -4469704917708123018L;
    	private long id = 0;
    	private String firstName = "";
    	private String lastName = "";
    	public long getId() {
    		return id;
    	public void setId(long id) { = id;
    	public String getFirstName() {
    		return firstName;
    	public void setFirstName(String firstName) {
    		this.firstName = firstName;
    	public String getLastName() {
    		return lastName;
    	public void setLastName(String lastName) {
    		this.lastName = lastName;

    In this example, I m going to make onlylastName as a required field. Which means the value of lastName should not be emptied.

  5. A Repository Class which contains Validator
    import java.lang.reflect.Field;
    public class UserRepository {
    	public static void register(UserModel userModel, ValidationMode validationMode) {
    		if (null  == userModel) {
    		if (validationMode == ValidationMode.BRANCHING) {
    		if (validationMode == ValidationMode.ANNOTATION) {
    	public static void validateWithBranching(UserModel userModel) {
    		if (("").equals(userModel.getFirstName())) {
    			throw new IllegalArgumentException("First Name is required");
    		if (("").equals(userModel.getLastName())) {
    			throw new IllegalArgumentException("Last Name is required");
    	public static void validateWithAnnotation(UserModel userModel) {
    		final Field[] modelFields = userModel.getClass().getDeclaredFields();
            for (Field modelField : modelFields) {
            	if (modelField.isAnnotationPresent(Required.class)) {
            		try {
            			String value = (String) modelField.get(userModel);
            			if ("".equals(value)) {
                            throw new IllegalArgumentException(modelField + " is required");
            		catch(IllegalAccessException  ex) {

    The main points of this class I would like to emphasize are the following:

    • userModel.getClass().getDeclaredFields()the getClass method returns an instance of Class, which has a method called getDeclaredFields that returns all attributes (even private) of this class.
    • modelField.isAnnotationPresent(Required.class)as the method name explains, this is where it’s verified the presence of the Required annotation for each attribute of the model being validated.
    • modelField.setAccessible(true)this makes a private field accessible, meaning we can read or change itsvalue.
    • modelField.get(userModel)it returns the value of the modelField attribute in any object instance
  7. Testing the codes
  8. UserRepositoryTest
    import static org.junit.jupiter.api.Assertions.assertThrows;
    import org.junit.jupiter.api.BeforeAll;
    import org.junit.jupiter.api.Test;
    class UserRepositoryTest {
    	static UserModel userModel;
    	static void init() {
    		userModel = new UserModel();
    	void testValidateWithBranchingMissingValue() {
    		assertThrows(IllegalArgumentException.class, () -> {
    			UserRepository.register(userModel, ValidationMode.BRANCHING);
    	void testValidateWithAnnotationMissingValue() {
    		assertThrows(IllegalArgumentException.class, () -> {
    			UserRepository.register(userModel, ValidationMode.ANNOTATION);


Java Custom Annotations
Java Reflection API

Source Codes


Author: Wu Chia Chong

My main areas of interest are software architectures and software design methods, patterns, and new trends in software development.