From a72f467125482ba8a263baac9f8640e02b8adf72 Mon Sep 17 00:00:00 2001 From: Frantisek Hartman Date: Wed, 27 Sep 2017 08:52:31 +0200 Subject: [PATCH] DATAGRAPH-1031 Use custom IsNewStrategy in auditing. also : Add check on date intervals in tests. Rename test to reintegrate it to tests run by CI. Update docs. (cherry picked from commit bdaf6f7) --- .../config/Neo4jAuditingRegistrar.java | 7 +-- .../Neo4jIsNewAwareAuditingHandler.java | 58 ++++++++++++++++++ ...o4jMappingContextIsNewStrategyFactory.java | 59 +++++++++++++++++++ ...va => JavaConfigurationAuditingTests.java} | 18 +++--- src/main/asciidoc/index.adoc | 4 ++ src/main/asciidoc/new-features.adoc | 1 + src/main/asciidoc/reference/auditing.adoc | 7 +++ 7 files changed, 142 insertions(+), 12 deletions(-) create mode 100644 spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jIsNewAwareAuditingHandler.java create mode 100644 spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jMappingContextIsNewStrategyFactory.java rename spring-data-neo4j/src/test/java/org/springframework/data/neo4j/auditing/{JavaConfigurationAuditingTest.java => JavaConfigurationAuditingTests.java} (87%) create mode 100644 src/main/asciidoc/reference/auditing.adoc 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 4850c9988..2e16637a2 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 @@ -13,19 +13,18 @@ package org.springframework.data.neo4j.repository.config; +import java.lang.annotation.Annotation; + import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.data.auditing.IsNewAwareAuditingHandler; import org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport; import org.springframework.data.auditing.config.AuditingConfiguration; import org.springframework.data.config.ParsingUtils; import org.springframework.data.neo4j.annotation.EnableNeo4jAuditing; import org.springframework.util.Assert; -import java.lang.annotation.Annotation; - /** * @author Frantisek Hartman */ @@ -46,7 +45,7 @@ public class Neo4jAuditingRegistrar extends AuditingBeanDefinitionRegistrarSuppo Assert.notNull(configuration, "AuditingConfiguration must not be null!"); - BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(IsNewAwareAuditingHandler.class); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Neo4jIsNewAwareAuditingHandler.class); BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(Neo4jMappingContextFactoryBean.class); definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR); diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jIsNewAwareAuditingHandler.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jIsNewAwareAuditingHandler.java new file mode 100644 index 000000000..9432ac4bc --- /dev/null +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jIsNewAwareAuditingHandler.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2002-2017 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product may include a number of subcomponents with + * separate copyright notices and license terms. Your use of the source + * code for these subcomponents is subject to the terms and + * conditions of the subcomponent's license, as noted in the LICENSE file. + */ + +package org.springframework.data.neo4j.repository.config; + +import java.util.Collections; + +import org.springframework.data.auditing.IsNewAwareAuditingHandler; +import org.springframework.data.mapping.PersistentEntity; +import org.springframework.data.mapping.PersistentProperty; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.mapping.context.PersistentEntities; +import org.springframework.data.support.IsNewStrategy; +import org.springframework.data.support.IsNewStrategyFactory; +import org.springframework.util.Assert; + +/** + * IsNewAwareAuditingHandler which overrides markAudited to provide our own Neo4jMappingContextIsNewStrategyFactory + * + * @author Frantisek Hartman + */ +public class Neo4jIsNewAwareAuditingHandler extends IsNewAwareAuditingHandler { + + private IsNewStrategyFactory isNewStrategyFactory; + + public Neo4jIsNewAwareAuditingHandler(MappingContext, ? extends PersistentProperty> mappingContext) { + this(new PersistentEntities(Collections.singletonList(mappingContext))); + } + + public Neo4jIsNewAwareAuditingHandler(PersistentEntities entities) { + super(entities); + + isNewStrategyFactory = new Neo4jMappingContextIsNewStrategyFactory(entities); + } + + public void markAudited(Object object) { + Assert.notNull(object, "Source object must not be null!"); + if (this.isAuditable(object)) { + IsNewStrategy strategy = this.isNewStrategyFactory.getIsNewStrategy(object.getClass()); + if (strategy.isNew(object)) { + this.markCreated(object); + } else { + this.markModified(object); + } + + } + } +} diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jMappingContextIsNewStrategyFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jMappingContextIsNewStrategyFactory.java new file mode 100644 index 000000000..16ef7f933 --- /dev/null +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/config/Neo4jMappingContextIsNewStrategyFactory.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2002-2017 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This product is licensed to you under the Apache License, Version 2.0 (the "License"). + * You may not use this product except in compliance with the License. + * + * This product may include a number of subcomponents with + * separate copyright notices and license terms. Your use of the source + * code for these subcomponents is subject to the terms and + * conditions of the subcomponent's license, as noted in the LICENSE file. + */ + +package org.springframework.data.neo4j.repository.config; + +import java.util.Collections; + +import org.springframework.data.mapping.PersistentEntity; +import org.springframework.data.mapping.PersistentProperty; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory; +import org.springframework.data.mapping.context.PersistentEntities; +import org.springframework.data.support.IsNewStrategy; +import org.springframework.lang.Nullable; + +/** + * Custom MappingContextIsNewStrategyFactory with overriden doGetIsNewStrategy + * + * @author Frantisek Hartman + */ +public class Neo4jMappingContextIsNewStrategyFactory extends MappingContextIsNewStrategyFactory { + + private final PersistentEntities context; + + public Neo4jMappingContextIsNewStrategyFactory(MappingContext, ?> context) { + this(new PersistentEntities(Collections.singletonList(context))); + } + + public Neo4jMappingContextIsNewStrategyFactory(PersistentEntities entities) { + super(entities); + this.context = entities; + } + + @Nullable + @Override + protected IsNewStrategy doGetIsNewStrategy(Class type) { + return new IsNewStrategy() { + @Override + public boolean isNew(Object o) { + PersistentEntity> entity = context.getRequiredPersistentEntity(type); + + PersistentProperty> property = entity.getRequiredIdProperty(); + Object value = property.getOwner().getPropertyAccessor(o).getProperty(property); + + return value == null || (value instanceof Long && ((Long) value) < 0); + } + }; + } +} diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/auditing/JavaConfigurationAuditingTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/auditing/JavaConfigurationAuditingTests.java similarity index 87% rename from spring-data-neo4j/src/test/java/org/springframework/data/neo4j/auditing/JavaConfigurationAuditingTest.java rename to spring-data-neo4j/src/test/java/org/springframework/data/neo4j/auditing/JavaConfigurationAuditingTests.java index e5f8895a1..a49b2dda9 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/auditing/JavaConfigurationAuditingTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/auditing/JavaConfigurationAuditingTests.java @@ -13,6 +13,13 @@ package org.springframework.data.neo4j.auditing; +import static java.util.Optional.*; +import static org.assertj.core.api.Assertions.*; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.Optional; + import org.junit.Test; import org.junit.runner.RunWith; import org.neo4j.ogm.session.SessionFactory; @@ -29,17 +36,12 @@ import org.springframework.data.neo4j.transaction.Neo4jTransactionManager; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import java.util.Optional; - -import static java.util.Optional.of; -import static org.assertj.core.api.Assertions.assertThat; - /** * @author Frantisek Hartman */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration -public class JavaConfigurationAuditingTest extends MultiDriverTestClass { +public class JavaConfigurationAuditingTests extends MultiDriverTestClass { @Configuration @EnableNeo4jAuditing(modifyOnCreate = false) @@ -81,7 +83,7 @@ public class JavaConfigurationAuditingTest extends MultiDriverTestClass { assertThat(loaded).isPresent(); User found = loaded.get(); - assertThat(found.getCreated()).isNotNull(); + assertThat(found.getCreated()).isNotNull().isCloseTo(LocalDateTime.now(), within(1, ChronoUnit.SECONDS)); assertThat(found.getCreatedBy()).isEqualTo("userId"); assertThat(found.getModified()).isNull(); @@ -101,7 +103,7 @@ public class JavaConfigurationAuditingTest extends MultiDriverTestClass { User found = loaded.get(); - assertThat(found.getModified()).isNotNull(); + assertThat(found.getModified()).isNotNull().isCloseTo(LocalDateTime.now(), within(1, ChronoUnit.SECONDS)); assertThat(found.getModifiedBy()).isEqualTo("userId"); } } diff --git a/src/main/asciidoc/index.adoc b/src/main/asciidoc/index.adoc index 545c84969..8f5d8fa96 100644 --- a/src/main/asciidoc/index.adoc +++ b/src/main/asciidoc/index.adoc @@ -20,6 +20,7 @@ include::preface.adoc[] include::new-features.adoc[] include::{spring-data-commons-docs}/dependencies.adoc[] include::{spring-data-commons-docs}/repositories.adoc[] +include::{spring-data-commons-docs}/auditing.adoc[] :leveloffset: -1 @@ -31,6 +32,9 @@ include::reference/introduction.adoc[] include::reference/getting-started.adoc[] include::reference/ogm-support.adoc[] include::reference/neo4j-repositories.adoc[] +include::reference/projections.adoc[] +include::reference/auditing.adoc[] + :leveloffset: -1 [[ogm-reference-documentation]] diff --git a/src/main/asciidoc/new-features.adoc b/src/main/asciidoc/new-features.adoc index 8d4cdc82b..172350e22 100644 --- a/src/main/asciidoc/new-features.adoc +++ b/src/main/asciidoc/new-features.adoc @@ -14,6 +14,7 @@ * More flexible configuration. * Better Java 8 support : all type queries can now return stream results and `Optional`. Better date / time management. * Internal metadata handling has been refactored for better reliability. +* Auditing support (since 5.0.1) When migrating from 4.x, please see the <>. diff --git a/src/main/asciidoc/reference/auditing.adoc b/src/main/asciidoc/reference/auditing.adoc new file mode 100644 index 000000000..7fa03a392 --- /dev/null +++ b/src/main/asciidoc/reference/auditing.adoc @@ -0,0 +1,7 @@ +[[reference_programming-auditing]] +=== Auditing + +Spring Data Neo4j integrates into the Spring Data auditing infrastructure +to keep track of who created or changed an entity and the point in time this happened. + +Please refer to the <> section of the Spring Data reference. \ No newline at end of file