package org.ligoj.bootstrap.core.dao;

import java.io.Serializable;

import javax.persistence.EntityManager;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

/**
 * Repository factory.
 * 
 * @param <R>
 *            Repository
 * @param <T>
 *            Entity type.
 * @param <K>
 *            Entity's key type.
 */
public class RestRepositoryFactoryBean<R extends JpaRepository<T, K>, T, K extends Serializable> extends JpaRepositoryFactoryBean<R, T, K> {
	
	@Autowired
	private static ApplicationContext applicationContext;

	@Override
	protected RepositoryFactorySupport createRepositoryFactory(final EntityManager entityManager) {
		return new RestRepositoryFactory(entityManager);
	}

	private static class RestRepositoryFactory extends JpaRepositoryFactory {

		/**
		 * Constructor called by Spring-Data
		 * 
		 * @param entityManager
		 *            injected entity manager.
		 */
		RestRepositoryFactory(final EntityManager entityManager) {
			super(entityManager);
		}

		@Override
		protected Class<?> getRepositoryBaseClass(final RepositoryMetadata metadata) {

			// The RepositoryMetadata can be safely ignored, it is used by the JpaRepositoryFactory
			// to check for QueryDslJpaRepository's which is out of scope.
			return RestRepositoryImpl.class;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean#afterPropertiesSet()
	 */
	@Override
	public void afterPropertiesSet() {
		// Invoke pre-spring-data listeners
		applicationContext.getBeansOfType(AfterJpaBeforeSpringDataListener.class).values()
				.forEach(AfterJpaBeforeSpringDataListener::callback);
		super.afterPropertiesSet();
	}
}
@@ -140,36 +140,22 @@
 ans.
-factory.annotation.Autowired
+BeansException
 ;%0Aim
@@ -207,16 +207,76 @@
 ontext;%0A
+import org.springframework.context.ApplicationContextAware;%0A
 import o
@@ -896,17 +896,19 @@
 lizable%3E
- 
+%0A%09%09
 extends 
@@ -945,23 +945,45 @@
  K%3E 
-%7B%0A%09%0A%09@Autowired
+implements ApplicationContextAware %7B%0A
 %0A%09pr
@@ -988,23 +988,16 @@
 private 
-static 
 Applicat
@@ -1026,16 +1026,65 @@
 Context;
+%0A%09private static boolean listenersCalled = false;
 %0A%0A%09@Over
@@ -1694,16 +1694,22 @@
 d by the
+%0A%09%09%09//
  JpaRepo
@@ -1867,16 +1867,20 @@
 %09 * @see
+%0A%09 *
  org.spr
@@ -1945,16 +1945,21 @@
 oryBean#
+%0A%09 * 
 afterPro
@@ -2023,16 +2023,43 @@
 Set() %7B%0A
+%09%09if (!listenersCalled) %7B%0A%09
 %09%09// Inv
@@ -2088,16 +2088,44 @@
 steners%0A
+%09%09%09listenersCalled = true;%0A%09
 %09%09applic
@@ -2205,16 +2205,17 @@
 s()%0A%09%09%09%09
+%09
 .forEach
@@ -2260,16 +2260,20 @@
 lback);%0A
+%09%09%7D%0A
 %09%09super.
@@ -2296,10 +2296,177 @@
 et();%0A%09%7D
+%0A%0A%09@Override%0A%09public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException %7B%0A%09%09this.applicationContext = applicationContext;%0A%09%7D
 %0A%7D

Add listener between JPA and Spring-Data