1

I have below class where I am trying to inject some JpaRepository dependency.

class Sample<T> implements SampleInterface<T> {
  @Autowired
  JpaRepository<T, Long> jpaRepository; // Want this to be injected by spring using A as entity
}


 class Main {
    @Bean
    Sample<A> sample() {
      return new Sample<A>(); // A is a jpa entity
    }
 }

Is it because annotations are parsed during compilation? Why can't spring make the autowiring dynamic using generics? I may be missing the fundamentals, but curious to fill that knowledge gap.

Akash
  • 4,412
  • 4
  • 30
  • 48
  • Does this answer your question? [How to Autowire Bean of generic type in Spring?](https://stackoverflow.com/questions/22603291/how-to-autowire-bean-of-generic-type-t-in-spring) – Shane Creedon Apr 03 '20 at 19:02
  • @ShaneCreedon Nope. Above question uses the concrete type during `@Autowired`. I want to know why generics (T) cannot be used to dynamically inject objects. – Akash Apr 03 '20 at 19:16
  • usually, the `autowired` field's type should be the class or the interface implemented by the bean. can you explain what is the relation here between the bean created and the `autowired` field (`JpaRepository`)? – elirandav Apr 03 '20 at 19:24
  • So I am assuming `T` should be replaced by `A` during bean creation by spring. I know there is something very basic that does not allow this. But why? – Akash Apr 03 '20 at 19:32
  • 1
    @Kayaman Spring could tell from the bean definition that the bean has a generic type argument `A` for `T`. If it maintained that mapping (through reflection from the source code), it could decide that the `JpaRepository` to be injected should be a `JpaRepository` bean, if one is available in the context. – Savior Apr 03 '20 at 19:39
  • It's not necessarily that Spring couldn't resolve the generic type if they really wanted to, but they haven't done the work. Working with generics at runtime requires extra work (see Shane's link), and that's not idiomatic code that you would see in Spring tutorials for example. Generics is "tacked on" after all, with erasure and other things that makes it a bit different than other features of the language. – Kayaman Apr 03 '20 at 19:52

1 Answers1

2

The reason for this is type erasure which happens at compile time while bean injection happens at runtime.

Since there are no bounds on it T gets erased and basically replaced by Object and Spring Data can't create repositories for Object.

See also Using generics in Spring Data JPA repositories

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
  • Thanks Jens. So type erasure it is. I did not know `T` gets erased after compilation. Is it because `java` is strictly typed? – Akash Apr 11 '20 at 15:19
  • 1
    Well without Java being strictly typed, generics would be pretty much useless, so yes. But there are different ways to implement generics. Reified types (the generics exist at run time) or type erasure (generics don't exist at run time). There are pro and cons for both approaches, which I don't really understand but the important argument to go with type erasure was to have backward compatibility with versions of Java that didn't have generics (Java < 1.5) – Jens Schauder Apr 11 '20 at 15:25