Kotlin, Retrofit 2: lang.IllegalArgumentException: Parameter type must not include a type variable or wildcard: java.util.Map<java.lang.String, ?>
Asked Answered
E

4

21

In my Kotlin, Retrofit 2 project:

class TransportService {

    // static analog
    companion object {
        @JvmStatic
        fun checkoutSessions(bodyMap: Map<String, Any>, callback: Callback<Void>) {
            val stripeMonitorRestClient = RestClientFactory.createRestClient(StripeRestClient::class.java!!)
            val headerMap = mutableMapOf<String, String>()
            headerMap["Accept"] = "application/json"
            headerMap["Content-Type"] = "application/x-www-form-urlencoded"
            headerMap["Stripe-Version"] = "2019-03-14; checkout_sessions_beta=v1"
            headerMap["Authorization"] = "Bearer sk_test_4eC39HqLyjWDarjtT1zdp7dc"
            val adMessagesList = stripeMonitorRestClient.checkoutSessions(headerMap, bodyMap) // error here 
            // asynchronously
            adMessagesList.enqueue(callback)
        }
    }

}

And Rest client api:

import retrofit2.Call
import retrofit2.http.FieldMap
import retrofit2.http.HeaderMap
import retrofit2.http.POST
import retrofit2.http.FormUrlEncoded


interface StripeRestClient {

    @FormUrlEncoded
    @POST("checkout/sessions")
    fun checkoutSessions(@HeaderMap headers: Map<String, String>, @FieldMap body: Map<String, Any>): Call<Void>
}

but I get runtime error

Exception in thread "main" java.lang.IllegalArgumentException: Parameter type must not include a type variable or wildcard: java.util.Map<java.lang.String, ?> (parameter #2)

in this line:

val adMessagesList = stripeMonitorRestClient.checkoutSessions(headerMap, bodyMap) 

Here logs:

Hello, World! Current date(groovy) = Mon Apr 01 17:32:47 EEST 2019
Exception in thread "main" java.lang.IllegalArgumentException: Parameter type must not include a type variable or wildcard: java.util.Map<java.lang.String, ?> (parameter #2)
    for method StripeRestClient.checkoutSessions
    at retrofit2.Utils.methodError(Utils.java:52)
    at retrofit2.Utils.methodError(Utils.java:42)
    at retrofit2.Utils.parameterError(Utils.java:61)
    at retrofit2.RequestFactory$Builder.validateResolvableType(RequestFactory.java:720)
    at retrofit2.RequestFactory$Builder.parseParameterAnnotation(RequestFactory.java:551)
    at retrofit2.RequestFactory$Builder.parseParameter(RequestFactory.java:295)
    at retrofit2.RequestFactory$Builder.build(RequestFactory.java:182)
    at retrofit2.RequestFactory.parseAnnotations(RequestFactory.java:65)
    at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:25)
    at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:168)
    at retrofit2.Retrofit$1.invoke(Retrofit.java:147)
    at com.sun.proxy.$Proxy0.checkoutSessions(Unknown Source)
    at myproject.service.TransportService$Companion.checkoutSessions(TransportService.kt:19)
    at myproject.MainKt.main(Main.kt:14)
Extrinsic answered 1/4, 2019 at 14:36 Comment(2)
Have you tried adding the @JvmSuppressWildcards annotation in fun checkoutSessions(bodyMap: Map<String, @JvmSuppressWildcards Any>, callback: Callback<Void>) and/or fun checkoutSessions(@HeaderMap headers: Map<String, String>, @FieldMap body: Map<String, @JvmSuppressWildcards Any>): Call<Void>?Sinclair
Yes, this help. ThanksExtrinsic
G
28

Just use @JvmSuppressWildcards annotation before your interface method -

Like -

 @POST("add_new_purchase.php")
 @JvmSuppressWildcards
 fun addNewPurchase(@Body purchaseList: List<PurchaseModel>):  Call< BaseResponse>
Germaun answered 25/9, 2020 at 15:27 Comment(2)
More details you can refer to github.com/square/retrofit/issues/3275 and github.com/square/retrofit/issues/1805Libel
Nice one !, it works..Breakneck
M
4

The problem is with @FieldMap body: Map<String, Any>, don't use "Any", instead use String and Integer/Long value maps separately.

Mroz answered 11/7, 2020 at 8:23 Comment(1)
this is the answer in my case as well as @QueryMapFerriter
I
1

I encountered the same problem when started migration to Kotlin. If StripeRestClient is in Java the call would work.

Try to convert interface to Java.

Ichabod answered 3/6, 2020 at 21:1 Comment(0)
S
1

You can not pass Map<String, Any?> in Retrofit specially if you are using Moshi for Json serialization.

For that you should pass it as RequestBody

@POST("/api")    
suspend fun postRequest(@Body requestBody: RequestBody?)

For converting map = Map<String, Any?> to RequestBody what you should do is.

val requestBody = JSONObject(map).toString().toRequestBody("application/json".toMediaTypeOrNull())
apiService.postRequest(requestBody)
Sech answered 11/6, 2024 at 15:38 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.