'How to return Generic List in FallbackHandler using Kotlin

I am trying to return List with Generic type from handle(context: ExecutionContext?) method of MicroProfile FallbackHandler using Kotlin. But it's throwing exception like " org.eclipse.microprofile.faulttolerance.exceptions.FaultToleranceDefinitionException: Invalid @Fallback on getDistanceData(java.lang.String): fallback handler's type java.util.List<? extends java.lang.String> is not the same as method's return type " RestClient :

@GET
    @Path("/testFallbackUrl")
    @Fallback(DistanceServiceFallback::class)
    @CircuitBreaker(
        requestVolumeThreshold = 4, failureRatio = 0.75, delay = 5000, successThreshold = 3
    )

    fun getDistanceData(@QueryParam("date") date: String) : List<String>

Handler:

@RegisterForReflection
class DistanceServiceFallback : FallbackHandler<List<String>> {

    @field:Default
    @field:Inject
    lateinit var logger: Logger

    override fun handle(context: ExecutionContext?): List<String> {
        logger.error("Inside DistanceServiceFallback handler. ")
        return listOf("Hello")
    }
}


Solution 1:[1]

This is because of a difference in type inference when your kotlin code is processed in Java. The return type of getDistanceData is java.util.List<String> and the handler's return type is as mentioned in the exception java.util.List<? extends java.lang.String>.

The return type java.util.List<String> is observed from the CDI interceptor so I am not sure how exactly it is extracted but obviously it is not carrying <? extends E> information.

The handler's type java.util.List<? extends java.lang.String> is on the other hand extracted from kotlin.collections.List which is defined as public interface List<out E> : Collection<E> which I think is correct as <out E> should translate to <? extends E>.

However, there is an easy workaround:

    @GET
    @Path("/testFallbackUrl")
    @Fallback(DistanceServiceFallback::class)
    @CircuitBreaker(
            requestVolumeThreshold = 4, failureRatio = 0.75, delay = 5000, successThreshold = 3
    )
    fun getDistanceData(@QueryParam("date") date: String) : MutableList<String> {
        return mutableListOf("Default")
    }

    @RegisterForReflection
    class DistanceServiceFallback : FallbackHandler<MutableList<String>> {

        @field:Default
        @field:Inject
        lateinit var logger: Logger

        override fun handle(context: ExecutionContext?): MutableList<String> {
            logger.error("Inside DistanceServiceFallback handler. ")
            return mutableListOf("Hello")
        }
    }

which works because MutableList is defined as public interface MutableList<E> : List<E>, MutableCollection<E> and thus it has now an exact generic type.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 xstefank