@@ -165,27 +165,15 @@ protected void processConstraintViolations(Set<ConstraintViolation<Object>> viol
165
165
String nestedField = bindingResult .getNestedPath () + field ;
166
166
if (nestedField .isEmpty ()) {
167
167
String [] errorCodes = bindingResult .resolveMessageCodes (errorCode );
168
- ObjectError error = new ObjectError (
169
- errors .getObjectName (), errorCodes , errorArgs , violation .getMessage ()) {
170
- @ Override
171
- public boolean shouldRenderDefaultMessage () {
172
- return requiresMessageFormat (violation );
173
- }
174
- };
175
- error .wrap (violation );
168
+ ObjectError error = new ViolationObjectError (
169
+ errors .getObjectName (), errorCodes , errorArgs , violation , this );
176
170
bindingResult .addError (error );
177
171
}
178
172
else {
179
173
Object rejectedValue = getRejectedValue (field , violation , bindingResult );
180
174
String [] errorCodes = bindingResult .resolveMessageCodes (errorCode , field );
181
- FieldError error = new FieldError (errors .getObjectName (), nestedField ,
182
- rejectedValue , false , errorCodes , errorArgs , violation .getMessage ()) {
183
- @ Override
184
- public boolean shouldRenderDefaultMessage () {
185
- return requiresMessageFormat (violation );
186
- }
187
- };
188
- error .wrap (violation );
175
+ FieldError error = new ViolationFieldError (errors .getObjectName (), nestedField ,
176
+ rejectedValue , errorCodes , errorArgs , violation , this );
189
177
bindingResult .addError (error );
190
178
}
191
179
}
@@ -307,29 +295,6 @@ protected MessageSourceResolvable getResolvableField(String objectName, String f
307
295
return new DefaultMessageSourceResolvable (codes , field );
308
296
}
309
297
310
- /**
311
- * Indicate whether this violation's interpolated message has remaining
312
- * placeholders and therefore requires {@link java.text.MessageFormat}
313
- * to be applied to it. Called for a Bean Validation defined message
314
- * (coming out {@code ValidationMessages.properties}) when rendered
315
- * as the default message in Spring's MessageSource.
316
- * <p>The default implementation considers a Spring-style "{0}" placeholder
317
- * for the field name as an indication for {@link java.text.MessageFormat}.
318
- * Any other placeholder or escape syntax occurrences are typically a
319
- * mismatch, coming out of regex pattern values or the like. Note that
320
- * standard Bean Validation does not support "{0}" style placeholders at all;
321
- * this is a feature typically used in Spring MessageSource resource bundles.
322
- * @param violation the Bean Validation constraint violation, including
323
- * BV-defined interpolation of named attribute references in its message
324
- * @return {@code true} if {@code java.text.MessageFormat} is to be applied,
325
- * or {@code false} if the violation's message should be used as-is
326
- * @since 5.1.8
327
- * @see #getArgumentsForConstraint
328
- */
329
- protected boolean requiresMessageFormat (ConstraintViolation <?> violation ) {
330
- return violation .getMessage ().contains ("{0}" );
331
- }
332
-
333
298
/**
334
299
* Extract the rejected value behind the given constraint violation,
335
300
* for exposure through the Spring errors representation.
@@ -354,6 +319,33 @@ protected Object getRejectedValue(String field, ConstraintViolation<Object> viol
354
319
return invalidValue ;
355
320
}
356
321
322
+ /**
323
+ * Indicate whether this violation's interpolated message has remaining
324
+ * placeholders and therefore requires {@link java.text.MessageFormat}
325
+ * to be applied to it. Called for a Bean Validation defined message
326
+ * (coming out {@code ValidationMessages.properties}) when rendered
327
+ * as the default message in Spring's MessageSource.
328
+ * <p>The default implementation considers a Spring-style "{0}" placeholder
329
+ * for the field name as an indication for {@link java.text.MessageFormat}.
330
+ * Any other placeholder or escape syntax occurrences are typically a
331
+ * mismatch, coming out of regex pattern values or the like. Note that
332
+ * standard Bean Validation does not support "{0}" style placeholders at all;
333
+ * this is a feature typically used in Spring MessageSource resource bundles.
334
+ * @param violation the Bean Validation constraint violation, including
335
+ * BV-defined interpolation of named attribute references in its message
336
+ * @return {@code true} if {@code java.text.MessageFormat} is to be applied,
337
+ * or {@code false} if the violation's message should be used as-is
338
+ * @since 5.1.8
339
+ * @see #getArgumentsForConstraint
340
+ */
341
+ protected boolean requiresMessageFormat (ConstraintViolation <?> violation ) {
342
+ return containsSpringStylePlaceholder (violation .getMessage ());
343
+ }
344
+
345
+ private static boolean containsSpringStylePlaceholder (@ Nullable String message ) {
346
+ return (message != null && message .contains ("{0}" ));
347
+ }
348
+
357
349
358
350
//---------------------------------------------------------------------
359
351
// Implementation of JSR-303 Validator interface
@@ -436,6 +428,71 @@ public Object[] getArguments() {
436
428
public String getDefaultMessage () {
437
429
return this .resolvableString ;
438
430
}
431
+
432
+ @ Override
433
+ public String toString () {
434
+ return this .resolvableString ;
435
+ }
436
+ }
437
+
438
+
439
+ /**
440
+ * Subclass of {@code ObjectError} with Spring-style default message rendering.
441
+ */
442
+ @ SuppressWarnings ("serial" )
443
+ private static class ViolationObjectError extends ObjectError implements Serializable {
444
+
445
+ @ Nullable
446
+ private transient SpringValidatorAdapter adapter ;
447
+
448
+ @ Nullable
449
+ private transient ConstraintViolation <?> violation ;
450
+
451
+ public ViolationObjectError (String objectName , String [] codes , Object [] arguments ,
452
+ ConstraintViolation <?> violation , SpringValidatorAdapter adapter ) {
453
+
454
+ super (objectName , codes , arguments , violation .getMessage ());
455
+ this .adapter = adapter ;
456
+ this .violation = violation ;
457
+ wrap (violation );
458
+ }
459
+
460
+ @ Override
461
+ public boolean shouldRenderDefaultMessage () {
462
+ return (this .adapter != null && this .violation != null ?
463
+ this .adapter .requiresMessageFormat (this .violation ) :
464
+ containsSpringStylePlaceholder (getDefaultMessage ()));
465
+ }
466
+ }
467
+
468
+
469
+ /**
470
+ * Subclass of {@code FieldError} with Spring-style default message rendering.
471
+ */
472
+ @ SuppressWarnings ("serial" )
473
+ private static class ViolationFieldError extends FieldError implements Serializable {
474
+
475
+ @ Nullable
476
+ private transient SpringValidatorAdapter adapter ;
477
+
478
+ @ Nullable
479
+ private transient ConstraintViolation <?> violation ;
480
+
481
+ public ViolationFieldError (String objectName , String field , @ Nullable Object rejectedValue , String [] codes ,
482
+ Object [] arguments , ConstraintViolation <?> violation , SpringValidatorAdapter adapter ) {
483
+
484
+ super (objectName , field , rejectedValue , false , codes , arguments , violation .getMessage ());
485
+ this .adapter = adapter ;
486
+ this .violation = violation ;
487
+ wrap (violation );
488
+ }
489
+
490
+ @ Override
491
+ public boolean shouldRenderDefaultMessage () {
492
+ return (this .adapter != null && this .violation != null ?
493
+ this .adapter .requiresMessageFormat (this .violation ) :
494
+ containsSpringStylePlaceholder (getDefaultMessage ()));
495
+ }
439
496
}
440
497
441
498
}
0 commit comments