Hi Hardy
I am as convinced as I can be that this is not doing as I think it should be and is a bug if you create these classes it will show the bug, I can send yo a zip of the classes to save you the time of creating the classes if you wish but I don't see a way of attaching a zip here
First the basic Annotation definition
Code:
package com.ttsltd.test;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.ReportAsSingleViolation;
@Target(TYPE)
@Retention(RUNTIME)
@Constraint(validatedBy = TestValidator.class)
@Documented
@ReportAsSingleViolation
public @interface IsValid {
Class<?>[] groups() default {};
String message() default "Default error message";
Class<? extends Payload>[] payload() default {};
}
Now its implementation
Code:
package com.ttsltd.test;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class TestValidator implements ConstraintValidator<IsValid, DummyTestClass>{
@Override
public void initialize(IsValid isValid) {}
@Override
public boolean isValid(DummyTestClass dummyTestClass, ConstraintValidatorContext constraintValidatorContext) {
constraintValidatorContext.disableDefaultConstraintViolation();
constraintValidatorContext.buildConstraintViolationWithTemplate("Changed error message").addConstraintViolation();
return false;
}
}
This is a dummy class definition to operate on it has no fields as I could see no point in the test context
Code:
package com.ttsltd.test;
@IsValid(groups=TestChecks.class)
public class DummyTestClass {}
Now the interface definition to define the group that it should only run the test against
Code:
package com.ttsltd.test;
public interface TestChecks {}
And finally a junit test case
Code:
package com.ttsltd.test;
import static org.junit.Assert.*;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.junit.Test;
public class TestClass {
@Test
public void test() throws Exception {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
DummyTestClass dummyTestClass = new DummyTestClass();
Set<ConstraintViolation<DummyTestClass>> constraintViolations = validator.validate(dummyTestClass, TestChecks.class);
for (ConstraintViolation<DummyTestClass> instance : constraintViolations)
assertEquals("Changed error message", instance.getMessage());
}
}
Basically my test case instantiates a new instance of DummyTestClass and runs the validation code against the instance, as the code testValidator instance is failing and altering the templae message I would expect the code to return the "Changed error message" it doesn't it returns the Deafult error message instead
I think this is incorrect see junit stack trace response below
Code:
org.junit.ComparisonFailure: expected:<[Changed] error message> but was:<[Default] error message>
at org.junit.Assert.assertEquals(Assert.java:123)
at org.junit.Assert.assertEquals(Assert.java:145)
at com.ttsltd.test.TestClass.test(TestClass.java:34)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Can you let me have you thoughts
I appreciate your help by the way
Chris