title: Why spring data jpa repositories force interfaces only?
body: <p>I am setting up a multi-module spring-boot project having the following structure:</p>
  
  <ul>
  <li>root
  
  <ul>
  <li>core(having class TestingHandler, injecting TestingRepository to save data)</li>
  <li>persistence-api(having custom repository interface TestingRepository)</li>
  <li>persistence-memory(having MemoryTestingRepository abstract class extending both TestingRepository and JpaRepository)</li>
  <li>main(having the entry point of the application and a runner which invokes the TestingHandler to save the data)</li>
  </ul></li>
  </ul>
  
  <p>I am trying to build a simple spring boot application which will persist a sample record in its h2 in-mem db. but i keep getting the following error:</p>
  
  <pre><code>The injection point has the following annotations:
      - @org.springframework.beans.factory.annotation.Autowired(required=true)
  
  
  Action:
  
  Consider defining a bean of type 'com.****.***.services.testing.persistence.memory.MemoryTestingRepository' in your configuration.
  </code></pre>
  
  <p>What am i missing?</p>
  
  <p>I have tried the following:</p>
  
  <ul>
  <li>Not using repository hierarchy. Just using a single interface which extends <code>JpaRepository</code> and it works but i have to have interface hierarchy due to custom methods and need to support multiple db implementations in future.</li>
  <li>tried using the MemoryRepository directly in TestingHandler, did not work. If i convert the MemoryRepository to interface (and get rid of custom methods), it works. but like i mentioned i need to have custom method an have to support the interface hierarchy to support legacy code.</li>
  <li>tried playing a lot with Annotations like @EnableJpaRepositories, @ComponentScan etc, no help.</li>
  <li>Testing.java is pretty standard POJO with @Entity and @Id annotation, very simple.</li>
  </ul>
  
  <p>Here is the Handler class:</p>
  
  <pre><code>package com.***.**.services.testing.core;
  
  @Service
  public class TestingHandler {
  
      @Autowired
      private TestingRepository testingRepository;
  
      @NotNull
      public Testing create(@NotNull final TestingDto testingDto) {
          Testing testing = new Testing("123", testingDto.getName(), testingDto.getDescription(), testingDto.Key(), testingDto.getVersion());
          testingRepository.create(testing);
          return testing;
      }
  }
  </code></pre>
  
  <p>Note it is injecting the interface TestingRepository.</p>
  
  <p>Here is the TestingRepository interface (plain and simple):</p>
  
  <pre><code>package com.***.**.services.testing.persistence.api;
  
  @Repository
  public interface TestingRepository {
    void create();
    void findByCustomAttr();
  }
  </code></pre>
  
  <p>Here is the impl class of TestingRepository:</p>
  
  <pre><code>package com.***.**.services.testing.persistence.memory;
  
  @Repository
  public abstract class MemoryTestingRepository implements JpaRepository&lt;Testing, Integer&gt;, TestingRepository {
   @Override
      public void create(@NotNull Testing testing) {
          save(testing); //the real jpa method called.
      }
  
  @Override
  public void findByCustomAttr(){
  //some impl....
  }
  
  }
  
  </code></pre>
  
  <p>finally, the main class looks like this:</p>
  
  <pre><code>package com.***.**.services.testing.main;
  @SpringBootApplication(scanBasePackages = "com.***.**.services.testing")
  @EnableJpaRepositories("com.***.**.services.testing.persistence")
  @EntityScan(basePackages = {"com.***.**.services.testing.persistence"})
  public class TestingApplication {
  
      public static void main(String[] args) {
          SpringApplication.run(TestingApplication.class, args);
      }
  
  }
  </code></pre>
  
  <p>i also have a runner class which invokes the handler method:</p>
  
  <pre><code>package com.***.**.services.testing.main;
  
  @Component
  public class TestingService implements CommandLineRunner {
  
      @Autowired
      private TestingHandler testingHandler;
  
      @Override
  
      public void run(final String... args) throws Exception {
          test();
      }
  
  
      public void test() {
          testingHandler.create(new TestingDto("name", "desc", "some_mapping_id", Version.create()));
      }
  
  }
  </code></pre>
  
  <p>Any pointers?</p>