Hello,
I am not sure if this is a Kotlin issue, but my problem can be reproduced by a simple test
interface Foo {
@AssertTrue
fun isValid() = false
}
class FooBean : Foo
class FooTest {
@Test
fun test() {
val factory = Validation.buildDefaultValidatorFactory()
val validator = factory.validator
val errors = validator.validate(FooBean())
assertThat(errors.size).isEqualTo(1)
}
}
Expected :1
Actual :2
It seems that metadata that is created has property “valid” for both Foo and FooBean “declaring classes” so validation is run twice and resulting duplicate errors if not valid.
See also https://paste.pics/44b73408ded6ebd46440fc80058a4e91
Kotlin decompiled
// Foo.java
package fi.foo;
import javax.validation.constraints.AssertTrue;
import kotlin.Metadata;
@Metadata(
mv = {1, 1, 13},
bv = {1, 0, 3},
k = 1,
d1 = {"\u0000\u0010\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\u000b\n\u0000\bf\u0018\u00002\u00020\u0001J\b\u0010\u0002\u001a\u00020\u0003H\u0017¨\u0006\u0004"},
d2 = {"Lfi/foo/Foo;", "", "isValid", "", "foo"}
)
public interface Foo {
@AssertTrue
boolean isValid();
@Metadata(
mv = {1, 1, 13},
bv = {1, 0, 3},
k = 3
)
public static final class DefaultImpls {
@AssertTrue
public static boolean isValid(Foo $this) {
return false;
}
}
}
// FooBean.java
package fi.foo;
import javax.validation.constraints.AssertTrue;
import kotlin.Metadata;
@Metadata(
mv = {1, 1, 13},
bv = {1, 0, 3},
k = 1,
d1 = {"\u0000\f\n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0002\b\u0002\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002¨\u0006\u0003"},
d2 = {"Lfi/foo/FooBean;", "Lfi/foo/Foo;", "()V", "foo"}
)
public final class FooBean implements Foo {
@AssertTrue
public boolean isValid() {
return Foo.DefaultImpls.isValid(this);
}
}
Any ideas?
EDIT: Using Kotlin @JvmDefault annotation for interface method fixes this issue, but it is not very nice workaround…