From f72f6a1c0e2847b4dc8f058621df2e6544376b39 Mon Sep 17 00:00:00 2001 From: Reto Breitenmoser Date: Fri, 22 May 2015 18:21:41 +0200 Subject: [PATCH] [Major] refactored the handling with code and data migration versions - The version handling with code and data migrations was messed up. The migration version was set after the data migration and then the code migration used this value for further processing. Now there are two attributes for the migration version (code and data). The files for the data migration and the classes for the code migration have now individual versions. --- .../li/strolch/migrations/CodeMigration.java | 14 +++++ .../CurrentMigrationVersionQuery.java | 52 +++++++++++++------ .../li/strolch/migrations/DataMigration.java | 12 +++++ .../java/li/strolch/migrations/Migration.java | 22 ++++---- .../strolch/migrations/MigrationVersion.java | 37 +++++++++++++ .../li/strolch/migrations/Migrations.java | 34 ++++++------ .../strolch/migrations/MigrationsHandler.java | 12 ++--- .../migrations/RunMigrationsAction.java | 4 +- .../li/strolch/migrations/MigrationsTest.java | 18 +++---- 9 files changed, 146 insertions(+), 59 deletions(-) create mode 100644 li.strolch.service/src/main/java/li/strolch/migrations/MigrationVersion.java diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/CodeMigration.java b/li.strolch.service/src/main/java/li/strolch/migrations/CodeMigration.java index 8d2b5a7f7..1cd48a1b7 100644 --- a/li.strolch.service/src/main/java/li/strolch/migrations/CodeMigration.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/CodeMigration.java @@ -18,6 +18,9 @@ package li.strolch.migrations; import java.io.File; import li.strolch.agent.api.ComponentContainer; +import li.strolch.command.parameter.SetParameterCommand; +import li.strolch.model.Resource; +import li.strolch.model.parameter.StringParameter; import ch.eitchnet.privilege.model.Certificate; import ch.eitchnet.utils.Version; @@ -35,4 +38,15 @@ public class CodeMigration extends Migration { public void migrate(ComponentContainer container, Certificate certificate) { logger.info("[" + this.realm + "] Running no-op migration " + this.version); } + + @Override + protected void setNewVersion(SetParameterCommand cmd, Resource migrationsRes) { + StringParameter currentCodeVersionP = migrationsRes.getParameter(BAG_PARAMETERS, PARAM_CURRENT_CODE_VERSION); + + cmd.setParameter(currentCodeVersionP); + cmd.setValueAsString(getVersion().toString()); + + } + + } diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/CurrentMigrationVersionQuery.java b/li.strolch.service/src/main/java/li/strolch/migrations/CurrentMigrationVersionQuery.java index d4b7b6cf5..ae056e4d1 100644 --- a/li.strolch.service/src/main/java/li/strolch/migrations/CurrentMigrationVersionQuery.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/CurrentMigrationVersionQuery.java @@ -18,7 +18,8 @@ package li.strolch.migrations; import static li.strolch.migrations.Migration.BAG_PARAMETERS; import static li.strolch.migrations.Migration.MIGRATIONS_ID; import static li.strolch.migrations.Migration.MIGRATIONS_TYPE; -import static li.strolch.migrations.Migration.PARAM_CURRENT_VERSION; +import static li.strolch.migrations.Migration.PARAM_CURRENT_DATA_VERSION; +import static li.strolch.migrations.Migration.PARAM_CURRENT_CODE_VERSION; import java.util.HashMap; import java.util.Map; @@ -35,7 +36,7 @@ import ch.eitchnet.utils.Version; public class CurrentMigrationVersionQuery { private ComponentContainer container; - private Map currentVersions; + private Map currentVersions; /** * @param container @@ -55,29 +56,46 @@ public class CurrentMigrationVersionQuery { Resource migrationsRes = tx.getResourceBy(MIGRATIONS_TYPE, MIGRATIONS_ID); if (migrationsRes == null) { - this.currentVersions.put(realmName, Version.emptyVersion); + this.currentVersions.put(realmName, new MigrationVersion(Version.emptyVersion,Version.emptyVersion)); continue; } - StringParameter currentVersionP = migrationsRes.getParameter(BAG_PARAMETERS, PARAM_CURRENT_VERSION); - if (currentVersionP == null) { - this.currentVersions.put(realmName, Version.emptyVersion); - continue; + StringParameter currentDataVersionP = migrationsRes.getParameter(BAG_PARAMETERS, PARAM_CURRENT_DATA_VERSION); + StringParameter currentCodeVersionP = migrationsRes.getParameter(BAG_PARAMETERS, PARAM_CURRENT_CODE_VERSION); + + if (currentDataVersionP == null && currentCodeVersionP == null) { + this.currentVersions.put(realmName, new MigrationVersion(Version.emptyVersion,Version.emptyVersion)); + } else if(currentDataVersionP == null && currentCodeVersionP != null) { + Version codeVersion = getVersionFromParam(currentCodeVersionP); + this.currentVersions.put(realmName, new MigrationVersion(Version.emptyVersion,codeVersion)); + } else if (currentDataVersionP != null && currentCodeVersionP == null) { + Version dataVersion = getVersionFromParam(currentDataVersionP); + this.currentVersions.put(realmName, new MigrationVersion(dataVersion,Version.emptyVersion)); + } else { + Version dataVersion = getVersionFromParam(currentDataVersionP); + Version codeVersion = getVersionFromParam(currentCodeVersionP); + this.currentVersions.put(realmName, new MigrationVersion(dataVersion,codeVersion)); } - - String versionS = currentVersionP.getValue(); - if (!Version.isParseable(versionS)) { - throw new StrolchConfigurationException("Version value " + versionS + " is not valid for " - + currentVersionP.getLocator()); - } - - Version version = Version.valueOf(versionS); - this.currentVersions.put(realmName, version); } } } - public Map getCurrentVersions() { + /** + * @param versionS + * @return + */ + private Version getVersionFromParam(StringParameter versionP) { + String versionS = versionP.getValue(); + if (!Version.isParseable(versionS)) { + throw new StrolchConfigurationException("Version value " + versionS + " is not valid for " + + versionP.getLocator()); + } + + Version version = Version.valueOf(versionS); + return version; + } + + public Map getCurrentVersions() { return this.currentVersions; } diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/DataMigration.java b/li.strolch.service/src/main/java/li/strolch/migrations/DataMigration.java index d35aa4687..3bdea55d2 100644 --- a/li.strolch.service/src/main/java/li/strolch/migrations/DataMigration.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/DataMigration.java @@ -21,8 +21,11 @@ import java.util.Collections; import li.strolch.agent.api.ComponentContainer; import li.strolch.command.XmlImportModelCommand; +import li.strolch.command.parameter.SetParameterCommand; import li.strolch.exception.StrolchException; import li.strolch.model.ModelStatistics; +import li.strolch.model.Resource; +import li.strolch.model.parameter.StringParameter; import li.strolch.persistence.api.StrolchTransaction; import ch.eitchnet.privilege.model.Certificate; import ch.eitchnet.utils.Version; @@ -60,4 +63,13 @@ public class DataMigration extends Migration { logger.info(MessageFormat .format("[{0}] Data migration for {1} loaded {2} Resources and {3} Orders.", getRealm(), getVersion(), statistics.nrOfResources, statistics.nrOfOrders)); //$NON-NLS-1$ } + + @Override + protected void setNewVersion(SetParameterCommand cmd, Resource migrationsRes) { + StringParameter currentDataVersionP = migrationsRes.getParameter(BAG_PARAMETERS, PARAM_CURRENT_DATA_VERSION); + + cmd.setParameter(currentDataVersionP); + cmd.setValueAsString(getVersion().toString()); + } + } diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/Migration.java b/li.strolch.service/src/main/java/li/strolch/migrations/Migration.java index 6a6ce71d0..d1ecb7878 100644 --- a/li.strolch.service/src/main/java/li/strolch/migrations/Migration.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/Migration.java @@ -36,7 +36,8 @@ public abstract class Migration { public static final String MIGRATIONS_TYPE = "Migrations"; public static final String MIGRATIONS_ID = "migrations"; public static final String BAG_PARAMETERS = "parameters"; - public static final String PARAM_CURRENT_VERSION = "currentVersion"; + public static final String PARAM_CURRENT_DATA_VERSION = "currentDataVersion"; + public static final String PARAM_CURRENT_CODE_VERSION = "currentCodeVersion"; protected static final Logger logger = LoggerFactory.getLogger(CodeMigration.class); @@ -75,9 +76,13 @@ public abstract class Migration { ParameterBag bag = new ParameterBag(BAG_PARAMETERS, BAG_PARAMETERS, BAG_PARAMETERS); migrationsRes.addParameterBag(bag); - StringParameter currentVersionP = new StringParameter(PARAM_CURRENT_VERSION, PARAM_CURRENT_VERSION, - getVersion().toString()); - bag.addParameter(currentVersionP); + StringParameter currentDataVersionP = new StringParameter(PARAM_CURRENT_DATA_VERSION, + PARAM_CURRENT_DATA_VERSION, getVersion().toString()); + bag.addParameter(currentDataVersionP); + + StringParameter currentCodeVersionP = new StringParameter(PARAM_CURRENT_CODE_VERSION, + PARAM_CURRENT_CODE_VERSION, getVersion().toString()); + bag.addParameter(currentCodeVersionP); AddResourceCommand cmd = new AddResourceCommand(container, tx); cmd.setResource(migrationsRes); @@ -85,16 +90,15 @@ public abstract class Migration { tx.addCommand(cmd); } else { - - StringParameter currentVersionP = migrationsRes.getParameter(BAG_PARAMETERS, PARAM_CURRENT_VERSION); - SetParameterCommand cmd = new SetParameterCommand(container, tx); - cmd.setParameter(currentVersionP); - cmd.setValueAsString(getVersion().toString()); + + setNewVersion(cmd,migrationsRes); tx.addCommand(cmd); } } public abstract void migrate(ComponentContainer container, Certificate certificate); + + protected abstract void setNewVersion(SetParameterCommand cmd,Resource migrationsRes); } diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/MigrationVersion.java b/li.strolch.service/src/main/java/li/strolch/migrations/MigrationVersion.java new file mode 100644 index 000000000..6ead4d919 --- /dev/null +++ b/li.strolch.service/src/main/java/li/strolch/migrations/MigrationVersion.java @@ -0,0 +1,37 @@ +/** + * + */ +package li.strolch.migrations; + +import ch.eitchnet.utils.Version; + +/** + * Migration versions for data and code migrations + * + * @author Reto Breitenmoser + */ +public class MigrationVersion { + + private Version dataVersion; + private Version codeVersion; + + public MigrationVersion(Version dataVersion, Version codeVersion) { + this.dataVersion = dataVersion; + this.codeVersion = codeVersion; + } + + /** + * @return the dataVersion + */ + public Version getDataVersion() { + return dataVersion; + } + + /** + * @return the codeVersion + */ + public Version getCodeVersion() { + return codeVersion; + } + +} diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/Migrations.java b/li.strolch.service/src/main/java/li/strolch/migrations/Migrations.java index d0f7811f8..184691b84 100644 --- a/li.strolch.service/src/main/java/li/strolch/migrations/Migrations.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/Migrations.java @@ -81,20 +81,21 @@ public class Migrations { logDetectedMigrations(this.realmNames, this.dataMigrations, this.codeMigrations); } - public void runMigrations(Certificate certificate, Map currentVersions) { + public void runMigrations(Certificate certificate, Map currentVersions) { MapOfLists migrationsRan = new MapOfLists<>(); - for (Entry entry : currentVersions.entrySet()) { + for (Entry entry : currentVersions.entrySet()) { String realm = entry.getKey(); - Version currentVersion = entry.getValue(); + MigrationVersion currentVersion = entry.getValue(); if (this.verbose) logger.info("[" + realm + "] Performing all migrations after " + currentVersion); - Version nextPossibleVersion = currentVersion.add(0, 0, 1); - CodeMigration currentCodeMigration = new CodeMigration(realm, nextPossibleVersion, null); - DataMigration currentDataMigration = new DataMigration(realm, nextPossibleVersion, null); + Version nextPossibleCodeVersion = currentVersion.getCodeVersion().add(0, 0, 1); + Version nextPossibleDataVersion = currentVersion.getDataVersion().add(0, 0, 1); + CodeMigration currentCodeMigration = new CodeMigration(realm, nextPossibleCodeVersion, null); + DataMigration currentDataMigration = new DataMigration(realm, nextPossibleDataVersion, null); SortedSet dataMigrations = this.dataMigrations.get(realm); if (dataMigrations != null && !dataMigrations.isEmpty()) { @@ -131,7 +132,7 @@ public class Migrations { * @param cert * @param codeMigrationsByRealm */ - public void runCodeMigrations(Certificate cert, Map currentVersions, + public void runCodeMigrations(Certificate cert, Map currentVersions, MapOfLists codeMigrationsByRealm) { MapOfLists migrationsRan = new MapOfLists<>(); @@ -142,21 +143,21 @@ public class Migrations { if (!this.realmNames.contains(realm)) continue; - Version currentVersion = currentVersions.get(realm); + MigrationVersion currentVersion = currentVersions.get(realm); List listOfMigrations = codeMigrationsByRealm.getList(realm); SortedSet migrations = new TreeSet<>((o1, o2) -> o1.getVersion().compareTo(o2.getVersion())); migrations.addAll(listOfMigrations); - Version nextVersion = currentVersion.add(0, 0, 1); + Version nextVersion = currentVersion.getCodeVersion().add(0, 0, 1); CodeMigration nextMigration = new CodeMigration(realm, nextVersion); SortedSet migrationsToRun = migrations.tailSet(nextMigration); for (CodeMigration migration : migrationsToRun) { DBC.INTERIM.assertEquals("Realms do not match!", realm, migration.getRealm()); Version migrateVersion = migration.getVersion(); - boolean isLaterMigration = migrateVersion.compareTo(currentVersion) > 0; - DBC.INTERIM.assertTrue("Current version " + currentVersion + " is not before next " + migrateVersion, + boolean isLaterMigration = migrateVersion.compareTo(currentVersion.getCodeVersion()) > 0; + DBC.INTERIM.assertTrue("Current version " + currentVersion.getCodeVersion() + " is not before next " + migrateVersion, isLaterMigration); String msg = "[{0}] Running code migration {1} {2}"; @@ -264,15 +265,16 @@ public class Migrations { return migrationsByRealm; } - public MapOfLists getMigrationsToRun(Map currentVersions) { + public MapOfLists getMigrationsToRun(Map currentVersions) { MapOfLists migrationsToRun = new MapOfLists<>(); - for (Entry entry : currentVersions.entrySet()) { + for (Entry entry : currentVersions.entrySet()) { String realm = entry.getKey(); - Version nextPossibleVersion = entry.getValue().add(0, 0, 1); - CodeMigration currentCodeMigration = new CodeMigration(realm, nextPossibleVersion, null); - DataMigration currentDataMigration = new DataMigration(realm, nextPossibleVersion, null); + Version nextPossibleCodeVersion = entry.getValue().getCodeVersion().add(0, 0, 1); + Version nextPossibleDataVersion = entry.getValue().getDataVersion().add(0, 0, 1); + CodeMigration currentCodeMigration = new CodeMigration(realm, nextPossibleCodeVersion, null); + DataMigration currentDataMigration = new DataMigration(realm, nextPossibleDataVersion, null); SortedSet allCodeMigrations = this.codeMigrations.get(realm); if (allCodeMigrations != null) { diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/MigrationsHandler.java b/li.strolch.service/src/main/java/li/strolch/migrations/MigrationsHandler.java index 7df37654f..c14cd7f65 100644 --- a/li.strolch.service/src/main/java/li/strolch/migrations/MigrationsHandler.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/MigrationsHandler.java @@ -62,7 +62,7 @@ public class MigrationsHandler extends StrolchComponent { return this.migrations.getMigrationsRan(); } - public Map getCurrentVersions(Certificate cert) { + public Map getCurrentVersions(Certificate cert) { CurrentMigrationVersionQuery query = new CurrentMigrationVersionQuery(getContainer()); query.doQuery(cert); return query.getCurrentVersions(); @@ -75,7 +75,7 @@ public class MigrationsHandler extends StrolchComponent { Migrations migrations = new Migrations(getContainer(), getContainer().getRealmNames(), this.verbose); migrations.parseMigrations(this.migrationsPath); - Map currentVersions = getCurrentVersions(cert); + Map currentVersions = getCurrentVersions(cert); this.migrations = migrations; return this.migrations.getMigrationsToRun(currentVersions); } @@ -87,12 +87,12 @@ public class MigrationsHandler extends StrolchComponent { Migrations migrations = new Migrations(getContainer(), getContainer().getRealmNames(), this.verbose); migrations.parseMigrations(this.migrationsPath); - Map currentVersions = getCurrentVersions(cert); + Map currentVersions = getCurrentVersions(cert); this.migrations.runMigrations(cert, currentVersions); } public void runCodeMigrations(Certificate cert, MapOfLists codeMigrationsByRealm) { - Map currentVersions = getCurrentVersions(cert); + Map currentVersions = getCurrentVersions(cert); Migrations migrations = new Migrations(getContainer(), getContainer().getRealmNames(), this.verbose); this.migrations = migrations; migrations.runCodeMigrations(cert, currentVersions, codeMigrationsByRealm); @@ -138,7 +138,7 @@ public class MigrationsHandler extends StrolchComponent { QueryCurrentVersionsAction queryAction = new QueryCurrentVersionsAction(query); PrivilegeHandler privilegeHandler = getContainer().getComponent(PrivilegeHandler.class); privilegeHandler.runAsSystem(RealmHandler.SYSTEM_USER_AGENT, queryAction); - Map currentVersions = query.getCurrentVersions(); + Map currentVersions = query.getCurrentVersions(); RunMigrationsAction action = new RunMigrationsAction(this.migrations, currentVersions); @@ -185,7 +185,7 @@ public class MigrationsHandler extends StrolchComponent { QueryCurrentVersionsAction queryAction = new QueryCurrentVersionsAction(query); PrivilegeHandler privilegeHandler = getContainer().getComponent(PrivilegeHandler.class); privilegeHandler.runAsSystem(RealmHandler.SYSTEM_USER_AGENT, queryAction); - Map currentVersions = query.getCurrentVersions(); + Map currentVersions = query.getCurrentVersions(); MigrationsHandler.this.migrations = migrations; if (migrations.getMigrationsToRun(currentVersions).isEmpty()) { diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/RunMigrationsAction.java b/li.strolch.service/src/main/java/li/strolch/migrations/RunMigrationsAction.java index 6f327d329..19e539fcc 100644 --- a/li.strolch.service/src/main/java/li/strolch/migrations/RunMigrationsAction.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/RunMigrationsAction.java @@ -27,13 +27,13 @@ import ch.eitchnet.utils.Version; public class RunMigrationsAction implements SystemUserAction { private Migrations migrations; - private Map currentVersions; + private Map currentVersions; /** * @param migrations * @param currentVersions */ - public RunMigrationsAction(Migrations migrations, Map currentVersions) { + public RunMigrationsAction(Migrations migrations, Map currentVersions) { this.migrations = migrations; this.currentVersions = currentVersions; } diff --git a/li.strolch.service/src/test/java/li/strolch/migrations/MigrationsTest.java b/li.strolch.service/src/test/java/li/strolch/migrations/MigrationsTest.java index 3cffa4c95..3e4a5b4b3 100644 --- a/li.strolch.service/src/test/java/li/strolch/migrations/MigrationsTest.java +++ b/li.strolch.service/src/test/java/li/strolch/migrations/MigrationsTest.java @@ -70,10 +70,10 @@ public class MigrationsTest { public void shouldRunMigrations() { MigrationsHandler migrationsHandler = runtimeMock.getContainer().getComponent(MigrationsHandler.class); - Map currentVersions = migrationsHandler.getCurrentVersions(certificate); + Map currentVersions = migrationsHandler.getCurrentVersions(certificate); String defRealm = StrolchConstants.DEFAULT_REALM; - assertEquals("1.1.1", currentVersions.get(defRealm).toString()); - assertEquals("0.0.0", currentVersions.get("other").toString()); + assertEquals("1.1.1", currentVersions.get(defRealm).getDataVersion().toString()); + assertEquals("0.0.0", currentVersions.get("other").getCodeVersion().toString()); MapOfLists lastMigrations = migrationsHandler.getLastMigrations(); List expectedMigrations = Arrays.asList(Version.valueOf("0.1.0"), Version.valueOf("0.1.1"), @@ -86,8 +86,8 @@ public class MigrationsTest { // assert new current version currentVersions = migrationsHandler.getCurrentVersions(certificate); - assertEquals("1.1.1", currentVersions.get(defRealm).toString()); - assertEquals("0.0.0", currentVersions.get("other").toString()); + assertEquals("1.1.1", currentVersions.get(defRealm).getDataVersion().toString()); + assertEquals("0.0.0", currentVersions.get("other").getCodeVersion().toString()); MapOfLists codeMigrationsByRealm = new MapOfLists<>(); // add migrations in wrong sequence - should be fixed by migration handler @@ -98,13 +98,13 @@ public class MigrationsTest { lastMigrations = migrationsHandler.getLastMigrations(); assertEquals(1, lastMigrations.keySet().size()); - assertEquals(Arrays.asList(Version.valueOf("1.2.0"), Version.valueOf("1.2.0.a")), + assertEquals(Arrays.asList(Version.valueOf("1.0.0"),Version.valueOf("1.2.0"), Version.valueOf("1.2.0.a")), lastMigrations.getList(defRealm)); // assert new current version currentVersions = migrationsHandler.getCurrentVersions(certificate); - assertEquals("1.2.0.a", currentVersions.get(defRealm).toString()); - assertEquals("0.0.0", currentVersions.get("other").toString()); + assertEquals("1.2.0.a", currentVersions.get(defRealm).getCodeVersion().toString()); + assertEquals("0.0.0", currentVersions.get("other").getDataVersion().toString()); } private static class MyMigration0 extends CodeMigration { @@ -148,7 +148,7 @@ public class MigrationsTest { try (StrolchTransaction tx = openTx(container, cert)) { - Order fooOrder = ModelGenerator.createOrder("foo", "Foo", "Foo"); + Order fooOrder = ModelGenerator.createOrder("foo1", "Foo", "Foo"); AddOrderCommand addOrderCommand = new AddOrderCommand(container, tx); addOrderCommand.setOrder(fooOrder);