package org.ligoj.bootstrap.core.dao;

import java.io.Serializable;

import javax.persistence.EntityManager;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
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> implements ApplicationContextAware {

	private ApplicationContext applicationContext;
	private static boolean listenersCalled = false;

	@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() {
		if (!listenersCalled) {
			// Invoke pre-spring-data listeners
			listenersCalled = true;
			applicationContext.getBeansOfType(AfterJpaBeforeSpringDataListener.class).values()
					.forEach(AfterJpaBeforeSpringDataListener::callback);
		}
		super.afterPropertiesSet();
	}

	@Override
	public void setApplicationContext(final ApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
	}
}
@@ -589,16 +589,51 @@
 pport;%0A%0A
+import lombok.extern.slf4j.Slf4j;%0A%0A
 /**%0A * R
@@ -786,16 +786,23 @@
 pe.%0A */%0A
+@Slf4j%0A
 public c
@@ -1025,54 +1025,144 @@
 t;%0A%09
-private static boolean listenersCalled = false
+%0A%09/**%0A%09 * Flag for the last invocations of %7B@link AfterJpaBeforeSpringDataListener%7D%0A%09 */%0A%09private static long lastListenerInvocation = 0
 ;%0A%0A%09
@@ -2116,92 +2116,246 @@
 if (
-!listenersCalled) %7B%0A%09%09%09// Invoke pre-spring-data listeners%0A%09%09%09listenersCalled = true
+applicationContext.getStartupDate() != lastListenerInvocation) %7B%0A%09%09%09// Invoke pre-spring-data listeners%0A%09%09%09log.info(%22Notify EMF is ready before parsing Spring-Data queries%22);%0A%09%09%09lastListenerInvocation = applicationContext.getStartupDate()
 ;%0A%09%09
@@ -2534,16 +2534,17 @@
 t();%0A%09%7D%0A
+%09
 %0A%09@Overr

Handle context restart for Spring-Data hook