or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

bean-validation.mdbootstrap-configuration.mdconstraints.mdcontainer-validation.mdcustom-constraints.mdindex.mdmetadata.mdmethod-validation.mdvalidation-groups.md

method-validation.mddocs/

0

# Method Validation

1

2

Validation support for method parameters, return values, and constructor parameters with cross-parameter constraint capabilities and executable validation configuration.

3

4

## Capabilities

5

6

### Executable Validator

7

8

Interface for validating method and constructor parameters and return values.

9

10

```java { .api }

11

/**

12

* Validates parameters and return values of methods and constructors

13

* Obtained from Validator.forExecutables()

14

*/

15

interface ExecutableValidator {

16

/**

17

* Validate method parameters

18

* @param object instance on which the method is invoked (null for static methods)

19

* @param method method to validate parameters for

20

* @param parameterValues parameter values to validate

21

* @param groups validation groups to apply

22

* @return set of constraint violations

23

*/

24

<T> Set<ConstraintViolation<T>> validateParameters(

25

T object, Method method, Object[] parameterValues, Class<?>... groups);

26

27

/**

28

* Validate method return value

29

* @param object instance on which the method was invoked (null for static methods)

30

* @param method method to validate return value for

31

* @param returnValue return value to validate

32

* @param groups validation groups to apply

33

* @return set of constraint violations

34

*/

35

<T> Set<ConstraintViolation<T>> validateReturnValue(

36

T object, Method method, Object returnValue, Class<?>... groups);

37

38

/**

39

* Validate constructor parameters

40

* @param constructor constructor to validate parameters for

41

* @param parameterValues parameter values to validate

42

* @param groups validation groups to apply

43

* @return set of constraint violations

44

*/

45

<T> Set<ConstraintViolation<T>> validateConstructorParameters(

46

Constructor<? extends T> constructor, Object[] parameterValues, Class<?>... groups);

47

48

/**

49

* Validate constructor return value (the created object)

50

* @param constructor constructor that created the object

51

* @param createdObject the created object to validate

52

* @param groups validation groups to apply

53

* @return set of constraint violations

54

*/

55

<T> Set<ConstraintViolation<T>> validateConstructorReturnValue(

56

Constructor<? extends T> constructor, T createdObject, Class<?>... groups);

57

}

58

```

59

60

### Executable Validation Configuration

61

62

Enums and annotations for configuring when executable validation occurs.

63

64

```java { .api }

65

/**

66

* Defines the types of executables targeted by an operation

67

*/

68

enum ExecutableType {

69

/** No executable validation */

70

NONE,

71

72

/** Implicit configuration (provider-specific) */

73

IMPLICIT,

74

75

/** All constructors */

76

CONSTRUCTORS,

77

78

/** All methods except getters */

79

NON_GETTER_METHODS,

80

81

/** Getter methods only */

82

GETTER_METHODS,

83

84

/** All executables (constructors and methods) */

85

ALL

86

}

87

88

/**

89

* Controls executable validation on methods and constructors

90

* Can be applied to types, methods, and constructors

91

*/

92

@Target({TYPE, METHOD, CONSTRUCTOR})

93

@Retention(RUNTIME)

94

@interface ValidateOnExecution {

95

/**

96

* Define the type of executables to validate

97

* @return array of ExecutableType values

98

*/

99

ExecutableType[] type() default {ExecutableType.IMPLICIT};

100

}

101

```

102

103

### Cross-Parameter Validation

104

105

Support for constraints that validate multiple parameters together.

106

107

```java { .api }

108

/**

109

* Validation target enum for constraint validators

110

*/

111

enum ValidationTarget {

112

/** Validate the annotated element */

113

ANNOTATED_ELEMENT,

114

115

/** Validate the array of parameters (cross-parameter validation) */

116

PARAMETERS

117

}

118

119

/**

120

* Defines targets a ConstraintValidator can validate

121

* Applied to ConstraintValidator implementations

122

*/

123

@Target({TYPE})

124

@Retention(RUNTIME)

125

@interface SupportedValidationTarget {

126

/**

127

* Supported validation targets

128

* @return array of ValidationTarget values

129

*/

130

ValidationTarget[] value();

131

}

132

133

/**

134

* Defines constraint target (parameters vs return value)

135

*/

136

enum ConstraintTarget {

137

/** Let the validation engine determine the target */

138

IMPLICIT,

139

140

/** Target the method/constructor parameters */

141

PARAMETERS,

142

143

/** Target the method return value */

144

RETURN_VALUE

145

}

146

```

147

148

**Usage Examples:**

149

150

```java

151

import jakarta.validation.*;

152

import jakarta.validation.constraints.*;

153

import jakarta.validation.executable.*;

154

import java.lang.reflect.Method;

155

156

// 1. Method parameter validation

157

@ValidateOnExecution(type = ExecutableType.NON_GETTER_METHODS)

158

public class UserService {

159

160

public User createUser(

161

@NotNull @Size(min = 2, max = 50) String name,

162

@Min(18) int age,

163

@Email String email) {

164

return new User(name, age, email);

165

}

166

167

@NotNull

168

@Valid

169

public User updateUser(@NotNull @Valid User user) {

170

// Update logic

171

return user;

172

}

173

174

// Getter - validation controlled by ExecutableType.GETTER_METHODS

175

@Size(min = 1)

176

public List<User> getUsers() {

177

return userRepository.findAll();

178

}

179

}

180

181

// 2. Constructor validation

182

public class Product {

183

private String name;

184

private BigDecimal price;

185

186

public Product(

187

@NotBlank String name,

188

@DecimalMin("0.01") BigDecimal price) {

189

this.name = name;

190

this.price = price;

191

}

192

}

193

194

// 3. Cross-parameter validation

195

@Target({METHOD, CONSTRUCTOR})

196

@Retention(RUNTIME)

197

@Constraint(validatedBy = {DateRangeValidator.class})

198

public @interface ValidDateRange {

199

String message() default "End date must be after start date";

200

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

201

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

202

}

203

204

@SupportedValidationTarget(ValidationTarget.PARAMETERS)

205

public class DateRangeValidator implements ConstraintValidator<ValidDateRange, Object[]> {

206

@Override

207

public boolean isValid(Object[] parameters, ConstraintValidatorContext context) {

208

if (parameters.length != 2) {

209

return false;

210

}

211

212

LocalDate startDate = (LocalDate) parameters[0];

213

LocalDate endDate = (LocalDate) parameters[1];

214

215

if (startDate == null || endDate == null) {

216

return true; // Let @NotNull handle null values

217

}

218

219

return endDate.isAfter(startDate);

220

}

221

}

222

223

// Usage of cross-parameter validation

224

public class BookingService {

225

@ValidDateRange

226

public Booking createBooking(

227

@NotNull LocalDate startDate,

228

@NotNull LocalDate endDate,

229

@NotNull String guestName) {

230

return new Booking(startDate, endDate, guestName);

231

}

232

}

233

234

// 4. Manual validation using ExecutableValidator

235

public class ValidationExample {

236

private Validator validator;

237

private ExecutableValidator executableValidator;

238

239

public ValidationExample() {

240

ValidatorFactory factory = Validation.buildDefaultValidatorFactory();

241

this.validator = factory.getValidator();

242

this.executableValidator = validator.forExecutables();

243

}

244

245

public void validateMethodCall() throws Exception {

246

UserService userService = new UserService();

247

Method createUserMethod = UserService.class.getMethod(

248

"createUser", String.class, int.class, String.class);

249

250

// Validate parameters before method call

251

Object[] parameters = {"", 15, "invalid-email"};

252

Set<ConstraintViolation<UserService>> parameterViolations =

253

executableValidator.validateParameters(

254

userService, createUserMethod, parameters);

255

256

if (!parameterViolations.isEmpty()) {

257

System.out.println("Parameter validation failed:");

258

for (ConstraintViolation<UserService> violation : parameterViolations) {

259

System.out.println(" " + violation.getPropertyPath() + ": " +

260

violation.getMessage());

261

}

262

return;

263

}

264

265

// Call method

266

User result = userService.createUser("Alice", 25, "alice@example.com");

267

268

// Validate return value

269

Set<ConstraintViolation<UserService>> returnValueViolations =

270

executableValidator.validateReturnValue(

271

userService, createUserMethod, result);

272

273

if (!returnValueViolations.isEmpty()) {

274

System.out.println("Return value validation failed:");

275

for (ConstraintViolation<UserService> violation : returnValueViolations) {

276

System.out.println(" " + violation.getMessage());

277

}

278

}

279

}

280

281

public void validateConstructor() throws Exception {

282

Constructor<Product> constructor = Product.class.getConstructor(

283

String.class, BigDecimal.class);

284

285

// Validate constructor parameters

286

Object[] parameters = {"", new BigDecimal("-1.00")};

287

Set<ConstraintViolation<Product>> violations =

288

executableValidator.validateConstructorParameters(constructor, parameters);

289

290

if (!violations.isEmpty()) {

291

System.out.println("Constructor parameter validation failed:");

292

for (ConstraintViolation<Product> violation : violations) {

293

System.out.println(" " + violation.getPropertyPath() + ": " +

294

violation.getMessage());

295

}

296

return;

297

}

298

299

// Create object

300

Product product = constructor.newInstance("Valid Product", new BigDecimal("29.99"));

301

302

// Validate created object

303

Set<ConstraintViolation<Product>> objectViolations =

304

executableValidator.validateConstructorReturnValue(constructor, product);

305

306

if (objectViolations.isEmpty()) {

307

System.out.println("Product created successfully");

308

}

309

}

310

}

311

312

// 5. Configuration at class and method level

313

@ValidateOnExecution(type = {ExecutableType.CONSTRUCTORS, ExecutableType.NON_GETTER_METHODS})

314

public class OrderService {

315

316

// This constructor will be validated (due to class-level annotation)

317

public OrderService(@NotNull String serviceName) {

318

// Constructor logic

319

}

320

321

// This method will be validated (due to class-level annotation)

322

public Order processOrder(@NotNull @Valid Order order) {

323

return order;

324

}

325

326

// Override class-level setting - no validation for this method

327

@ValidateOnExecution(type = ExecutableType.NONE)

328

public void internalMethod(String param) {

329

// Internal method with no validation

330

}

331

332

// This getter will NOT be validated (not included in class-level annotation)

333

public String getServiceName() {

334

return "OrderService";

335

}

336

}

337

```