Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FlywayException: Found more than one migration with version when multiple locations named with the same roots #606

Closed
greggulrajani opened this issue Sep 17, 2013 · 1 comment

Comments

@greggulrajani
Copy link

@greggulrajani greggulrajani commented Sep 17, 2013

  • Version 2.2.1
  • Spring 3.x

Flyway spring config:

<bean id='flyway' class='com.googlecode.flyway.core.Flyway' init-method='migrate'>
        <property name='dataSource' ref='dataSource' />

        <property name='InitOnMigrate'>
            <value>true</value>
        </property>
        <property name='table'>
            <value>flyway-version-core</value>
        </property>

        <property name='locations'>
            <list>
                <value>migrations-nuclear-core</value>
                <value>migrations-nuclear-core-data-${runtimeMode}</value> 
            </list>
        </property>
    </bean>

In JarFileClassPathLocationScanner the line entryName.startsWith('migrations-nuclear-core') acts like migrations-nuclear-core* and adds the *.sql files in migrations-nuclear-core-data-dev and migrations-nuclear-core. The caller than iterates over the next location migrations-nuclear-core-data-dev and matches the same file found in the previous location.

    private Set<String> findResourceNamesFromJarFile(JarFile jarFile, String location) throws IOException {
        Set<String> resourceNames = new TreeSet<String>();

        Enumeration<JarEntry> entries = jarFile.entries();
        while (entries.hasMoreElements()) {
            String entryName = entries.nextElement().getName();
            if (entryName.startsWith(location)) {
                resourceNames.add(entryName);
            }
        }

        return resourceNames;
    }

Thanks for the hard work on Flyway !

below is patch for a possible fix.


diff --git a/flyway-core/src/main/java/com/googlecode/flyway/core/util/scanner/classpath/JarFileClassPathLocationScanner.java b/flyway-core/src/main/java/com/googlecode/flyway/core/util/scanner/classpath/JarFileClassPathLocationScanner.java
index a49c37b..9f6279d 100644
--- a/flyway-core/src/main/java/com/googlecode/flyway/core/util/scanner/classpath/JarFileClassPathLocationScanner.java
+++ b/flyway-core/src/main/java/com/googlecode/flyway/core/util/scanner/classpath/JarFileClassPathLocationScanner.java
@@ -15,8 +15,6 @@
  */
 package com.googlecode.flyway.core.util.scanner.classpath;

-import com.googlecode.flyway.core.util.scanner.classpath.ClassPathLocationScanner;
-
 import java.io.IOException;
 import java.net.JarURLConnection;
 import java.net.URISyntaxException;
@@ -90,6 +88,7 @@ public class JarFileClassPathLocationScanner implements ClassPathLocationScanner
      * @throws java.io.IOException when reading the jar file failed.
      */
     private Set<String> findResourceNamesFromJarFile(JarFile jarFile, String location) throws IOException {
+        location += location.endsWith("/") ? "" : "/";
         Set<String> resourceNames = new TreeSet<String>();

         Enumeration<JarEntry> entries = jarFile.entries();
diff --git a/flyway-core/src/test/java/com/googlecode/flyway/core/util/scanner/classpath/ClassPathScannerSmallTest.java b/flyway-core/src/test/java/com/googlecode/flyway/core/util/scanner/classpath/ClassPathScannerSmallTest.java
index 16dd4d7..7b6a483 100644
--- a/flyway-core/src/test/java/com/googlecode/flyway/core/util/scanner/classpath/ClassPathScannerSmallTest.java
+++ b/flyway-core/src/test/java/com/googlecode/flyway/core/util/scanner/classpath/ClassPathScannerSmallTest.java
@@ -15,6 +15,13 @@
  */
 package com.googlecode.flyway.core.util.scanner.classpath;

+import java.io.IOException;
+import java.util.Arrays;
+
+import org.junit.Test;
+import org.mockito.MockSettings;
+import org.mockito.internal.creation.MockSettingsImpl;
+
 import com.googlecode.flyway.core.api.FlywayException;
 import com.googlecode.flyway.core.api.migration.jdbc.JdbcMigration;
 import com.googlecode.flyway.core.dbsupport.db2.DB2MigrationMediumTest;
@@ -23,17 +30,9 @@ import com.googlecode.flyway.core.resolver.jdbc.dummy.V2__InterfaceBasedMigratio
 import com.googlecode.flyway.core.resolver.jdbc.dummy.V4__DummyExtendedAbstractJdbcMigration;
 import com.googlecode.flyway.core.resolver.jdbc.dummy.Version3dot5;
 import com.googlecode.flyway.core.util.Resource;
-import com.googlecode.flyway.core.util.scanner.classpath.ClassPathScanner;
-import com.googlecode.flyway.core.util.scanner.classpath.UrlResolver;
 import com.googlecode.flyway.core.util.scanner.classpath.jboss.JBossVFSv2UrlResolver;
-import org.junit.Test;
-import org.mockito.MockSettings;
-import org.mockito.internal.creation.MockSettingsImpl;
-
-import java.util.Arrays;

-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;

 /**
  * Tests for ClassPathScanner.
@@ -149,4 +148,12 @@ public class ClassPathScannerSmallTest {

         assertTrue(Arrays.asList(classes).contains(MockSettingsImpl.class));
     }
+
+
+    @Test
+    public void scanForSpecificPathWhenMultiplePathsExist() throws IOException {
+        Resource[] resources = new ClassPathScanner().scanForResources("net/sourceforge/jtds/jdbc", "", ".class");
+        assertEquals(54, resources.length);
+
+    }
 }


@axelfontaine
Copy link
Contributor

@axelfontaine axelfontaine commented Apr 15, 2014

Sorry for the very late reply! Thanks you so much for submitting the bug report, doing the investigation and providing a fix!

My apologies for not merging this sooner.

P.S.: I've added you to the hall of fame page (flyway-3.0 branch until merged).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.