title: Async Queries not working right in Spring Data JPA project
body: <p>After going through @KevinBowersox's Infinite Skills course on Spring Data for Java Developers, the only part that didn't seem to work as advertised were the Async methods. Mind you, at the beginning of the course he covered xml and Java configuration, but he proceeded to use the xml configuration throughout the rest of the course, whereas, I kept using Java configuration for each of the exercises and was able to get all the other parts to work. One minor difference is I am using IntelliJ IDEA rather than STS, as he uses throughout the course.</p>
  
  <p>If anyone familiar with Spring Data Async Queries or the segment of his course (<a href="https://www.safaribooksonline.com/library/view/spring-data-for/9781771375924/video241705.html" rel="nofollow noreferrer">https://www.safaribooksonline.com/library/view/spring-data-for/9781771375924/video241705.html</a>) has some insight into what might be missing, please let me know. </p>
  
  <p>Here are the relevant bits:</p>
  
  <p>/* Application.java */</p>
  
  <pre><code>@EnableAsync
  public class Application {
  
  public static void main(String[] args) throws ParseException {
  
      try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
              DataConfiguration.class)) {
          BookRepository repository = context.getBean(BookRepository.class);
  
          // TODO: Make method Async
          for (long x = 0; x &lt; 4; x++) {
              repository.findByIds(x);
          }
      }
  }
  </code></pre>
  
  <p>}</p>
  
  <p>/* BaseRepository.java */</p>
  
  <pre><code>@NoRepositoryBean
  public interface BaseRepository&lt;T, ID extends Serializable&gt; extends JpaRepository&lt;T, ID&gt; {
  
      @Override
      @Async("executor")
      List&lt;T&gt; findByIds(ID... ids);
  }
  </code></pre>
  
  <p>/* ExtendedRepositoryImpl.java */</p>
  
  <pre><code>public class ExtendedRepositoryImpl&lt;T, ID extends Serializable&gt;
          extends SimpleJpaRepository&lt;T, ID&gt; implements BaseRepository&lt;T, ID&gt; {
      private JpaEntityInformation&lt;T, ?&gt; entityInformation;
      private final EntityManager entityManager;
  
      public ExtendedRepositoryImpl(
              JpaEntityInformation&lt;T, ?&gt; entityInformation,
              EntityManager entityManager) {
          super(entityInformation, entityManager);
          this.entityInformation = entityInformation;
          this.entityManager = entityManager;
      }
  
      @Override
      public List&lt;T&gt; findByIds(ID... ids) {
          Query query = this.entityManager.createQuery("select e from " + this.entityInformation.getEntityName()
          + " e where e." + this.entityInformation.getIdAttribute().getName() + " in :ids");
          query.setParameter("ids", Arrays.asList(ids));
  
          long wait = new Random().nextInt(10000-1) +1;
          System.out.println(wait);
  
          try {
              Thread.sleep(wait);
          }
          catch (InterruptedException e) {
              e.printStackTrace();
          }
  
          System.out.println("Executing query for ID: " + Arrays.toString(ids));
  
          return (List&lt;T&gt;) query.getResultList();
      }
  }
  </code></pre>
  
  <p>/* DataConfiguration.java (aka AppConfig.java) */</p>
  
  <pre><code>@EnableJpaRepositories(
              basePackages = {"com.infiniteskills.springdata.async"},
              repositoryBaseClass = com.infiniteskills.springdata.async.data.repository.ExtendedRepositoryImpl.class,
              repositoryImplementationPostfix = "CustomImpl")
      @EnableJpaAuditing(auditorAwareRef = "customAuditorAware")
      @EnableAsync
      @EnableTransactionManagement
      @ComponentScan("com.infiniteskills.springdata.async")
      @Configuration
      public class DataConfiguration implements AsyncConfigurer {
          @Bean
          public CustomAuditorAware customAuditorAware() {
              return new CustomAuditorAware();
          }
  
          @Bean
          public DataSource dataSource() {
              EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
              return builder.setType(EmbeddedDatabaseType.H2).build();
          }
  
          @Bean
          public EntityManagerFactory entityManagerFactory() {
              HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
              // Generate tables in database
              vendorAdapter.setGenerateDdl(true);
  
              Properties jpaProperties = new Properties();
              jpaProperties.put("hibernate.hbm2ddl.auto", "create-drop");
              //jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
              //jpaProperties.put("hibernate.connection.driver_class", "org.h2.Driver");
  
              // After DDL has been run, run init script to populate table with data.
              jpaProperties.put("hibernate.hbm2ddl.import_files", "init.sql");
  
              // Entity Manager Factory Bean
              LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
              entityManagerFactoryBean.setDataSource(dataSource());
              entityManagerFactoryBean.setPackagesToScan("com.infiniteskills.springdata.async");
              entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
              entityManagerFactoryBean.setJpaProperties(jpaProperties);
              entityManagerFactoryBean.afterPropertiesSet();
              return entityManagerFactoryBean.getObject();
          }
  
          @Bean
          public PlatformTransactionManager transactionManager() {
              JpaTransactionManager transactionManager = new JpaTransactionManager();
              transactionManager.setEntityManagerFactory(entityManagerFactory());
              return transactionManager;
          }
  
          @Override
          @Bean(name = "executor")
          public Executor getAsyncExecutor() {
              ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
              executor.setCorePoolSize(10);
              executor.setMaxPoolSize(10);
              executor.setQueueCapacity(100);
              executor.setThreadNamePrefix("executor-");
              executor.initialize();
              return executor;
          }
  
          @Override
          @Bean
          public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
              return new SimpleAsyncUncaughtExceptionHandler();
          }
      }
  </code></pre>