diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jAuditingEventListener.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jAuditingEventListener.java index 1191de171..056756cd6 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jAuditingEventListener.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jAuditingEventListener.java @@ -21,10 +21,9 @@ import org.springframework.beans.factory.ObjectFactory; import org.springframework.data.auditing.AuditingHandler; import org.springframework.data.auditing.IsNewAwareAuditingHandler; import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.neo4j.repository.support.Neo4jAuditingBeanFactoryPostProcessor; import org.springframework.util.Assert; -import java.util.Optional; - /** * @author Frantisek Hartman */ @@ -34,8 +33,9 @@ public class Neo4jAuditingEventListener extends EventListenerAdapter implements /** * Creates a new {@link Neo4jAuditingEventListener} using the given {@link MappingContext} and {@link AuditingHandler} - * provided by the given {@link ObjectFactory}. - * + * provided by the given {@link ObjectFactory}. This constructor does an additional registration to the + * {@link SessionFactory}. Therefore the {@link SessionFactory} must already be instantiated. + * * @param auditingHandlerFactory must not be {@literal null}. */ public Neo4jAuditingEventListener(ObjectFactory auditingHandlerFactory, @@ -47,6 +47,17 @@ public class Neo4jAuditingEventListener extends EventListenerAdapter implements sessionFactory.register(this); } + /** + * Constructor used for creating an instance in the {@link Neo4jAuditingRegistrar} to get registered in the session + * "manually". The registration is done within the {@link Neo4jAuditingBeanFactoryPostProcessor}. + * + * @param auditingHandlerFactory {@link AuditingHandler} to hook into the {@code preSave} phase for auditing. + */ + public Neo4jAuditingEventListener(ObjectFactory auditingHandlerFactory) { + Assert.notNull(auditingHandlerFactory, "IsNewAwareAuditingHandler must not be null!"); + this.auditingHandlerFactory = auditingHandlerFactory; + } + @Override public void onPreSave(Event event) { Object object = event.getObject(); diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jAuditingRegistrar.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jAuditingRegistrar.java index 2e16637a2..3742b567a 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jAuditingRegistrar.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jAuditingRegistrar.java @@ -64,8 +64,7 @@ public class Neo4jAuditingRegistrar extends AuditingBeanDefinitionRegistrarSuppo BeanDefinitionBuilder listenerBeanDefinitionBuilder = BeanDefinitionBuilder .rootBeanDefinition(Neo4jAuditingEventListener.class); listenerBeanDefinitionBuilder - .addConstructorArgValue(ParsingUtils.getObjectFactoryBeanDefinition(getAuditingHandlerBeanName(), registry)) - .addConstructorArgReference("sessionFactory"); + .addConstructorArgValue(ParsingUtils.getObjectFactoryBeanDefinition(getAuditingHandlerBeanName(), registry)); registerInfrastructureBeanWithId(listenerBeanDefinitionBuilder.getBeanDefinition(), Neo4jAuditingEventListener.class.getName(), registry); diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jRepositoryConfigurationExtension.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jRepositoryConfigurationExtension.java index b261c3596..5b5a9c671 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jRepositoryConfigurationExtension.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jRepositoryConfigurationExtension.java @@ -28,6 +28,7 @@ import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.dao.DataAccessException; import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; import org.springframework.data.neo4j.repository.Neo4jRepository; +import org.springframework.data.neo4j.repository.support.Neo4jAuditingBeanFactoryPostProcessor; import org.springframework.data.neo4j.repository.support.Neo4jRepositoryFactoryBean; import org.springframework.data.neo4j.repository.support.SessionBeanDefinitionRegistrarPostProcessor; import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource; @@ -50,6 +51,7 @@ public class Neo4jRepositoryConfigurationExtension extends RepositoryConfigurati private static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager"; private static final String NEO4J_MAPPING_CONTEXT_BEAN_NAME = "neo4jMappingContext"; + private static final String NEO4J_AUDITING_POST_PROCESSOR_NAME = "neo4jAuditionBeanFactoryPostProcessor"; private static final String ENABLE_DEFAULT_TRANSACTIONS_ATTRIBUTE = "enableDefaultTransactions"; private static final String SESSION_BEAN_DEFINITION_REGISTRAR_POST_PROCESSOR_BEAN_NAME = "sessionBeanDefinitionRegistrarPostProcessor"; @@ -159,5 +161,9 @@ public class Neo4jRepositoryConfigurationExtension extends RepositoryConfigurati registerIfNotAlreadyRegistered(new RootBeanDefinition(Neo4jMappingContextFactoryBean.class), registry, NEO4J_MAPPING_CONTEXT_BEAN_NAME, source); + + registerIfNotAlreadyRegistered(new RootBeanDefinition(Neo4jAuditingBeanFactoryPostProcessor.class), registry, + NEO4J_AUDITING_POST_PROCESSOR_NAME, source); + } } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/support/Neo4jAuditingBeanFactoryPostProcessor.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/support/Neo4jAuditingBeanFactoryPostProcessor.java new file mode 100644 index 000000000..a78d9b5ab --- /dev/null +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/support/Neo4jAuditingBeanFactoryPostProcessor.java @@ -0,0 +1,31 @@ +package org.springframework.data.neo4j.repository.support; + +import org.neo4j.ogm.session.SessionFactory; +import org.neo4j.ogm.session.event.EventListener; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.data.neo4j.repository.config.Neo4jAuditingEventListener; + +public class Neo4jAuditingBeanFactoryPostProcessor implements BeanPostProcessor { + + private final SessionFactory sessionFactory; + + @Autowired + public Neo4jAuditingBeanFactoryPostProcessor(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if (bean instanceof Neo4jAuditingEventListener) { + EventListener auditingEventListener = (EventListener) bean; + + // we need to de-register first to be sure we just register once. + // Background: SpringBoot auto configuration does register all event listener in the context. + sessionFactory.deregister(auditingEventListener); + sessionFactory.register(auditingEventListener); + } + return bean; + } +}