2

I'm writing a custom Java annotation for processing CrudRepositories with Reflection in Java Spring. With the org.reflections.reflections library. I'm getting all interfaces annotated with my annotation as a class file like so:

Reflections reflections = new Reflections("basePackage");
Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(MyAnnotation.class);

Only interfaces, which at some point extend JpaRepository are annotated with my @MyAnnotation at the class level.


My repository structure is as follows: There are two cases,

first case:
public interface SomeRepo extends JpaRepository<SomeEntity, Long> {...}

the second case is composed out of a inheritance hierarchy:
public interface SuperClassRepo <T extends SomeRandomEntity> extends JpaRepository<T, String> {...}
public interface SubClassRepo extends SuperClassRepo<SubEntityOfSomeRandomEntity> {...}

My goal is now to extract the generic type parameters of the underlying JpaRepository. I achieved to do that if the annotated class is a Java class, not an interface. How can I achieve the same for an interface? I guess I'm also having trouble because of the inheritance. I guess I have to get the "super class" until I reach the JpaRepository and then somewhat extract the generic type arguments.

Help is very much appreciated, thanks in advance

2
  • For what it's worth, Spring already has something for this. GenericsUtils#getParameterType Commented Apr 24, 2020 at 14:51
  • Thanks for your answer, this is exactly what I'm searching for, unfourunatly is this only contained in the Spring Cloud Stream library. I don't want to pull this whole library in my project just for this one function. Also, I tried it and it is working fine for the first case, for the second case the method runs infinitely. I noticed in debug, that for the generic inheritance class the resolved super type is always "?" which causes the code to run infinitely. The super class of "?" is again "?" which breaks the loop of the method Commented Apr 24, 2020 at 15:25

1 Answer 1

2

I found a solution by looking at the GenericsUtils#getParameterType as suggested:

private static Class<?> extractKeyFromRepository(Class<?> repository) {
    ResolvableType currentType = ResolvableType.forType(repository);
    ResolvableType resolvableType = currentType.getInterfaces()[0];

    if (JpaRepository.class.equals(resolvableType.getRawClass())) {
        ResolvableType[] generics = resolvableType.getGenerics();
        ResolvableType generic = generics[1];

        return generic.resolve();
    } else {
        return extractKeyFromRepository(resolvableType.toClass());
    }
}

This works only because I ensure beforehand, that what I'm putting in this method is valid. I do it like so, also I pay attention that only one interface is extended, by extending more than one interface one has to figure out which of these interfaces is the JpaRepository:

if (!repository.isInterface()) {throw new IllegalArgumentException();}

if (!JpaRepository.class.isAssignableFrom(repository)) {throw new IllegalArgumentException();}

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.