From b7faf6dcbfff25045e30fad0b5a7f81d8255f420 Mon Sep 17 00:00:00 2001 From: ilya Date: Mon, 9 Dec 2019 15:07:32 +0300 Subject: [PATCH] #921: Allow JaversAuditableDelete work with id --- .../annotation/JaversAuditableDelete.java | 7 ++- .../auditable/aspect/JaversCommitAdvice.java | 26 +++++++++-- ...stractSpringAuditableRepositoryAspect.java | 9 ++-- ...uditableDeleteAspectIntegrationTest.groovy | 46 +++++++++++++++++++ .../repository/DummyAuditedRepository.groovy | 19 ++++++-- 5 files changed, 93 insertions(+), 14 deletions(-) diff --git a/javers-spring/src/main/java/org/javers/spring/annotation/JaversAuditableDelete.java b/javers-spring/src/main/java/org/javers/spring/annotation/JaversAuditableDelete.java index a2efc28af..27b2e008d 100644 --- a/javers-spring/src/main/java/org/javers/spring/annotation/JaversAuditableDelete.java +++ b/javers-spring/src/main/java/org/javers/spring/annotation/JaversAuditableDelete.java @@ -19,4 +19,9 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface JaversAuditableDelete { -} \ No newline at end of file + + /** + * domain type of entity to delete, required in case of delete by id + */ + Class domainType() default Void.class; +} diff --git a/javers-spring/src/main/java/org/javers/spring/auditable/aspect/JaversCommitAdvice.java b/javers-spring/src/main/java/org/javers/spring/auditable/aspect/JaversCommitAdvice.java index b04b1d795..701c46d0e 100644 --- a/javers-spring/src/main/java/org/javers/spring/auditable/aspect/JaversCommitAdvice.java +++ b/javers-spring/src/main/java/org/javers/spring/auditable/aspect/JaversCommitAdvice.java @@ -1,8 +1,13 @@ package org.javers.spring.auditable.aspect; import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.reflect.MethodSignature; import org.javers.common.collections.Maps; import org.javers.core.Javers; +import org.javers.core.metamodel.type.EntityType; +import org.javers.core.metamodel.type.JaversType; +import org.javers.core.metamodel.type.PrimitiveOrValueType; +import org.javers.spring.annotation.JaversAuditableDelete; import org.javers.spring.auditable.AspectUtil; import org.javers.spring.auditable.AuthorProvider; import org.javers.spring.auditable.CommitPropertiesProvider; @@ -30,9 +35,20 @@ public void commitSaveMethodArguments(JoinPoint pjp) { } } - public void commitDeleteMethodArguments(JoinPoint pjp) { - for (Object arg : AspectUtil.collectArguments(pjp)) { - commitShallowDelete(arg); + public void commitDeleteMethodArguments(JoinPoint jp) { + for (Object arg : AspectUtil.collectArguments(jp)) { + JaversType typeMapping = javers.getTypeMapping(arg.getClass()); + if (typeMapping instanceof EntityType) { + commitShallowDelete(arg); + } else if (typeMapping instanceof PrimitiveOrValueType) { + JaversAuditableDelete javersAuditableDelete = + ((MethodSignature) jp.getSignature()).getMethod().getAnnotation(JaversAuditableDelete.class); + Class domainType = javersAuditableDelete.domainType(); + if (domainType == Void.class) { + throw new IllegalStateException("Committing by id requires a domain type"); + } + commitShallowDeleteById(arg, domainType); + } } } @@ -40,8 +56,8 @@ public void commitObject(Object domainObject) { String author = authorProvider.provide(); javers.commit(author, domainObject, Maps.merge( - commitPropertiesProvider.provideForCommittedObject(domainObject), - commitPropertiesProvider.provide())); + commitPropertiesProvider.provideForCommittedObject(domainObject), + commitPropertiesProvider.provide())); } public void commitShallowDelete(Object domainObject) { diff --git a/javers-spring/src/main/java/org/javers/spring/auditable/aspect/springdata/AbstractSpringAuditableRepositoryAspect.java b/javers-spring/src/main/java/org/javers/spring/auditable/aspect/springdata/AbstractSpringAuditableRepositoryAspect.java index 43944a053..e4dc442c1 100644 --- a/javers-spring/src/main/java/org/javers/spring/auditable/aspect/springdata/AbstractSpringAuditableRepositoryAspect.java +++ b/javers-spring/src/main/java/org/javers/spring/auditable/aspect/springdata/AbstractSpringAuditableRepositoryAspect.java @@ -27,9 +27,8 @@ protected AbstractSpringAuditableRepositoryAspect(Javers javers, AuthorProvider } protected void onSave(JoinPoint pjp, Object returnedObject) { - getRepositoryInterface(pjp).ifPresent( i -> { - AspectUtil.collectReturnedObjects(returnedObject).forEach(o -> javersCommitAdvice.commitObject(o)); - }); + getRepositoryInterface(pjp).ifPresent(i -> + AspectUtil.collectReturnedObjects(returnedObject).forEach(javersCommitAdvice::commitObject)); } protected void onDelete(JoinPoint pjp) { @@ -56,12 +55,12 @@ private class OnDeleteAuditChangeHandler implements AuditChangeHandler { public void handle(RepositoryMetadata repositoryMetadata, Object domainObjectOrId) { if (isIdClass(repositoryMetadata, domainObjectOrId)) { Class domainType = repositoryMetadata.getDomainType(); - if (javers.findSnapshots(QueryBuilder.byInstanceId(domainObjectOrId, domainType).build()).size() == 0) { + if (javers.findSnapshots(QueryBuilder.byInstanceId(domainObjectOrId, domainType).limit(1).build()).size() == 0) { return; } javersCommitAdvice.commitShallowDeleteById(domainObjectOrId, domainType); } else if (isDomainClass(repositoryMetadata, domainObjectOrId)) { - if (javers.findSnapshots(QueryBuilder.byInstance(domainObjectOrId).build()).size() == 0) { + if (javers.findSnapshots(QueryBuilder.byInstance(domainObjectOrId).limit(1).build()).size() == 0) { return; } javersCommitAdvice.commitShallowDelete(domainObjectOrId); diff --git a/javers-spring/src/test/groovy/org/javers/spring/auditable/integration/JaversAuditableDeleteAspectIntegrationTest.groovy b/javers-spring/src/test/groovy/org/javers/spring/auditable/integration/JaversAuditableDeleteAspectIntegrationTest.groovy index a793ad127..33ff19f66 100644 --- a/javers-spring/src/test/groovy/org/javers/spring/auditable/integration/JaversAuditableDeleteAspectIntegrationTest.groovy +++ b/javers-spring/src/test/groovy/org/javers/spring/auditable/integration/JaversAuditableDeleteAspectIntegrationTest.groovy @@ -86,4 +86,50 @@ class JaversAuditableDeleteAspectIntegrationTest extends Specification { snapshots[1].initial } } + + def "should commit delete by id when method is annotated with @JaversAuditableDelete"() { + given: + def o = new DummyObject() + + when: + repository.save(o) + repository.deleteById(o.id) + + then: + def snapshots = javers.findSnapshots(QueryBuilder.byInstanceId(o.id, DummyObject).build()) + snapshots.size() == 2 + snapshots[0].terminal + snapshots[1].initial + } + + def "should commit ids iterable when method is annotated with @JaversAuditableDelete"() { + given: + def objects = [new DummyObject(), new DummyObject()] + + when: "iterable arg test" + repository.saveAll(objects) + repository.deleteAllById(objects.collect { it.id }) + + then: + objects.each { + javers.findSnapshots(QueryBuilder.byInstanceId(it.id, DummyObject).build()).size() == 1 + + def snapshots = javers.findSnapshots(QueryBuilder.byInstanceId(it.id, DummyObject).build()) + snapshots.size() == 2 + snapshots[0].terminal + snapshots[1].initial + } + } + + def "should throw exception if no domain type present when annotated with @JaversAuditableDelete"() { + given: + def o = new DummyObject() + + when: + repository.save(o) + repository.deleteByIdNoClass(o.id) + + then: + thrown(IllegalStateException) + } } diff --git a/javers-spring/src/test/groovy/org/javers/spring/repository/DummyAuditedRepository.groovy b/javers-spring/src/test/groovy/org/javers/spring/repository/DummyAuditedRepository.groovy index 2e30a233c..87921b73a 100644 --- a/javers-spring/src/test/groovy/org/javers/spring/repository/DummyAuditedRepository.groovy +++ b/javers-spring/src/test/groovy/org/javers/spring/repository/DummyAuditedRepository.groovy @@ -26,7 +26,7 @@ class DummyAuditedRepository { //... omitted } - DummyObject find(DummyObject query){ + DummyObject find(DummyObject query) { //... omitted null } @@ -36,13 +36,26 @@ class DummyAuditedRepository { //... omitted } + @JaversAuditableDelete(domainType = DummyObject.class) + void deleteById(String id) { + } + + @JaversAuditableDelete(domainType = DummyObject.class) + void deleteAllById(Iterable ids) { + } + + @JaversAuditableDelete + void deleteByIdNoClass(String id) { + } + + @JaversAuditableDelete - void deleteTwo(DummyObject obj, obj2){ + void deleteTwo(DummyObject obj, obj2) { //... omitted } @JaversAuditableDelete - void deleteAll(Iterable objetcs){ + void deleteAll(Iterable objetcs) { //... omitted }