spring-framework icon indicating copy to clipboard operation
spring-framework copied to clipboard

GenericTypeResolver resolves to an incorrect type if a class implements multiple generic interfaces depending on the order of definition of the interfaces.

Open arneschweenbs opened this issue 1 year ago • 0 comments

Affects: 5.3.20

GenericTypeResolver#resolveVariable(TypeVariable<?> typeVariable, ResolvableType contextType) eventually resorts to recursively resolving the type of typeVariable by iterating over contextType.getInterfaces(). The first generic interface will hit the "// Fallback to bounds"-branch in ResolvableType#resolveType() even though this interface (and its generic type) might have nothing to do with typeVariable.

Workaround for us: omitting the type bound "F extends Number" at FooService

Minimal working example:

Output: java.lang.Integer java.lang.Number

Expected output: java.lang.Integer java.lang.Integer

Code:

import java.lang.reflect.Type;

import org.springframework.core.GenericTypeResolver;

public class Main {

    public static class BaseParam {
    }

    public static class FooParam extends BaseParam {
    }

    public interface FooService<F extends Number> {

        default void foo(F f) {
            // ...
        }
    }

    public interface BarService<B> {

        default void bar(B b) {
            // ...
        }
    }

    public static class FooBarService implements FooService<Integer>, BarService<String> {
    }

    public static class BarFooService implements BarService<String>, FooService<Integer> {
    }

    public static void printType(Class<?> cls) {

        Type f = FooService.class.getTypeParameters()[0];
        System.out.println(GenericTypeResolver.resolveType(f, cls).getTypeName());
    }

    public static void main(String[] args) throws Exception {

        printType(FooBarService.class);
        printType(BarFooService.class);
    }
}

arneschweenbs avatar Aug 01 '22 14:08 arneschweenbs