Maven 3.0.4, Windows, Oracle Java SE 1.6.0_30
Consider a software module 'module-1' having the following properties:
1. Runtime class-path is too long for Windows command-line or environment variables.
2. ClassLoader.getSystemClassLoader() is used to scan class-path URLs.
3. Thread.currentThread().getContextClassLoader() is used to scan class-path URLs.
As I understand it the following then holds true:
(1) and (3) combined prevents us from using useSystemClassLoader=true with useManifestOnlyJar=false
(2) prevents us from using the Isolated class-loader as solved by setting useSystemClassLoader=false
What we really want is to use the 'manifest-only jar' configuration with the surefire-booter (which is the current 2.12.4 default configuration for surefire of useSystemClassLoader=true and useManifestOnlyJar=true), and for all class-loaders visible to module-1 to appear as if we did not have only the surefire-booter jar on the class-path when scanning elements from java.net.URLClassLoader.getURLs().
Attached surefireclassloaderweaknessdemo.zip which contains a minimal maven demo project with junit tests that fail in order to demonstrate this issue.
Attached ClasspathConfiguration.diff which is a 'git diff' suggestion on how to resolve this issue. I have put the text 'SUREFIRE-XXX' in the diff where 'XXX' should probably be replaced with the appropriate issue number (this issue).
Steps to reproduce:
1. Unzip attached surefireclassloaderweaknessdemo.zip
2. enter surefireclassloaderweaknessdemo folder and run 'mvn test'
3. Observe that unit-tests fail
Steps to make unit-tests pass:
1. Apply/patch attached ClasspathConfiguration.diff to git master (currently 2.13-SNAPSHOT)
2. Run 'mvn install' to update surefire 2.13-SNAPSHOT
3. Edit surefireclassloaderweaknessdemo/pom.xml and switch surefire plugin version to 2.13-SNAPSHOT
4. enter surefireclassloaderweaknessdemo folder and run 'mvn test'
5. Observe that unit-tests passes
The solution (as included in the diff file) uses reflection to access the 'java.net.URLClassLoader.addURL(java.net.URL)' method and adds elements that are available (they really are when using other parts of class-loader APIs) on the class-path.
I believe this solution should benefit all software run from surefire that attempt to scan the class-path using java.net.URLClassLoader.getURLs().
For those interested in where this issue turned up, read on:
This issue has turned up while working with a large web-application that uses apache Jasper to render JSP pages. The JspServlet does in fact search the list of URLs returned by ((URLClassLoader) Thread.currentThread().getContextClassLoader()).getURLs() for jars with META-INF folders containing tld (taglib) files. The symptoms were that under the default maven-surefire configuration (as also used in the attached demo project) the Jasper JSP compiler was unable to detect taglibs that were definetly there and worked in all other contexts (e.g. running junit embedded in Eclipse or IntelliJ IDE, running the application in deployed production context, running junit using a Gradle project file)