Skip to content

Instantly share code, notes, and snippets.

@rponte
Last active April 13, 2025 16:29
Show Gist options
  • Select an option

  • Save rponte/b7a827224c2ac88d588c2ed6fbeefd14 to your computer and use it in GitHub Desktop.

Select an option

Save rponte/b7a827224c2ac88d588c2ed6fbeefd14 to your computer and use it in GitHub Desktop.
Bean Validation: playing a little bit with Constraint Composition

Bean Validation: Composing Constraints

We can use the Composite Constraint feature to compose many Bean Validation's annotations into a single one custom annotation/validation, as the following code:

import org.hibernate.validator.constraints.CompositionType;
import org.hibernate.validator.constraints.ConstraintComposition;
import org.hibernate.validator.constraints.br.CNPJ;
import org.hibernate.validator.constraints.br.CPF;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@CPF
@CNPJ
@ConstraintComposition(CompositionType.OR) // specifies OR as boolean operator instead of AND
@ReportAsSingleViolation // the error reports of each individual composing constraint are ignored
@Constraint(validatedBy = { }) // we don't need a validator :-)
@Documented
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CPFOrCNPJ {

    String message() default "it's not a valid CPF or CNPJ";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };

}

Here are some interesting links about this feature:

@rponte
Copy link
Author

rponte commented Mar 19, 2021

The same custom annotation in Kotlin:

import org.hibernate.validator.constraints.CompositionType
import org.hibernate.validator.constraints.ConstraintComposition
import org.hibernate.validator.constraints.br.CNPJ
import org.hibernate.validator.constraints.br.CPF
import javax.validation.Constraint
import javax.validation.Payload
import javax.validation.ReportAsSingleViolation
import kotlin.annotation.AnnotationRetention.*
import kotlin.annotation.AnnotationTarget.*
import kotlin.reflect.KClass

@CPF
@CNPJ
@ConstraintComposition(CompositionType.OR)
@ReportAsSingleViolation
@Constraint(validatedBy = [])
@MustBeDocumented
@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
annotation class CpfOrCnpj(
    val message: String = "document is not a valid CPF or CNPJ",
    val groups: Array<KClass<Any>> = [],
    val payload: Array<KClass<Payload>> = [],
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment