From e4d1e1d5c442e0a0cc67d2d75ff67b220ab05d24 Mon Sep 17 00:00:00 2001 From: yadhuksp Date: Wed, 15 Jun 2022 00:05:53 +0530 Subject: [PATCH 1/8] add ChangeUnitConstructor --- .../java/io/mongock/api/annotations/ChangeUnit.java | 2 ++ .../api/annotations/ChangeUnitConstructor.java | 11 +++++++++++ 2 files changed, 13 insertions(+) create mode 100644 mongock-core/mongock-api/src/main/java/io/mongock/api/annotations/ChangeUnitConstructor.java diff --git a/mongock-core/mongock-api/src/main/java/io/mongock/api/annotations/ChangeUnit.java b/mongock-core/mongock-api/src/main/java/io/mongock/api/annotations/ChangeUnit.java index e59f59dbf..290f750c2 100644 --- a/mongock-core/mongock-api/src/main/java/io/mongock/api/annotations/ChangeUnit.java +++ b/mongock-core/mongock-api/src/main/java/io/mongock/api/annotations/ChangeUnit.java @@ -18,6 +18,7 @@ * The concept is basically the same, a class that wraps the logic of the migration *

* Classes annotated with @ChangeUnit must have the following: + * - One(and only one) one valid constructor annotated with @ChangeUnitConstructor(mandatory if more than one constructor exist) * - One(and only one) method annotated with @Execution(mandatory) * - One(and only one) method annotated with @RollbackExecution(mandatory) * - At most, one method annotated with @BeforeExecution(optional) @@ -28,6 +29,7 @@ *

* - For new changeLogs/changeSets created from version 5: Annotated you class migration class with the annotation @ChangeUnit * + * @see ChangeUnitConstructor * @see Execution * @see BeforeExecution * @see RollbackExecution diff --git a/mongock-core/mongock-api/src/main/java/io/mongock/api/annotations/ChangeUnitConstructor.java b/mongock-core/mongock-api/src/main/java/io/mongock/api/annotations/ChangeUnitConstructor.java new file mode 100644 index 000000000..ceb9c48f2 --- /dev/null +++ b/mongock-core/mongock-api/src/main/java/io/mongock/api/annotations/ChangeUnitConstructor.java @@ -0,0 +1,11 @@ +package io.mongock.api.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.CONSTRUCTOR) +@Retention(RetentionPolicy.RUNTIME) +public @interface ChangeUnitConstructor { +} From 38d12f1798048eed30dd3545ffa1281051d1520c Mon Sep 17 00:00:00 2001 From: yadhuksp Date: Sun, 19 Jun 2022 11:49:58 +0530 Subject: [PATCH 2/8] enhance exception when no valid constructor exist --- .../core/executor/ChangeLogRuntimeImpl.java | 9 +++++++-- .../ChangeUnitWithoutValidConstructor.java | 20 +++++++++++++++++++ .../executor/ChangeUnitExecutorImplTest.java | 12 +++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithoutValidConstructor.java diff --git a/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java b/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java index f78c70505..4d9f72b4d 100644 --- a/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java +++ b/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java @@ -1,7 +1,6 @@ package io.mongock.runner.core.executor; import io.changock.migration.api.annotations.NonLockGuarded; - import io.mongock.api.annotations.ChangeUnit; import io.mongock.api.exception.MongockException; import io.mongock.driver.api.common.DependencyInjectionException; @@ -20,10 +19,13 @@ import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.function.Function; +import java.util.stream.Stream; public class ChangeLogRuntimeImpl implements ChangeLogRuntime { private static final Logger logger = LoggerFactory.getLogger(ChangeLogRuntimeImpl.class); @@ -120,6 +122,9 @@ private String getParameterName(Parameter parameter) { private Constructor getConstructor(Class type) { - return type.getConstructors()[0]; + return Optional.of(type.getConstructors()) + .map(Arrays::stream) + .flatMap(Stream::findFirst) + .orElseThrow(() -> new MongockException("Mongock cannot find a valid constructor for changeUnit[%s]", type.getName())); } } diff --git a/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithoutValidConstructor.java b/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithoutValidConstructor.java new file mode 100644 index 000000000..394cd454b --- /dev/null +++ b/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithoutValidConstructor.java @@ -0,0 +1,20 @@ +package io.mongock.runner.core.changelogs.withConstructor; + +import io.mongock.api.annotations.ChangeUnit; +import io.mongock.api.annotations.Execution; +import io.mongock.api.annotations.RollbackExecution; + +@ChangeUnit(id = "ChangeUnitWithoutValidConstructor", order = "1") +public class ChangeUnitWithoutValidConstructor { + + private ChangeUnitWithoutValidConstructor() { + } + + @Execution + public void execution() { + } + + @RollbackExecution + public void rollbackExecution() { + } +} diff --git a/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/executor/ChangeUnitExecutorImplTest.java b/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/executor/ChangeUnitExecutorImplTest.java index 06e34cd9a..94456d401 100644 --- a/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/executor/ChangeUnitExecutorImplTest.java +++ b/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/executor/ChangeUnitExecutorImplTest.java @@ -26,6 +26,7 @@ import io.mongock.runner.core.changelogs.skipmigration.withnochangeset.ChangeLogWithNoChangeSet; import io.mongock.runner.core.changelogs.system.NewChangeUnit; import io.mongock.runner.core.changelogs.system.SystemChangeUnit; +import io.mongock.runner.core.changelogs.withConstructor.ChangeUnitWithoutValidConstructor; import io.mongock.runner.core.changelogs.withRollback.AdvanceChangeLogWithBefore; import io.mongock.runner.core.changelogs.withRollback.AdvanceChangeLogWithBeforeAndChangeSetFailing; import io.mongock.runner.core.changelogs.withRollback.BasicChangeLogWithExceptionInChangeSetAndRollback; @@ -63,6 +64,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -964,6 +966,16 @@ public void shouldNotRollbackManuallyAnyChangeSetsAndStoreChangeEntries_whenSeco } + @Test + public void shouldNotCreateInstanceWhenNoValidConstructorExist() { + ChangeLogRuntimeImpl changeLogRuntime = getChangeLogRuntime(new DependencyManager()); + MongockException mongockException = assertThrows(MongockException.class, + () -> changeLogRuntime.getInstance(ChangeUnitWithoutValidConstructor.class)); + assertEquals("Mongock cannot find a valid constructor for " + + "changeUnit[io.mongock.runner.core.changelogs.withConstructor.ChangeUnitWithoutValidConstructor]", + mongockException.getMessage()); + } + private SortedSet createInitialChangeLogsByPackage(Class... executorChangeLogClass) { List packages = Stream.of(executorChangeLogClass) .map(clazz -> clazz.getPackage().getName()) From 7bf139e4ca83073def9bb3c1a4ca915314cffa8f Mon Sep 17 00:00:00 2001 From: yadhuksp Date: Sun, 19 Jun 2022 12:41:10 +0530 Subject: [PATCH 3/8] add findChangeUnitConstructor in ChangeLogRuntimeImpl --- .../core/executor/ChangeLogRuntimeImpl.java | 17 ++++++++++++ ...tWithMoreThanOneChangeUnitConstructor.java | 26 +++++++++++++++++++ .../executor/ChangeUnitExecutorImplTest.java | 13 ++++++++++ 3 files changed, 56 insertions(+) create mode 100644 mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithMoreThanOneChangeUnitConstructor.java diff --git a/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java b/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java index 4d9f72b4d..a0e4694d8 100644 --- a/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java +++ b/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java @@ -2,6 +2,7 @@ import io.changock.migration.api.annotations.NonLockGuarded; import io.mongock.api.annotations.ChangeUnit; +import io.mongock.api.annotations.ChangeUnitConstructor; import io.mongock.api.exception.MongockException; import io.mongock.driver.api.common.DependencyInjectionException; import io.mongock.driver.api.driver.ChangeSetDependency; @@ -25,6 +26,7 @@ import java.util.Optional; import java.util.Set; import java.util.function.Function; +import java.util.function.Supplier; import java.util.stream.Stream; public class ChangeLogRuntimeImpl implements ChangeLogRuntime { @@ -122,9 +124,24 @@ private String getParameterName(Parameter parameter) { private Constructor getConstructor(Class type) { + return findChangeUnitConstructor(type, type.getName()) + .orElseGet(() -> findDefaultConstructor(type)); + } + + private Constructor findDefaultConstructor(Class type) { return Optional.of(type.getConstructors()) .map(Arrays::stream) .flatMap(Stream::findFirst) .orElseThrow(() -> new MongockException("Mongock cannot find a valid constructor for changeUnit[%s]", type.getName())); } + + private Optional> findChangeUnitConstructor(Class type, String className) { + Supplier>> changeUnitConstructorsSupplier = () -> Arrays.stream(type.getConstructors()) + .filter(constructor -> constructor.isAnnotationPresent(ChangeUnitConstructor.class)); + if (changeUnitConstructorsSupplier.get().count() > 1) { + throw new MongockException("Found multiple constructors for changeUnit[%s] without annotation @ChangeUnitConstructor." + + " Annotate the one you want Mongock to use to instantiate your changeUnit", className); + } + return changeUnitConstructorsSupplier.get().findFirst(); + } } diff --git a/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithMoreThanOneChangeUnitConstructor.java b/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithMoreThanOneChangeUnitConstructor.java new file mode 100644 index 000000000..6edb553e3 --- /dev/null +++ b/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithMoreThanOneChangeUnitConstructor.java @@ -0,0 +1,26 @@ +package io.mongock.runner.core.changelogs.withConstructor; + +import io.mongock.api.annotations.ChangeUnit; +import io.mongock.api.annotations.ChangeUnitConstructor; +import io.mongock.api.annotations.Execution; +import io.mongock.api.annotations.RollbackExecution; + +@ChangeUnit(id = "ChangeUnitWithMoreThanOneChangeUnitConstructor", order = "1") +public class ChangeUnitWithMoreThanOneChangeUnitConstructor { + + @ChangeUnitConstructor + public ChangeUnitWithMoreThanOneChangeUnitConstructor() { + } + + @ChangeUnitConstructor + public ChangeUnitWithMoreThanOneChangeUnitConstructor(String dummy) { + } + + @Execution + public void execution() { + } + + @RollbackExecution + public void rollbackExecution() { + } +} diff --git a/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/executor/ChangeUnitExecutorImplTest.java b/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/executor/ChangeUnitExecutorImplTest.java index 94456d401..3c05dc0ab 100644 --- a/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/executor/ChangeUnitExecutorImplTest.java +++ b/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/executor/ChangeUnitExecutorImplTest.java @@ -26,6 +26,7 @@ import io.mongock.runner.core.changelogs.skipmigration.withnochangeset.ChangeLogWithNoChangeSet; import io.mongock.runner.core.changelogs.system.NewChangeUnit; import io.mongock.runner.core.changelogs.system.SystemChangeUnit; +import io.mongock.runner.core.changelogs.withConstructor.ChangeUnitWithMoreThanOneChangeUnitConstructor; import io.mongock.runner.core.changelogs.withConstructor.ChangeUnitWithoutValidConstructor; import io.mongock.runner.core.changelogs.withRollback.AdvanceChangeLogWithBefore; import io.mongock.runner.core.changelogs.withRollback.AdvanceChangeLogWithBeforeAndChangeSetFailing; @@ -976,6 +977,18 @@ public void shouldNotCreateInstanceWhenNoValidConstructorExist() { mongockException.getMessage()); } + @Test + public void shouldNotCreateInstanceWhenMoreThanOneConstructorIsAnnotatedWithChangeUnitConstructor() { + ChangeLogRuntimeImpl changeLogRuntime = getChangeLogRuntime(new DependencyManager()); + MongockException mongockException = assertThrows(MongockException.class, + () -> changeLogRuntime.getInstance(ChangeUnitWithMoreThanOneChangeUnitConstructor.class)); + assertEquals("Found multiple constructors for" + + " changeUnit[io.mongock.runner.core.changelogs.withConstructor.ChangeUnitWithMoreThanOneChangeUnitConstructor] " + + "without annotation @ChangeUnitConstructor. " + + "Annotate the one you want Mongock to use to instantiate your changeUnit", + mongockException.getMessage()); + } + private SortedSet createInitialChangeLogsByPackage(Class... executorChangeLogClass) { List packages = Stream.of(executorChangeLogClass) .map(clazz -> clazz.getPackage().getName()) From 3513614db3a24f961feb574129ea1e06fd72f78f Mon Sep 17 00:00:00 2001 From: yadhuksp Date: Sun, 19 Jun 2022 13:06:40 +0530 Subject: [PATCH 4/8] add warning when all valid constructors are not annotated with ChangeUnitConstructor --- .../runner/core/executor/ChangeLogRuntimeImpl.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java b/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java index a0e4694d8..5c7f50415 100644 --- a/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java +++ b/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java @@ -129,9 +129,14 @@ private Constructor getConstructor(Class type) { } private Constructor findDefaultConstructor(Class type) { - return Optional.of(type.getConstructors()) - .map(Arrays::stream) - .flatMap(Stream::findFirst) + Supplier>> constructorSupplier = () -> Arrays.stream(type.getConstructors()); + if (constructorSupplier.get().count() > 1) { + logger.warn("Mongock found multiple constructors for changeUnit[{}]. " + + "It's recommended to annotate the one you want Mongock to use with @ChangeUnitConstructor. " + + "FROM VERSION 6 THIS WILL CAUSE AN ERROR ", type.getName()); + } + return constructorSupplier.get() + .findFirst() .orElseThrow(() -> new MongockException("Mongock cannot find a valid constructor for changeUnit[%s]", type.getName())); } From da0a4269e5fbc5b3d959880b424b80e10efebf1e Mon Sep 17 00:00:00 2001 From: yadhuksp Date: Sun, 19 Jun 2022 13:08:48 +0530 Subject: [PATCH 5/8] minor refactoring --- .../mongock/runner/core/executor/ChangeLogRuntimeImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java b/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java index 5c7f50415..dda6421a6 100644 --- a/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java +++ b/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java @@ -124,7 +124,7 @@ private String getParameterName(Parameter parameter) { private Constructor getConstructor(Class type) { - return findChangeUnitConstructor(type, type.getName()) + return findChangeUnitConstructor(type) .orElseGet(() -> findDefaultConstructor(type)); } @@ -140,12 +140,12 @@ private Constructor findDefaultConstructor(Class type) { .orElseThrow(() -> new MongockException("Mongock cannot find a valid constructor for changeUnit[%s]", type.getName())); } - private Optional> findChangeUnitConstructor(Class type, String className) { + private Optional> findChangeUnitConstructor(Class type) { Supplier>> changeUnitConstructorsSupplier = () -> Arrays.stream(type.getConstructors()) .filter(constructor -> constructor.isAnnotationPresent(ChangeUnitConstructor.class)); if (changeUnitConstructorsSupplier.get().count() > 1) { throw new MongockException("Found multiple constructors for changeUnit[%s] without annotation @ChangeUnitConstructor." + - " Annotate the one you want Mongock to use to instantiate your changeUnit", className); + " Annotate the one you want Mongock to use to instantiate your changeUnit", type.getName()); } return changeUnitConstructorsSupplier.get().findFirst(); } From 7ee61d586199d312826b2e5d82d0187516cd6bf1 Mon Sep 17 00:00:00 2001 From: yadhuksp Date: Sun, 19 Jun 2022 13:19:27 +0530 Subject: [PATCH 6/8] add tests to validate valid constructor behaviour --- .../ChangeUnitWithDefaultConstructor.java | 17 +++++++++ .../ChangeUnitWithValidConstructor.java | 20 +++++++++++ ...nstructorsHavingChangeUnitConstructor.java | 35 +++++++++++++++++++ .../executor/ChangeUnitExecutorImplTest.java | 26 ++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithDefaultConstructor.java create mode 100644 mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithValidConstructor.java create mode 100644 mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithValidConstructorsHavingChangeUnitConstructor.java diff --git a/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithDefaultConstructor.java b/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithDefaultConstructor.java new file mode 100644 index 000000000..c222d1db5 --- /dev/null +++ b/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithDefaultConstructor.java @@ -0,0 +1,17 @@ +package io.mongock.runner.core.changelogs.withConstructor; + +import io.mongock.api.annotations.ChangeUnit; +import io.mongock.api.annotations.Execution; +import io.mongock.api.annotations.RollbackExecution; + +@ChangeUnit(id = "ChangeUnitWithDefaultConstructor", order = "1") +public class ChangeUnitWithDefaultConstructor { + + @Execution + public void execution() { + } + + @RollbackExecution + public void rollbackExecution() { + } +} diff --git a/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithValidConstructor.java b/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithValidConstructor.java new file mode 100644 index 000000000..c10e4b5b9 --- /dev/null +++ b/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithValidConstructor.java @@ -0,0 +1,20 @@ +package io.mongock.runner.core.changelogs.withConstructor; + +import io.mongock.api.annotations.ChangeUnit; +import io.mongock.api.annotations.Execution; +import io.mongock.api.annotations.RollbackExecution; + +@ChangeUnit(id = "ChangeUnitWithValidConstructor", order = "1") +public class ChangeUnitWithValidConstructor { + + public ChangeUnitWithValidConstructor() { + } + + @Execution + public void execution() { + } + + @RollbackExecution + public void rollbackExecution() { + } +} diff --git a/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithValidConstructorsHavingChangeUnitConstructor.java b/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithValidConstructorsHavingChangeUnitConstructor.java new file mode 100644 index 000000000..38bcaf6db --- /dev/null +++ b/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/changelogs/withConstructor/ChangeUnitWithValidConstructorsHavingChangeUnitConstructor.java @@ -0,0 +1,35 @@ +package io.mongock.runner.core.changelogs.withConstructor; + +import io.mongock.api.annotations.ChangeUnit; +import io.mongock.api.annotations.ChangeUnitConstructor; +import io.mongock.api.annotations.Execution; +import io.mongock.api.annotations.RollbackExecution; + +@ChangeUnit(id = "ChangeUnitWithValidConstructorsHavingChangeUnitConstructor", order = "1") +public class ChangeUnitWithValidConstructorsHavingChangeUnitConstructor { + + public static final String DUMMY_VALUE = "dummyValue"; + private final String dummy; + + public ChangeUnitWithValidConstructorsHavingChangeUnitConstructor(String dummy) { + this.dummy = dummy; + } + + + @ChangeUnitConstructor + public ChangeUnitWithValidConstructorsHavingChangeUnitConstructor() { + this.dummy = DUMMY_VALUE; + } + + @Execution + public void execution() { + } + + @RollbackExecution + public void rollbackExecution() { + } + + public String getDummy() { + return dummy; + } +} diff --git a/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/executor/ChangeUnitExecutorImplTest.java b/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/executor/ChangeUnitExecutorImplTest.java index 3c05dc0ab..13494e49f 100644 --- a/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/executor/ChangeUnitExecutorImplTest.java +++ b/mongock-core/mongock-runner/mongock-runner-core/src/test/java/io/mongock/runner/core/executor/ChangeUnitExecutorImplTest.java @@ -26,7 +26,10 @@ import io.mongock.runner.core.changelogs.skipmigration.withnochangeset.ChangeLogWithNoChangeSet; import io.mongock.runner.core.changelogs.system.NewChangeUnit; import io.mongock.runner.core.changelogs.system.SystemChangeUnit; +import io.mongock.runner.core.changelogs.withConstructor.ChangeUnitWithDefaultConstructor; import io.mongock.runner.core.changelogs.withConstructor.ChangeUnitWithMoreThanOneChangeUnitConstructor; +import io.mongock.runner.core.changelogs.withConstructor.ChangeUnitWithValidConstructor; +import io.mongock.runner.core.changelogs.withConstructor.ChangeUnitWithValidConstructorsHavingChangeUnitConstructor; import io.mongock.runner.core.changelogs.withConstructor.ChangeUnitWithoutValidConstructor; import io.mongock.runner.core.changelogs.withRollback.AdvanceChangeLogWithBefore; import io.mongock.runner.core.changelogs.withRollback.AdvanceChangeLogWithBeforeAndChangeSetFailing; @@ -65,6 +68,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doThrow; @@ -989,6 +993,28 @@ public void shouldNotCreateInstanceWhenMoreThanOneConstructorIsAnnotatedWithChan mongockException.getMessage()); } + @Test + public void shouldCreateInstanceWhenOnlyOneValidConstructorExistWithoutChangeUnitConstructor() { + ChangeLogRuntimeImpl changeLogRuntime = getChangeLogRuntime(new DependencyManager()); + assertNotNull(changeLogRuntime.getInstance(ChangeUnitWithValidConstructor.class)); + } + + @Test + public void shouldCreateInstanceWithDefaultConstructor() { + ChangeLogRuntimeImpl changeLogRuntime = getChangeLogRuntime(new DependencyManager()); + assertNotNull(changeLogRuntime.getInstance(ChangeUnitWithDefaultConstructor.class)); + } + + @Test + public void shouldCreateInstanceWhenOneValidConstructorExistWithChangeUnitConstructor() { + ChangeLogRuntimeImpl changeLogRuntime = getChangeLogRuntime(new DependencyManager()); + ChangeUnitWithValidConstructorsHavingChangeUnitConstructor instance = + (ChangeUnitWithValidConstructorsHavingChangeUnitConstructor) changeLogRuntime + .getInstance(ChangeUnitWithValidConstructorsHavingChangeUnitConstructor.class); + assertNotNull(instance); + assertEquals(ChangeUnitWithValidConstructorsHavingChangeUnitConstructor.DUMMY_VALUE, instance.getDummy()); + } + private SortedSet createInitialChangeLogsByPackage(Class... executorChangeLogClass) { List packages = Stream.of(executorChangeLogClass) .map(clazz -> clazz.getPackage().getName()) From df2519b93564857e48b34138d57051f5508bd323 Mon Sep 17 00:00:00 2001 From: yadhuksp Date: Sun, 19 Jun 2022 13:27:09 +0530 Subject: [PATCH 7/8] fix annotation doc in ChangeUnit --- .../src/main/java/io/mongock/api/annotations/ChangeUnit.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mongock-core/mongock-api/src/main/java/io/mongock/api/annotations/ChangeUnit.java b/mongock-core/mongock-api/src/main/java/io/mongock/api/annotations/ChangeUnit.java index 290f750c2..3dac8746c 100644 --- a/mongock-core/mongock-api/src/main/java/io/mongock/api/annotations/ChangeUnit.java +++ b/mongock-core/mongock-api/src/main/java/io/mongock/api/annotations/ChangeUnit.java @@ -18,7 +18,7 @@ * The concept is basically the same, a class that wraps the logic of the migration *

* Classes annotated with @ChangeUnit must have the following: - * - One(and only one) one valid constructor annotated with @ChangeUnitConstructor(mandatory if more than one constructor exist) + * - One(and only one) one valid constructor annotated with @ChangeUnitConstructor(mandatory if more than one constructor exist after version 6) * - One(and only one) method annotated with @Execution(mandatory) * - One(and only one) method annotated with @RollbackExecution(mandatory) * - At most, one method annotated with @BeforeExecution(optional) From 7dadea8c346a85cea7cbfa922722879017cc0828 Mon Sep 17 00:00:00 2001 From: yadhuksp Date: Wed, 22 Jun 2022 16:50:34 +0530 Subject: [PATCH 8/8] replace use of stream supplier to array --- .../runner/core/executor/ChangeLogRuntimeImpl.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java b/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java index dda6421a6..79b7ab2ed 100644 --- a/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java +++ b/mongock-core/mongock-runner/mongock-runner-core/src/main/java/io/mongock/runner/core/executor/ChangeLogRuntimeImpl.java @@ -129,15 +129,16 @@ private Constructor getConstructor(Class type) { } private Constructor findDefaultConstructor(Class type) { - Supplier>> constructorSupplier = () -> Arrays.stream(type.getConstructors()); - if (constructorSupplier.get().count() > 1) { + Constructor[] constructors = type.getConstructors(); + if (constructors.length == 0) { + throw new MongockException("Mongock cannot find a valid constructor for changeUnit[%s]", type.getName()); + } + if (constructors.length > 1) { logger.warn("Mongock found multiple constructors for changeUnit[{}]. " + "It's recommended to annotate the one you want Mongock to use with @ChangeUnitConstructor. " + "FROM VERSION 6 THIS WILL CAUSE AN ERROR ", type.getName()); } - return constructorSupplier.get() - .findFirst() - .orElseThrow(() -> new MongockException("Mongock cannot find a valid constructor for changeUnit[%s]", type.getName())); + return constructors[0]; } private Optional> findChangeUnitConstructor(Class type) {