SuperAPI AI Directory

ddd4j-validation

Coding & development

View repository

Updated 10-16 05:47

About this skill

DDD4J Custom Validation Rules

Code the usage rules for the four custom Bean Validation constraints in DDD4J projects. LLMs don't know these constraints exist and will write their own validation logic.

Why this skill is needed

LLMs will use @Pattern(regexp="^1[3-9]\\d{9}$") to validate phone numbers—DDD4J has @PhoneNumber(based on libphonenumber, supports internationalization). LLMs will use @DateFormat to validate dates—DDD4J has @StringDateValue(empty strings silently pass). LLMs are completely unaware of these custom constraints.

Capability Boundaries

✅ Strong Suits

  1. @AllowedValues — String array whitelist validation, supports nullable
  2. @PhoneNumber — Google libphonenumber phone number validation
  3. @NumberValue — Regex numeric format validation
  4. @StringDateValue — Date string format validation (empty strings pass)

❌ Out of Scope

  1. Entity definition / return value conventions → ddd4j-core
  2. Jackson serialization validation → ddd4j-jackson

The mistakes LLMs make most often

# Mistake Correct approach
1 @Pattern(regexp="1[3-9]\\d{9}") to validate phone numbers Use @PhoneNumber(libphonenumber, internationalization)
2 @DateTimeFormat to validate dates Use @StringDateValue(format="yyyy-MM-dd HH:mm:ss")
3 Custom Validator classes for validation Put validation annotations on Param/DTO fields
4 Passing an empty string to a @StringDateValue field Empty strings silently pass, it is not a validation failure
5 Not writing the message attribute All custom constraints must explicitly specify message
6 Use @NotEmpty instead of @AllowedValues.nullable=false nullable controls null value behavior

Core Rules Quick Reference

// ✅ 正确:四个自定义约束

// @AllowedValues — 白名单校验
public class UserParam extends BaseParam {
    @AllowedValues(values = {"MALE", "FEMALE", "OTHER"}, nullable = false,
        message = "性别必须为 MALE/FEMALE/OTHER 之一")
    private String gender;

    @AllowedValues(values = {"ACTIVE", "INACTIVE"}, nullable = true,
        message = "状态必须为 ACTIVE/INACTIVE")
    private String status;  // nullable=true → 空值通过校验
}

// @PhoneNumber — 手机号校验(libphonenumber)
public class RegisterParam extends BaseParam {
    @PhoneNumber(lang = "CN", message = "手机号格式不正确")
    private String phone;

    @PhoneNumber(lang = "US", message = "Invalid US phone number")
    private String usPhone;
}

// @NumberValue — 数字格式
public class IdParam {
    @NumberValue(regex = "^[0-9\\-]+$", message = "ID只能包含数字和横线")
    private String id;
}

// @StringDateValue — 日期字符串
public class DateParam {
    @StringDateValue(format = "yyyy-MM-dd HH:mm:ss", message = "日期格式错误")
    private String beginTime;   // "" 空字符串 → 静默通过
    // SimpleDateFormat.setLenient(false) → 严格模式
}

Gotchas

  1. @StringDateValue empty strings silently pass — Null values do not trigger validation, needs to be combined with @NotEmpty
  2. All custom constraints must provide message — Validator disableDefaultConstraintViolation disables the default message
  3. @PhoneNumber depends on libphonenumber — Requires importing com.googlecode.libphonenumber
  4. @AllowedValues.nullable=true allows both null and empty strings to pass — nullable=false does not allow null values to pass
  5. @NumberValue default regex ^[0-9\\-]+$ — Only allows digits and hyphens
  6. Put validation annotations on Param/DTO — Do not create standalone Validator classes
  7. @StringDateValue uses strict mode — SimpleDateFormat.setLenient(false), non-strict dates do not pass

Data Privacy

This skill does not collect, store, or transmit any user data.