square / retrofit

A type-safe HTTP client for Android and the JVM

Home Page:https://square.github.io/retrofit/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Feature Request - Ignoring methods in the interface with an annotation

ghahramani opened this issue · comments

I have multiple interfaces for different external services which some of interfaces are implemented via Retrofit and some have a custom implementation. Therefore, I needed to put a base interface as the contract for all clients. Here is the example

@Scope(SCOPE_PROTOTYPE)
interface BaseApiClient {

    fun type(): Type

    fun supports(type: Type): Boolean = type == type()

    fun create(
        headers: Map<String, String> = hashMapOf(),
        body: CreateClientRequestRestModel
    ): Mono<CreateClientResponseRestModel>

}

and the retrofit interface is

interface RetrofitClient : BaseApiClient {

    override fun type() = EXTERNAL_ONE

    @POST("api/blah/blah")
    override fun create(
        @HeaderMap headers: Map<String, String>,
        @Body body: @JvmSuppressWildcards CreatClientRequestRestModel
    ): Mono<CreateClientResponseRestModel>

}

I am encountering this error

Caused by: java.lang.IllegalArgumentException: HTTP method annotation is required (e.g., @GET, @POST, etc.).
    for method RetrofitClient.type

is there a way to just add a @Ignore annotation and tell to retrofit ignores the methods that are not annotation with http verb annotations? something like the below

interface RetrofitClient : BaseApiClient {
    
    @Ignore // -> This is a new annotation
    override fun type() = EXTERNAL_ONE

    @POST("api/blah/blah")
    override fun create(
        @HeaderMap headers: Map<String, String>,
        @Body body: @JvmSuppressWildcards CreatClientRequestRestModel
    ): Mono<CreateClientResponseRestModel>

}

Are you using -Xjvm-default=all in your Kotlin compiler flags? Retrofit should ignore any method that has a default implementation, but it needs to be a default as seen by Java's reflection. Since Kotlin used to target versions of the JVM older than 8, it has a compatibility mode for doing its default functions as rendered in bytecode.

You would also annotate each one with @JvmDefault, but that's a bit archaic nowadays with 8 being everyone's minimum (if not even higher).

I used @JvmDefault but did not work and also it is deprecated, I did not use Xjvm-default=all