Skip to content

Commit a5988f4

Browse files
gsmetgunnarmorling
authored andcommitted
HV-1471 Properly reset the context after constraint validation
The path was properly reset but the value was not. I introduced a plain object to manage the state so that it's properly reset everywhere.
1 parent 200b020 commit a5988f4

File tree

5 files changed

+64
-15
lines changed

5 files changed

+64
-15
lines changed

engine/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ private void validateMetaConstraints(ValidationContext<?> validationContext, Val
534534
}
535535

536536
private boolean validateMetaConstraint(ValidationContext<?> validationContext, ValueContext<?, Object> valueContext, Object parent, MetaConstraint<?> metaConstraint) {
537-
PathImpl currentPath = valueContext.getPropertyPath();
537+
ValueContext.ValueState<Object> originalValueState = valueContext.getCurrentValueState();
538538
valueContext.appendNode( metaConstraint.getLocation() );
539539
boolean success = true;
540540

@@ -554,8 +554,8 @@ private boolean validateMetaConstraint(ValidationContext<?> validationContext, V
554554
validationContext.markConstraintProcessed( valueContext.getCurrentBean(), valueContext.getPropertyPath(), metaConstraint );
555555
}
556556

557-
// reset the path to the state before this call
558-
valueContext.setPropertyPath( currentPath );
557+
// reset the value context to the state before this call
558+
valueContext.resetValueState( originalValueState );
559559

560560
return success;
561561
}
@@ -569,7 +569,7 @@ private boolean validateMetaConstraint(ValidationContext<?> validationContext, V
569569
*/
570570
private void validateCascadedConstraints(ValidationContext<?> validationContext, ValueContext<?, Object> valueContext) {
571571
Validatable validatable = valueContext.getCurrentValidatable();
572-
PathImpl originalPath = valueContext.getPropertyPath();
572+
ValueContext.ValueState<Object> originalValueState = valueContext.getCurrentValueState();
573573

574574
for ( Cascadable cascadable : validatable.getCascadables() ) {
575575
valueContext.appendNode( cascadable );
@@ -597,8 +597,8 @@ private void validateCascadedConstraints(ValidationContext<?> validationContext,
597597
}
598598
}
599599

600-
// reset the path
601-
valueContext.setPropertyPath( originalPath );
600+
// reset the value context
601+
valueContext.resetValueState( originalValueState );
602602
}
603603
}
604604

engine/src/main/java/org/hibernate/validator/internal/engine/ValueContext.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,6 @@ public final Object getCurrentValidatedValue() {
137137
return currentValue;
138138
}
139139

140-
public final void setPropertyPath(PathImpl propertyPath) {
141-
this.propertyPath = propertyPath;
142-
}
143-
144140
public final void appendNode(Cascadable node) {
145141
PathImpl newPath = PathImpl.createCopy( propertyPath );
146142
node.appendTo( newPath );
@@ -212,6 +208,15 @@ public final void setElementType(ElementType elementType) {
212208
this.elementType = elementType;
213209
}
214210

211+
public final ValueState<V> getCurrentValueState() {
212+
return new ValueState<V>( propertyPath, currentValue );
213+
}
214+
215+
public final void resetValueState(ValueState<V> valueState) {
216+
this.propertyPath = valueState.propertyPath;
217+
this.currentValue = valueState.currentValue;
218+
}
219+
215220
@Override
216221
public String toString() {
217222
final StringBuilder sb = new StringBuilder();
@@ -230,4 +235,16 @@ public Object getValue(Object parent, ConstraintLocation location) {
230235
// TODO: For BVAL-214 we'd get the value from a map or another alternative structure instead
231236
return location.getValue( parent );
232237
}
238+
239+
public static class ValueState<V> {
240+
241+
private final PathImpl propertyPath;
242+
243+
private final V currentValue;
244+
245+
private ValueState(PathImpl propertyPath, V currentValue) {
246+
this.propertyPath = propertyPath;
247+
this.currentValue = currentValue;
248+
}
249+
}
233250
}

engine/src/main/java/org/hibernate/validator/internal/metadata/core/MetaConstraint.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import org.hibernate.validator.internal.engine.ValidationContext;
2020
import org.hibernate.validator.internal.engine.ValueContext;
2121
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree;
22-
import org.hibernate.validator.internal.engine.path.PathImpl;
2322
import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorDescriptor;
2423
import org.hibernate.validator.internal.engine.valueextraction.ValueExtractorHelper;
2524
import org.hibernate.validator.internal.metadata.descriptor.ConstraintDescriptorImpl;
@@ -208,7 +207,7 @@ public void keyedValue(String nodeName, Object key, Object value) {
208207
}
209208

210209
private void doValidate(Object value, String nodeName) {
211-
PathImpl before = valueContext.getPropertyPath();
210+
ValueContext.ValueState<Object> originalValueState = valueContext.getCurrentValueState();
212211

213212
Class<?> containerClass = currentValueExtractionPathNode.getContainerClass();
214213
if ( containerClass != null ) {
@@ -235,8 +234,8 @@ private void doValidate(Object value, String nodeName) {
235234
success &= doValidateConstraint( validationContext, valueContext );
236235
}
237236

238-
// reset the path to the state before this call
239-
valueContext.setPropertyPath( before );
237+
// reset the value context to the state before this call
238+
valueContext.resetValueState( originalValueState );
240239
}
241240

242241
public boolean isSuccess() {

engine/src/test/java/org/hibernate/validator/test/internal/engine/valueextraction/UnwrapValidatedValueTest.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.hibernate.validator.cfg.ConstraintMapping;
2626
import org.hibernate.validator.cfg.defs.MaxDef;
2727
import org.hibernate.validator.test.internal.engine.valueextraction.model.Account;
28+
import org.hibernate.validator.test.internal.engine.valueextraction.model.Company;
2829
import org.hibernate.validator.test.internal.engine.valueextraction.model.Customer;
2930
import org.hibernate.validator.test.internal.engine.valueextraction.model.Order;
3031
import org.hibernate.validator.test.internal.engine.valueextraction.model.OrderLine;
@@ -35,7 +36,6 @@
3536
import org.hibernate.validator.testutil.TestForIssue;
3637
import org.hibernate.validator.testutils.CandidateForTck;
3738
import org.hibernate.validator.testutils.ValidatorUtil;
38-
3939
import org.testng.annotations.BeforeMethod;
4040
import org.testng.annotations.Test;
4141

@@ -139,6 +139,19 @@ public void shouldUnwrapPropertyValuesDuringValueValidation() {
139139
);
140140
}
141141

142+
@Test
143+
@TestForIssue(jiraKey = "HV-1471")
144+
public void shouldUnwrapPropertyValuesDuringValueValidationAndProperlyResetContextAfterConstraintValidation() {
145+
Set<ConstraintViolation<Company>> violations = validator.validateValue(
146+
Company.class,
147+
"name",
148+
new StringProperty( "Acm" )
149+
);
150+
assertThat( violations ).containsOnlyViolations(
151+
violationOf( Size.class )
152+
);
153+
}
154+
142155
@Test(expectedExceptions = ConstraintDeclarationException.class, expectedExceptionsMessageRegExp = "HV000198.*")
143156
public void shouldRaiseExceptionIfNoMatchingUnwrapperIsFound() {
144157
validator.validate( new Order() );
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Hibernate Validator, declare and validate application constraints
3+
*
4+
* License: Apache License, Version 2.0
5+
* See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
6+
*/
7+
package org.hibernate.validator.test.internal.engine.valueextraction.model;
8+
9+
import javax.validation.constraints.NotNull;
10+
import javax.validation.constraints.Size;
11+
12+
/**
13+
* @author Guillaume Smet
14+
*/
15+
public class Company {
16+
17+
@NotNull
18+
@Size(min = 4)
19+
private Property<String> name = new Property<String>( "Acm" );
20+
}

0 commit comments

Comments
 (0)