Interface validation is ran twice (Kotlin)

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…