Loading a JAR on the classpath from a network drive #372

Closed
mrmeyers99 opened this Issue Aug 9, 2012 · 11 comments

3 participants

@mrmeyers99

We have a scenario where our local Maven repo is on a network drive. It seems to work fine for all the builds except the ones that use Cucmber JVM. It fails at runtime when we try to execute the tests. If I point the maven repo to my local machine everything works fine. I've tried it on both 1.08 and 1.09.

Here's what I have in my settings.xml:

<localRepository>\\hostname\SHARED_TOOLS\maven\repository\</localRepository>

Here is the stack trace:

[14:25:10][initializationError] cucumber.runtime.CucumberException: java.io.FileNotFoundException: E:\shared_tools\maven\repository\info\cukes\cucumber-java\1.0.8\cucumber-java-1.0.8.jar (The system cannot find the path specified)
[14:25:10][initializationError] 
cucumber.runtime.CucumberException: java.io.FileNotFoundException: E:\shared_tools\maven\repository\info\cukes\cucumber-java\1.0.8\cucumber-java-1.0.8.jar (The system cannot find the path specified)
    at cucumber.io.ClasspathIterable.iterator(ClasspathIterable.java:43)
    at cucumber.io.ClasspathResourceLoader.getDescendants(ClasspathResourceLoader.java:31)
    at cucumber.io.ClasspathResourceLoader.instantiateSubclasses(ClasspathResourceLoader.java:54)
    at cucumber.runtime.Runtime.loadBackends(Runtime.java:70)
    at cucumber.runtime.Runtime.<init>(Runtime.java:50)
    at cucumber.junit.Cucumber.<init>(Cucumber.java:58)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:31)
    at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:24)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:24)
    at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:51)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:123)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:104)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)
    at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:172)
    at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:104)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:70)
Caused by: java.io.FileNotFoundException: E:\shared_tools\maven\repository\info\cukes\cucumber-java\1.0.8\cucumber-java-1.0.8.jar (The system cannot find the path specified)
    at java.util.zip.ZipFile.open(Native Method)
    at java.util.zip.ZipFile.<init>(ZipFile.java:127)
    at java.util.zip.ZipFile.<init>(ZipFile.java:88)
    at cucumber.io.ZipResourceIterator.<init>(ZipResourceIterator.java:20)
    at cucumber.io.ClasspathIterable.iterator(ClasspathIterable.java:34)
    ... 27 more

When I debugged it, I found on line 31 of ClasspathIterable.java, it gets a URL to the jar file. The value of that url is:

file://hostname/SHARED_TOOLS/maven/repository/info/cukes/cucumber-java/1.0.8/cucumber-java-1.0.8.jar!/cucumber/runtime

Then it calls a method called filePath(url) which has the following on line 48.

String path = new File(new URL(jarUrl.getFile()).getFile()).getAbsolutePath();

After that line, the path variable equals C:\SHARED_TOOLS\maven\repository\info\cukes\cucumber-java\1.0.8\cucumber-java-1.0.8.jar!\cucumber\runtime.

It seems that line 48 is not network-path friendly.

@aslakhellesoy
Cucumber member

Any chance you could submit a pull request that fixes this? Perhaps @lmcgrath who fixed #360 and #361 (related issue) can weigh in here.

@lmcgrath

Let me look at the code and see if there's a way to keep it from mangling the path to the JAR.

@mrmeyers99 any particular reason you're hosting a local repository from a network drive?

@lmcgrath

I've confirmed the problem. It's easily reproduced by setting your local repository to a shared windows drive and performing a build with tests.

@lmcgrath

@mrmeyers99 using a network drive for the local repository is resulting in the slowest builds I've ever seen. I'm working on a fix, but it may take a little while.

@lmcgrath

I got it working, however there's a few things to consider before I submit a pull request:

In all seriousness, I can't think of a good reason to ever load JARs from a network drive. The problem here is directly related to using a Maven local repository on a network drive, which in and of itself is a really bad practice smelling a bit like Item 2 this blog post: http://www.cubeia.com/index.php/blog/archives/41.

In short, the problem is not a shortcoming of Cucumber JVM, itself.

@mrmeyers99 because I don't know your reasons for placing your local Maven repository on a network drive, I would consider just mapping your network drive to a proper drive letter and seeing what happens.

@mrmeyers99

Sorry, I never got any e-mail so I thought no one had ever looked at this. The reason I'm using the local maven repo is that's how the TeamCity farm is setup at work. They were trying to centralize all the tools, so they put the maven installations on a central server and put the local repo settings as a global setting on the maven installation.

I think you have a valid point that it's probably not the ideal way to do it though.

@mrmeyers99

Are you sure it's not a Cucumber specific issue though? No one else has reported an issue with having the local repo on the shared server, just people using Cucumber JVM.

@lmcgrath

Map your network drive to a proper drive letter.

@mrmeyers99
@aslakhellesoy
Cucumber member

Can we close this issue?

@mrmeyers99
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment