Fading Coder

One Final Commit for the Last Sprint

Home > Notes > Content

Enforcing Non-Negative Values with Custom Java Annotations

Notes 1

Creating Range-Constrained Numeric Annotations

Java annotations provide a powerful mechanism for embedding metadata within source code. They enable developers to specify constraints and behaviors without altering the core logic of aplications.

To enforce that numeric values remain at or above zero, we can create a custom annotation combined with runtime validation.

Defining the Constraint Annotation

A custom annotation interface is declared using the @interface keyword. For our use case, we define an annotation that specifies a minimum acceptable value:

public @interface NonNegative {
    int minValue() default 0;
}

This creates a NonNegative annotation with a configurable threshold, defaulting to zero.

Applying the Annotation

Once defined, the annotation can be applied to class fields requiring validation:

class ValueContainer {
    @NonNegative
    private int amount;
    
    public int getAmount() {
        return amount;
    }
    
    public void setAmount(int amount) {
        this.amount = amount;
    }
}

The amount field is now marked with the constraint, indicating it should not fall below the specified limit.

Implementing Validation Logic

Runtime enforcement requires a component capable of inspecting annotated elements. Using reflection, we can build a validator that checks field values against their annotations:

public class Validator {
    public static void validate(Object target) {
        Field[] fields = target.getClass().getDeclaredFields();
        
        for (Field field : fields) {
            if (field.isAnnotationPresent(NonNegative.class)) {
                NonNegative constraint = field.getAnnotation(NonNegative.class);
                int threshold = constraint.minValue();
                
                try {
                    field.setAccessible(true);
                    int currentValue = (int) field.get(target);
                    
                    if (currentValue < threshold) {
                        throw new IllegalStateException(
                            "Field '" + field.getName() + "' must be >= " + threshold
                        );
                    }
                } catch (IllegalAccessException exception) {
                    exception.printStackTrace();
                }
            }
        }
    }
}

This validator iterates through all declared fields, identifies those annotated with NonNegative, and ensures their current values meet the required condition.

Validation Example

Here's how the validation mechanism operates in practice:

public class Application {
    public static void main(String[] args) {
        ValueContainer container = new ValueContainer();
        container.setAmount(15);
        
        try {
            Validator.validate(container);
            System.out.println("Validation passed");
        } catch (IllegalStateException error) {
            System.err.println("Validation failed: " + error.getMessage());
        }
    }
}

In this example, setting amount to a positive value results in successful validation.

Related Articles

Designing Alertmanager Templates for Prometheus Notifications

How to craft Alertmanager templates to format alert messages, improving clarity and presentation. Alertmanager uses Go’s text/template engine with additional helper functions. Alerting rules referenc...

Deploying a Maven Web Application to Tomcat 9 Using the Tomcat Manager

Tomcat 9 does not provide a dedicated Maven plugin. The Tomcat Manager interface, however, is backward-compatible, so the Tomcat 7 Maven Plugin can be used to deploy to Tomcat 9. This guide shows two...

Skipping Errors in MySQL Asynchronous Replication

When a replica halts because the SQL thread encounters an error, you can resume replication by skipping the problematic event(s). Two common approaches are available. Methods to Skip Errors 1) Skip a...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.