Jdbi: Erro de métodos ambíguos (método de ponte ausente) para sobrecarga covariante de Kotlin

Criado em 9 ago. 2019  ·  8Comentários  ·  Fonte: jdbi/jdbi

EDIT: Atualizado com um exemplo mais simples.

De acordo com a documentação, os genéricos e o JDBI funcionam juntos, e eu já vi esse trabalho antes (embora com uma versão mais antiga do JDBI), mas por alguma razão agora recebo um erro:

org.jdbi.v3.sqlobject.UnableToCreateSqlObjectException: a interface Bar tem métodos ambíguos [public abstract java.lang.Object Foo.baz (java.util.UUID), public abstract java.util.UUID Bar.baz (java.util.UUID )], resolva com uma modificação explícita

http://jdbi.org/#_annotations_and_inheritance

Eu tentei @Override por uma boa medida, mas isso não mudou nada.

interface Foo<T> {
    <strong i="12">@SqlQuery</strong>
    fun baz(a: UUID): T
}

interface Bar : Foo<UUID> {
    @SqlQuery("SELECT ClientID " +
              "FROM ClientInstance " +
              "WHERE ClientInstanceID = ?")
    override fun baz(a: UUID): UUID
}

JDBI.inTransactionUnchecked { handle ->
    val tester = handle.attach(Bar::class.java)
    val hest = tester.baz(UUID.fromString("7a949c0e-28db-424a-a449-b118e5175a3b"))
    LOGGER.info { "hest $hest" }
}
bug

Comentários muito úteis

Oi Tor,
Testamos que uma construção muito semelhante funciona em Java vanilla: https://github.com/jdbi/jdbi/blob/master/sqlobject/src/test/java/org/jdbi/v3/sqlobject/TestSqlObject.java#L293 - L307
Talvez tenhamos perdido um caso para Kotlin. Devemos adicionar um teste correspondente ao seu uso aqui e corrigir qualquer bug que for descoberto.

Todos 8 comentários

Oi Tor,
Testamos que uma construção muito semelhante funciona em Java vanilla: https://github.com/jdbi/jdbi/blob/master/sqlobject/src/test/java/org/jdbi/v3/sqlobject/TestSqlObject.java#L293 - L307
Talvez tenhamos perdido um caso para Kotlin. Devemos adicionar um teste correspondente ao seu uso aqui e corrigir qualquer bug que for descoberto.

Ah, olhando mais de perto: observe que os tipos de retorno são diferentes, Object vs UUID . Espero que isso signifique que o compilador Kotlin está emitindo um método de ponte sintética que não estamos manipulando corretamente.

Para pessoas que pesquisam no Google, esse bug produz uma mensagem de erro diferente quando a interface pai não está anotada (demorei um pouco para encontrar isso!)

Exception in thread "main" java.lang.IllegalStateException: Method StringRepo.get must be default or be annotated with a SQL method annotation.
    at org.jdbi.v3.sqlobject.SqlObjectFactory.lambda$buildMethodHandler$15(SqlObjectFactory.java:148)
...
interface Repo<T> {
    fun get(): T
}
interface StringRepo : Repo<String> {
    @SqlQuery("SELECT 'Hello world!'")
    override fun get(): String
}
//...snip
jdbi.onDemand(StringRepo::class.java).get()

@LittleMikeDev , esse é um problema um pouco diferente. Eu melhorei a mensagem de erro para não enganar sobre a classe que está faltando a anotação: https://github.com/jdbi/jdbi/pull/1590/files#diff -75b1c04d402bd8924262c7fececfcdb1L166

@TorRanfelt , cavei um pouco mais nisso e não é óbvio o que fazer para consertar. Parece que o compilador Kotlin não está emitindo um método de ponte para a especialização do método covariante. Registrei um problema no rastreador de bug do Kotlin: https://youtrack.jetbrains.com/issue/KT-33634

Como solução alternativa, o Jdbi pode emular o método de ponte necessário. O código necessário provavelmente acaba sendo pequeno, mas muito difícil de escrever. Espero que Kotlin avalie o problema pelo menos em breve.

@stevenschlansker Obrigado por investigar isso.
Kotlin deve ter tido esta ponte antes porque eu a vi funcionar. - Isso explica por que não consegui fazer com que funcionasse novamente, revertendo para versões mais antigas do JDBI.

Parece que isso foi um compromisso para manter a compatibilidade do Java 6: 6 não oferece suporte a métodos de ponte em interfaces, portanto, Kotlin não os emite. Isso soa muito bobo hoje em dia, mas provavelmente fazia sentido há 10 anos;) Esperançosamente, eles abandonarão o suporte 6 logo, ou pelo menos habilitarão condicionalmente a compatibilidade com o mundo pós-6.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

qualidafial picture qualidafial  ·  3Comentários

Shujito picture Shujito  ·  5Comentários

goxr3plus picture goxr3plus  ·  4Comentários

jimmyhmiller picture jimmyhmiller  ·  6Comentários

Romqa picture Romqa  ·  5Comentários