or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdconstraint-validation.mdconstraints.mdindex.mdmessage-interpolation.mdpath-navigation.mdprogrammatic-config.mdresource-loading.mdspi.md

programmatic-config.mddocs/

0

# Programmatic Constraint Configuration

1

2

Define constraints programmatically without annotations using a fluent API. This approach supports all constraint types including properties, methods, constructors, parameters, return values, cross-parameter constraints, and container elements with full feature parity to annotation-based configuration.

3

4

## Capabilities

5

6

### Constraint Mapping Entry Point

7

8

Create and configure constraint mappings to define validation rules programmatically.

9

10

```java { .api }

11

package org.hibernate.validator.cfg;

12

13

import java.lang.annotation.Annotation;

14

import org.hibernate.validator.cfg.context.ConstraintDefinitionContext;

15

import org.hibernate.validator.cfg.context.TypeConstraintMappingContext;

16

17

/**

18

* Represents a constraint mapping configured via programmatic API.

19

* Create via BaseHibernateValidatorConfiguration.createConstraintMapping().

20

*/

21

interface ConstraintMapping {

22

/**

23

* Start defining constraints on specified bean class.

24

* Each bean class may only be configured once within all constraint mappings.

25

*

26

* @param <C> type to be configured

27

* @param beanClass bean class on which to define constraints

28

* @return context for defining constraints on the class

29

*/

30

<C> TypeConstraintMappingContext<C> type(Class<C> beanClass);

31

32

/**

33

* Start defining ConstraintValidators for specified constraint annotation.

34

* Each constraint may only be configured once within all constraint mappings.

35

*

36

* @param <A> annotation type to be configured

37

* @param annotationClass constraint annotation class

38

* @return context for defining validators for the constraint

39

* @since 5.3

40

*/

41

<A extends Annotation> ConstraintDefinitionContext<A> constraintDefinition(Class<A> annotationClass);

42

}

43

```

44

45

**Usage Example:**

46

47

```java

48

import jakarta.validation.Validation;

49

import org.hibernate.validator.HibernateValidator;

50

import org.hibernate.validator.HibernateValidatorConfiguration;

51

import org.hibernate.validator.cfg.ConstraintMapping;

52

53

HibernateValidatorConfiguration configuration = Validation

54

.byProvider(HibernateValidator.class)

55

.configure();

56

57

// Create constraint mapping

58

ConstraintMapping mapping = configuration.createConstraintMapping();

59

60

// Configure constraints (see examples below)

61

62

// Add mapping to configuration

63

configuration.addMapping(mapping);

64

65

ValidatorFactory factory = configuration.buildValidatorFactory();

66

```

67

68

### Type-Level Configuration

69

70

Configure constraints at the class level including class-level constraints, property constraints, method constraints, and constructor constraints.

71

72

```java { .api }

73

package org.hibernate.validator.cfg.context;

74

75

import org.hibernate.validator.cfg.ConstraintDef;

76

77

/**

78

* Context for defining constraints at type level.

79

*

80

* @param <C> configured bean type

81

*/

82

interface TypeConstraintMappingContext<C> extends Constrainable<TypeConstraintMappingContext<C>>,

83

Cascadable<TypeConstraintMappingContext<C>>,

84

AnnotationIgnoreOptions<TypeConstraintMappingContext<C>>,

85

PropertyTarget {

86

87

/**

88

* Start defining constraints on a method.

89

*

90

* @param methodName method name

91

* @param parameterTypes method parameter types

92

* @return context for defining method constraints

93

*/

94

MethodConstraintMappingContext method(String methodName, Class<?>... parameterTypes);

95

96

/**

97

* Start defining constraints on a constructor.

98

*

99

* @param parameterTypes constructor parameter types

100

* @return context for defining constructor constraints

101

*/

102

ConstructorConstraintMappingContext constructor(Class<?>... parameterTypes);

103

}

104

105

/**

106

* Provides methods for configuring property-level constraints.

107

*/

108

interface PropertyTarget {

109

/**

110

* Start defining constraints on a property via field access.

111

*

112

* @param property property name

113

* @return context for defining property constraints

114

*/

115

PropertyConstraintMappingContext field(String property);

116

117

/**

118

* Start defining constraints on a property via getter method access.

119

*

120

* @param property property name

121

* @return context for defining property constraints

122

*/

123

PropertyConstraintMappingContext getter(String property);

124

}

125

```

126

127

**Important Note:** The `PropertyTarget` interface provides two distinct methods for property constraint configuration:

128

- Use `field(String property)` to apply constraints at the field level

129

- Use `getter(String property)` to apply constraints at the getter method level

130

131

There is no single `property()` method. The term "property" in method parameters refers to the JavaBean property name, while the method itself (`field` or `getter`) specifies how to access it.

132

133

**Usage Example:**

134

135

```java

136

import org.hibernate.validator.cfg.ConstraintMapping;

137

import org.hibernate.validator.cfg.defs.*;

138

139

ConstraintMapping mapping = configuration.createConstraintMapping();

140

141

// Configure type-level constraints

142

mapping.type(User.class)

143

// Add class-level constraint

144

.constraint(new ScriptAssertDef()

145

.lang("javascript")

146

.script("_this.password == _this.confirmPassword")

147

.message("Passwords must match"))

148

// Mark type for cascaded validation

149

.valid()

150

// Configure property constraints via field access

151

.field("email")

152

.constraint(new NotNullDef())

153

.constraint(new EmailDef())

154

.field("age")

155

.constraint(new MinDef().value(18))

156

.constraint(new MaxDef().value(120));

157

```

158

159

### Property-Level Configuration

160

161

Configure constraints on bean properties (fields or getter methods).

162

163

```java { .api }

164

package org.hibernate.validator.cfg.context;

165

166

/**

167

* Context for defining constraints on properties.

168

*/

169

interface PropertyConstraintMappingContext extends Constrainable<PropertyConstraintMappingContext>,

170

Cascadable<PropertyConstraintMappingContext>,

171

ContainerElementTarget,

172

AnnotationIgnoreOptions<PropertyConstraintMappingContext>,

173

PropertyTarget {

174

175

/**

176

* Move to method configuration.

177

*

178

* @param methodName method name

179

* @param parameterTypes parameter types

180

* @return method-level context

181

*/

182

MethodConstraintMappingContext method(String methodName, Class<?>... parameterTypes);

183

184

/**

185

* Move to constructor configuration.

186

*

187

* @param parameterTypes parameter types

188

* @return constructor-level context

189

*/

190

ConstructorConstraintMappingContext constructor(Class<?>... parameterTypes);

191

}

192

```

193

194

**Usage Example:**

195

196

```java

197

mapping.type(Order.class)

198

.field("items")

199

.constraint(new NotEmptyDef())

200

.constraint(new SizeDef().min(1).max(100))

201

// Configure container elements (List items)

202

.containerElementType()

203

.valid() // Cascade validation to each item

204

.field("totalAmount")

205

.constraint(new DecimalMinDef().value("0.00"))

206

.constraint(new DigitsDef().integer(10).fraction(2));

207

```

208

209

### Method and Constructor Configuration

210

211

Configure constraints on method parameters, return values, and constructors.

212

213

```java { .api }

214

package org.hibernate.validator.cfg.context;

215

216

/**

217

* Context for defining constraints on methods.

218

*/

219

interface MethodConstraintMappingContext extends Cascadable<MethodConstraintMappingContext>,

220

AnnotationIgnoreOptions<MethodConstraintMappingContext> {

221

222

/**

223

* Configure parameter constraints.

224

*

225

* @param index parameter index (0-based)

226

* @return parameter constraint context

227

*/

228

ParameterConstraintMappingContext parameter(int index);

229

230

/**

231

* Configure cross-parameter constraints.

232

*

233

* @return cross-parameter constraint context

234

*/

235

CrossParameterConstraintMappingContext crossParameter();

236

237

/**

238

* Configure return value constraints.

239

*

240

* @return return value constraint context

241

*/

242

ReturnValueConstraintMappingContext returnValue();

243

244

/**

245

* Move to another method.

246

*

247

* @param methodName method name

248

* @param parameterTypes parameter types

249

* @return method constraint context

250

*/

251

MethodConstraintMappingContext method(String methodName, Class<?>... parameterTypes);

252

253

/**

254

* Move to constructor configuration.

255

*

256

* @param parameterTypes parameter types

257

* @return constructor constraint context

258

*/

259

ConstructorConstraintMappingContext constructor(Class<?>... parameterTypes);

260

}

261

262

/**

263

* Context for defining constraints on constructors.

264

*/

265

interface ConstructorConstraintMappingContext extends Cascadable<ConstructorConstraintMappingContext>,

266

AnnotationIgnoreOptions<ConstructorConstraintMappingContext> {

267

268

/**

269

* Configure parameter constraints.

270

*

271

* @param index parameter index (0-based)

272

* @return parameter constraint context

273

*/

274

ParameterConstraintMappingContext parameter(int index);

275

276

/**

277

* Configure cross-parameter constraints.

278

*

279

* @return cross-parameter constraint context

280

*/

281

CrossParameterConstraintMappingContext crossParameter();

282

283

/**

284

* Configure return value constraints (constructor validation).

285

*

286

* @return return value constraint context

287

*/

288

ReturnValueConstraintMappingContext returnValue();

289

290

/**

291

* Move to another constructor.

292

*

293

* @param parameterTypes parameter types

294

* @return constructor constraint context

295

*/

296

ConstructorConstraintMappingContext constructor(Class<?>... parameterTypes);

297

298

/**

299

* Move to method configuration.

300

*

301

* @param methodName method name

302

* @param parameterTypes parameter types

303

* @return method constraint context

304

*/

305

MethodConstraintMappingContext method(String methodName, Class<?>... parameterTypes);

306

}

307

```

308

309

**Usage Example:**

310

311

```java

312

mapping.type(UserService.class)

313

// Configure method parameter constraints

314

.method("createUser", String.class, String.class, int.class)

315

.parameter(0) // username parameter

316

.constraint(new NotNullDef())

317

.constraint(new SizeDef().min(3).max(50))

318

.parameter(1) // email parameter

319

.constraint(new NotNullDef())

320

.constraint(new EmailDef())

321

.parameter(2) // age parameter

322

.constraint(new MinDef().value(18))

323

.returnValue() // return value constraints

324

.constraint(new NotNullDef())

325

.valid() // cascade validation

326

327

// Configure constructor constraints

328

.constructor(String.class)

329

.parameter(0)

330

.constraint(new NotBlankDef())

331

.returnValue()

332

.valid();

333

```

334

335

### Parameter and Return Value Configuration

336

337

Configure constraints on method/constructor parameters and return values.

338

339

```java { .api }

340

package org.hibernate.validator.cfg.context;

341

342

/**

343

* Context for defining constraints on parameters.

344

*/

345

interface ParameterConstraintMappingContext extends Constrainable<ParameterConstraintMappingContext>,

346

Cascadable<ParameterConstraintMappingContext>,

347

ContainerElementTarget,

348

AnnotationIgnoreOptions<ParameterConstraintMappingContext> {

349

350

/**

351

* Move to another parameter.

352

*

353

* @param index parameter index

354

* @return parameter constraint context

355

*/

356

ParameterConstraintMappingContext parameter(int index);

357

358

/**

359

* Move to cross-parameter constraints.

360

*

361

* @return cross-parameter constraint context

362

*/

363

CrossParameterConstraintMappingContext crossParameter();

364

365

/**

366

* Move to return value constraints.

367

*

368

* @return return value constraint context

369

*/

370

ReturnValueConstraintMappingContext returnValue();

371

}

372

373

/**

374

* Context for defining constraints on return values.

375

*/

376

interface ReturnValueConstraintMappingContext extends Constrainable<ReturnValueConstraintMappingContext>,

377

Cascadable<ReturnValueConstraintMappingContext>,

378

ContainerElementTarget,

379

AnnotationIgnoreOptions<ReturnValueConstraintMappingContext> {

380

381

/**

382

* Move to parameter constraints.

383

*

384

* @param index parameter index

385

* @return parameter constraint context

386

*/

387

ParameterConstraintMappingContext parameter(int index);

388

389

/**

390

* Move to cross-parameter constraints.

391

*

392

* @return cross-parameter constraint context

393

*/

394

CrossParameterConstraintMappingContext crossParameter();

395

}

396

397

/**

398

* Context for defining cross-parameter constraints.

399

*/

400

interface CrossParameterConstraintMappingContext

401

extends Constrainable<CrossParameterConstraintMappingContext> {

402

403

/**

404

* Move to parameter constraints.

405

*

406

* @param index parameter index

407

* @return parameter constraint context

408

*/

409

ParameterConstraintMappingContext parameter(int index);

410

411

/**

412

* Move to return value constraints.

413

*

414

* @return return value constraint context

415

*/

416

ReturnValueConstraintMappingContext returnValue();

417

}

418

```

419

420

**Usage Example:**

421

422

```java

423

mapping.type(Calculator.class)

424

.method("divide", double.class, double.class)

425

.parameter(0)

426

.constraint(new NotNullDef())

427

.parameter(1)

428

.constraint(new NotNullDef())

429

.constraint(new DecimalMinDef().value("0.01"))

430

.crossParameter()

431

.constraint(new ParameterScriptAssertDef()

432

.lang("javascript")

433

.script("_args[0] > _args[1]")

434

.message("Dividend must be greater than divisor"))

435

.returnValue()

436

.constraint(new NotNullDef());

437

```

438

439

### Container Element Configuration

440

441

Configure constraints on container elements (generic type arguments).

442

443

```java { .api }

444

package org.hibernate.validator.cfg.context;

445

446

/**

447

* Context for defining constraints on container elements.

448

*/

449

interface ContainerElementConstraintMappingContext extends Constrainable<ContainerElementConstraintMappingContext>,

450

Cascadable<ContainerElementConstraintMappingContext>,

451

ContainerElementTarget,

452

AnnotationIgnoreOptions<ContainerElementConstraintMappingContext> {

453

454

/**

455

* Move to another container element.

456

*

457

* @return container element constraint context

458

*/

459

ContainerElementConstraintMappingContext containerElementType();

460

461

/**

462

* Specify type argument index for nested generics.

463

*

464

* @param index type argument index

465

* @param typeArgumentIndex nested type argument index

466

* @return container element constraint context

467

*/

468

ContainerElementConstraintMappingContext containerElementType(int index, int... typeArgumentIndex);

469

}

470

471

/**

472

* Marker interface for targets that can have container element constraints.

473

*/

474

interface ContainerElementTarget {

475

/**

476

* Start configuring container element constraints.

477

*

478

* @return container element constraint context

479

*/

480

ContainerElementConstraintMappingContext containerElementType();

481

482

/**

483

* Start configuring container element constraints with type argument indices.

484

*

485

* @param index type argument index

486

* @param typeArgumentIndex nested type argument indices

487

* @return container element constraint context

488

*/

489

ContainerElementConstraintMappingContext containerElementType(int index, int... typeArgumentIndex);

490

}

491

```

492

493

**Usage Example:**

494

495

```java

496

import java.util.List;

497

import java.util.Map;

498

499

mapping.type(ShoppingCart.class)

500

// Configure constraints on List<Product> items

501

.field("items")

502

.containerElementType() // Constrain List elements

503

.constraint(new NotNullDef())

504

.valid() // Cascade to Product

505

506

// Configure constraints on Map<String, Order> values

507

.field("orders")

508

.containerElementType(0) // Map key (String)

509

.constraint(new NotBlankDef())

510

.containerElementType(1) // Map value (Order)

511

.constraint(new NotNullDef())

512

.valid() // Cascade to Order

513

514

// Configure nested generics: Map<String, List<Item>>

515

.field("itemsByCategory")

516

.containerElementType(1, 0) // Map value's List elements

517

.valid();

518

```

519

520

### Constraint and Cascading Configuration

521

522

Core interfaces for adding constraints and configuring cascaded validation.

523

524

```java { .api }

525

package org.hibernate.validator.cfg.context;

526

527

import jakarta.validation.groups.Default;

528

import org.hibernate.validator.cfg.ConstraintDef;

529

530

/**

531

* Interface for elements that can have constraints applied.

532

*

533

* @param <C> context type for method chaining

534

*/

535

interface Constrainable<C extends Constrainable<C>> {

536

/**

537

* Add a constraint to this element.

538

*

539

* @param <A> constraint definition type

540

* @param definition constraint definition

541

* @return this context for method chaining

542

*/

543

<A extends ConstraintDef<?, ?>> C constraint(A definition);

544

}

545

546

/**

547

* Interface for elements that can be marked for cascaded validation.

548

*

549

* @param <C> context type for method chaining

550

*/

551

interface Cascadable<C extends Cascadable<C>> {

552

/**

553

* Mark this element for cascaded validation.

554

* Equivalent to @Valid annotation.

555

*

556

* @return this context for method chaining

557

*/

558

C valid();

559

560

/**

561

* Define group conversion for cascaded validation.

562

* When validating with fromGroup, validate cascaded object with toGroup.

563

*

564

* @param fromGroup source group

565

* @param toGroup target group

566

* @return this context for method chaining

567

*/

568

GroupConversionTargetContext<C> convertGroup(Class<?> fromGroup);

569

}

570

571

/**

572

* Context for defining group conversion target.

573

*

574

* @param <C> context type for method chaining

575

*/

576

interface GroupConversionTargetContext<C> {

577

/**

578

* Specify target group for group conversion.

579

*

580

* @param toGroup target group

581

* @return parent context

582

*/

583

C to(Class<?> toGroup);

584

}

585

586

/**

587

* Interface for controlling which annotations to ignore.

588

*

589

* @param <C> context type for method chaining

590

*/

591

interface AnnotationIgnoreOptions<C extends AnnotationIgnoreOptions<C>> {

592

/**

593

* Ignore all constraint annotations on this element.

594

*

595

* @return this context for method chaining

596

*/

597

C ignoreAnnotations();

598

599

/**

600

* Ignore specific annotations on this element.

601

*

602

* @param ignoreAnnotations true to ignore annotations

603

* @return this context for method chaining

604

*/

605

C ignoreAnnotations(boolean ignoreAnnotations);

606

}

607

```

608

609

**Usage Example:**

610

611

```java

612

// Group conversion example

613

interface PurchaseGroup {}

614

interface OrderGroup {}

615

616

mapping.type(Order.class)

617

.field("customer")

618

.valid()

619

.convertGroup(Default.class).to(PurchaseGroup.class)

620

.convertGroup(PurchaseGroup.class).to(OrderGroup.class);

621

622

// Ignoring annotations example

623

mapping.type(LegacyEntity.class)

624

.field("oldField")

625

.ignoreAnnotations() // Ignore any @NotNull, @Size, etc. on this field

626

.constraint(new LengthDef().min(10).max(100)); // Use programmatic constraint instead

627

```

628

629

### Constraint Definition Types

630

631

Type-safe constraint definition classes for programmatic configuration.

632

633

```java { .api }

634

package org.hibernate.validator.cfg;

635

636

import jakarta.validation.Payload;

637

import java.lang.annotation.Annotation;

638

639

/**

640

* Base class for annotation definitions in programmatic API.

641

*

642

* @param <C> concrete subtype (self-referencing generic)

643

* @param <A> annotation type being defined

644

*/

645

abstract class AnnotationDef<C extends AnnotationDef<C, A>, A extends Annotation> {

646

// Base annotation definition functionality

647

}

648

649

/**

650

* Base class for all constraint definition types.

651

*

652

* @param <C> concrete constraint definition type

653

* @param <A> constraint annotation type

654

*/

655

abstract class ConstraintDef<C extends ConstraintDef<C, A>, A extends Annotation>

656

extends AnnotationDef<C, A> {

657

658

/**

659

* Set constraint message.

660

*

661

* @param message constraint message

662

* @return this definition for method chaining

663

*/

664

C message(String message);

665

666

/**

667

* Set validation groups.

668

*

669

* @param groups validation groups

670

* @return this definition for method chaining

671

*/

672

C groups(Class<?>... groups);

673

674

/**

675

* Set payload.

676

*

677

* @param payload payload classes

678

* @return this definition for method chaining

679

*/

680

C payload(Class<? extends Payload>... payload);

681

}

682

683

/**

684

* Generic constraint definition for constraints without specific type-safe class.

685

* Allows configuring any constraint annotation type.

686

*

687

* @param <A> constraint annotation type

688

*/

689

class GenericConstraintDef<A extends Annotation> extends ConstraintDef<GenericConstraintDef<A>, A> {

690

/**

691

* Set any annotation parameter.

692

*

693

* @param name parameter name

694

* @param value parameter value

695

* @return this definition for method chaining

696

*/

697

GenericConstraintDef<A> param(String name, Object value);

698

}

699

```

700

701

**Type-safe Constraint Definition Classes:**

702

703

All standard Jakarta Validation and Hibernate Validator constraints have corresponding type-safe definition classes in `org.hibernate.validator.cfg.defs` package. The following table shows the mapping between constraint annotations and their programmatic definition classes:

704

705

**Jakarta Validation Constraints:**

706

- `@AssertFalse``AssertFalseDef`

707

- `@AssertTrue``AssertTrueDef`

708

- `@DecimalMax``DecimalMaxDef`

709

- `@DecimalMin``DecimalMinDef`

710

- `@Digits``DigitsDef`

711

- `@Email``EmailDef`

712

- `@Future``FutureDef`

713

- `@FutureOrPresent``FutureOrPresentDef`

714

- `@Max``MaxDef`

715

- `@Min``MinDef`

716

- `@Negative``NegativeDef`

717

- `@NegativeOrZero``NegativeOrZeroDef`

718

- `@NotBlank``NotBlankDef`

719

- `@NotEmpty``NotEmptyDef`

720

- `@NotNull``NotNullDef`

721

- `@Null``NullDef`

722

- `@Past``PastDef`

723

- `@PastOrPresent``PastOrPresentDef`

724

- `@Pattern``PatternDef`

725

- `@Positive``PositiveDef`

726

- `@PositiveOrZero``PositiveOrZeroDef`

727

- `@Size``SizeDef`

728

729

**Hibernate Validator Constraints:**

730

- `@BitcoinAddress``BitcoinAddressDef`

731

- `@CodePointLength``CodePointLengthDef`

732

- `@ConstraintComposition``ConstraintCompositionDef`

733

- `@CreditCardNumber``CreditCardNumberDef`

734

- `@Currency``CurrencyDef`

735

- `@EAN``EANDef`

736

- `@ISBN``ISBNDef`

737

- `@Length``LengthDef`

738

- `@LuhnCheck``LuhnCheckDef`

739

- `@Mod10Check``Mod10CheckDef`

740

- `@Mod11Check``Mod11CheckDef`

741

- `@Normalized``NormalizedDef`

742

- `@ParameterScriptAssert``ParameterScriptAssertDef`

743

- `@Range``RangeDef`

744

- `@ScriptAssert``ScriptAssertDef`

745

- `@UniqueElements``UniqueElementsDef`

746

- `@URL``URLDef`

747

- `@UUID``UUIDDef`

748

- `@DurationMax``DurationMaxDef` (time package)

749

- `@DurationMin``DurationMinDef` (time package)

750

751

**Country-Specific Constraints:**

752

- `@CPF``org.hibernate.validator.cfg.defs.br.CPFDef` (Brazil)

753

- `@CNPJ``org.hibernate.validator.cfg.defs.br.CNPJDef` (Brazil)

754

- `@TituloEleitoral``org.hibernate.validator.cfg.defs.br.TituloEleitoralDef` (Brazil)

755

- `@KorRRN``org.hibernate.validator.cfg.defs.kor.KorRRNDef` (Korea)

756

- `@NIP``org.hibernate.validator.cfg.defs.pl.NIPDef` (Poland)

757

- `@PESEL``org.hibernate.validator.cfg.defs.pl.PESELDef` (Poland)

758

- `@REGON``org.hibernate.validator.cfg.defs.pl.REGONDef` (Poland)

759

- `@INN``org.hibernate.validator.cfg.defs.ru.INNDef` (Russia)

760

761

**Usage Example:**

762

763

```java

764

import org.hibernate.validator.cfg.defs.*;

765

import org.hibernate.validator.cfg.GenericConstraintDef;

766

767

// Using type-safe definition classes

768

mapping.type(Product.class)

769

.field("name")

770

.constraint(new NotBlankDef()

771

.message("Product name is required")

772

.groups(BasicGroup.class))

773

.constraint(new LengthDef()

774

.min(3)

775

.max(100));

776

777

// Using GenericConstraintDef for custom constraints

778

mapping.type(CustomEntity.class)

779

.field("code")

780

.constraint(new GenericConstraintDef<MyCustomConstraint>(MyCustomConstraint.class)

781

.param("pattern", "[A-Z]{3}-[0-9]{4}")

782

.param("allowEmpty", false)

783

.message("Invalid code format"));

784

```

785

786

### Constraint Validator Definition

787

788

Define custom constraint validators programmatically.

789

790

```java { .api }

791

package org.hibernate.validator.cfg.context;

792

793

import jakarta.validation.ConstraintValidator;

794

import java.lang.annotation.Annotation;

795

796

/**

797

* Context for defining constraint validators for a constraint annotation.

798

*

799

* @param <A> constraint annotation type

800

*/

801

interface ConstraintDefinitionContext<A extends Annotation> {

802

/**

803

* Register a constraint validator for this constraint.

804

*

805

* @param <T> validated type

806

* @param type type this validator validates

807

* @param validatorType validator class

808

* @return this context for method chaining

809

*/

810

<T> ConstraintDefinitionContext<A> validatedBy(Class<T> type,

811

Class<? extends ConstraintValidator<A, ? super T>> validatorType);

812

813

/**

814

* Register a constraint validator for this constraint (auto-detect validated type).

815

*

816

* @param validatorType validator class

817

* @return this context for method chaining

818

*/

819

ConstraintDefinitionContext<A> validatedBy(

820

Class<? extends ConstraintValidator<A, ?>> validatorType);

821

822

/**

823

* Include existing validators from annotation's @Constraint meta-annotation.

824

*

825

* @param includeExistingValidators true to include existing validators

826

* @return this context for method chaining

827

*/

828

ConstraintDefinitionContext<A> includeExistingValidators(boolean includeExistingValidators);

829

}

830

```

831

832

**Usage Example:**

833

834

```java

835

import jakarta.validation.ConstraintValidator;

836

import jakarta.validation.ConstraintValidatorContext;

837

838

// Define custom constraint annotation

839

@interface MyCustomConstraint {

840

String message() default "Invalid value";

841

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

842

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

843

}

844

845

// Define custom validator

846

class MyCustomValidator implements ConstraintValidator<MyCustomConstraint, String> {

847

@Override

848

public boolean isValid(String value, ConstraintValidatorContext context) {

849

return value != null && value.matches("[A-Z]{3}-[0-9]{4}");

850

}

851

}

852

853

// Register validator programmatically

854

ConstraintMapping mapping = configuration.createConstraintMapping();

855

856

mapping.constraintDefinition(MyCustomConstraint.class)

857

.includeExistingValidators(false) // Don't use validators from @Constraint annotation

858

.validatedBy(String.class, MyCustomValidator.class);

859

860

// Apply constraint

861

mapping.type(Product.class)

862

.field("code")

863

.constraint(new GenericConstraintDef<>(MyCustomConstraint.class));

864

```

865

866

## Complete Usage Example

867

868

```java

869

import jakarta.validation.*;

870

import org.hibernate.validator.HibernateValidator;

871

import org.hibernate.validator.HibernateValidatorConfiguration;

872

import org.hibernate.validator.cfg.ConstraintMapping;

873

import org.hibernate.validator.cfg.defs.*;

874

875

// Bootstrap configuration

876

HibernateValidatorConfiguration configuration = Validation

877

.byProvider(HibernateValidator.class)

878

.configure();

879

880

// Create constraint mapping

881

ConstraintMapping mapping = configuration.createConstraintMapping();

882

883

// Configure comprehensive constraints

884

mapping.type(User.class)

885

// Class-level constraint

886

.constraint(new ScriptAssertDef()

887

.lang("javascript")

888

.script("_this.password == _this.confirmPassword")

889

.reportOn("confirmPassword")

890

.message("Passwords must match"))

891

892

// Property constraints via field access

893

.field("username")

894

.constraint(new NotNullDef())

895

.constraint(new LengthDef().min(3).max(50))

896

.field("email")

897

.constraint(new NotNullDef())

898

.constraint(new EmailDef())

899

.field("age")

900

.constraint(new MinDef().value(18))

901

.constraint(new MaxDef().value(120))

902

.field("creditCard")

903

.constraint(new CreditCardNumberDef().ignoreNonDigitCharacters(true))

904

.field("address")

905

.valid() // Cascade validation

906

907

// Method parameter and return value constraints

908

.method("updateEmail", String.class)

909

.parameter(0)

910

.constraint(new NotNullDef())

911

.constraint(new EmailDef())

912

.returnValue()

913

.constraint(new NotNullDef())

914

915

// Constructor constraints

916

.constructor(String.class, String.class)

917

.parameter(0)

918

.constraint(new NotBlankDef())

919

.parameter(1)

920

.constraint(new NotBlankDef());

921

922

// Configure collection constraints

923

mapping.type(Order.class)

924

.field("items")

925

.constraint(new NotEmptyDef())

926

.constraint(new SizeDef().min(1).max(100))

927

.containerElementType() // Constrain list elements

928

.constraint(new NotNullDef())

929

.valid();

930

931

// Add mapping and build factory

932

configuration.addMapping(mapping);

933

ValidatorFactory factory = configuration.buildValidatorFactory();

934

Validator validator = factory.getValidator();

935

936

// Use validator

937

User user = new User();

938

Set<ConstraintViolation<User>> violations = validator.validate(user);

939

```

940