14
votes
interface Marker<T : BaseFoo> {
    fun getSpecialFoo(): List<T>
}

@Dao
interface FooDao: Marker<Foo> {
    @Query("SELECT * FROM foo WHERE bar = :bar")
    fun get(bar: Int): List<Foo>

    @Transaction
    override fun getSpecialFoo(): List<Foo> {
        return get(1)
    }
}

This results in

An abstract DAO method must be annotated with one and only one of the following annotations: Insert,Delete,Query,Update,RawQuery

However, Marker is not marked with @Dao and FooDao override getSpecialFoo already. Why does this error still show?

I need Marker because I need a generic DAO that has some methods. Is there a way to work around this?

The only way I can think of is marking the dao to Any and cast the type runtime or build a wrapper for the DAO.

2
@IntelliJAmiya That was a typo when I type on StackOverflow. Edited. - Joshua

2 Answers

19
votes

You can solve it.

The issue is not in room restrictions, but in kotlin implementation itself. You are using generic collection method, which by default is processed to List<? extends T> java implementation, but overridden method has List<Foo> return type. Room generator matches method signature and can't find implemented method with same signature, so you get

An abstract DAO method must be annotated with one and only one of the following annotations

The solution is just annotate method parameter in interface with @JvmSuppressWildcards:

fun getSpecialFoo(): List<@JvmSuppressWildcards T>

2
votes

This seems like it is limitation of the Room library. You can work around it like the following.

@Dao
interface FooDao {
    @Query("SELECT * FROM foo WHERE bar = :bar")
    fun get(bar: Int): List<Foo>

    @Transaction
    fun getSpecialFoo(): List<Foo> {
        return get(1)
    }
}

fun FooDao.wrapper(): Marker<Foo> {
    return Wrapper(this)
}


private class Wrapper(private val dao: FooDao): Marker<Foo> {
    override fun getSpecialFoo() = dao.getSpecialFoo()
}

When you need it to be Marker<Foo>, you can wrapper() to create a wrapper which implement Marker<Foo> by the dao.