0

I have two projects:

  1. Main: M
  2. Dependency: D

Project D has a subdirectory called 'xsd' where it has a few XSD files that it uses for validation.

This is the piece of code in project D that retrieves these XSD files:

private List<StreamSource> retrieveSchemaDefinitionsFromClasspath(String classpathXsdDir, String schemaDefinitionFilePattern) {
  ClasspathResourceManager resourceManager = new ClasspathResourceManager()
  List<String> schemaDefinitionFileNames = resourceManager.getReader(classpathXsdDir).text.split()
  schemaDefinitionFileNames.findAll { it ==~ schemaDefinitionFilePattern }.collect {
    new StreamSource(resourceManager.getReader("$classpathXsdDir/$it"))
  }
}

Now, this piece of code works well when I run my test cases.

However, when I use project D as a dependency inside project M, I get a NullPointerException on this line of the above method:

  List<String> schemaDefinitionFileNames = resourceManager.getReader(classpathXsdDir).text.split()

I've looked at this answer: Load jar file contained within another jar file not working which points to the JarClassLoader turorial: http://docs.oracle.com/javase/tutorial/deployment/jar/jarclassloader.html

However, from what I could gather from the JarClassLoader tutorial, it looks like I need to specify the name of the jar.

But, I want to be able to seamlessly use the dependency jar produced by project D in any project without having to worry about what project/jar D does to load it's reasources.

So, what is the best way to approach this problem?

Thanks!

Community
  • 1
  • 1
nemo
  • 1,504
  • 3
  • 21
  • 41
  • What are you using for dependency management? There's easy ways to do this with Maven, for example. – danehammer Nov 23 '15 at 20:52
  • @danehammer I'm using gradle for dependency management. So, the jar artifact produced by project D is installed in my maven repository and it is being declared as a dependency inside project M's build.gradle. – nemo Nov 23 '15 at 21:05

1 Answers1

1

You can use Class#getResource(String) to do exactly what I think you're going for. It's used in service lookup patterns a lot, like for finding implementations of an SPI.

Beware, the classpath lookup can get very slow in large classpaths. You want to cache the answer eternally, most likely. In some cases that might still be too slow (especially if it doesn't get primed by a bootstrapping area of your code).

danehammer
  • 416
  • 3
  • 13
  • Hey @danehammer, I changed the method to use this.getClass().getResourceAsStream(...) method (the ClasspathResource manager uses .getClass().getClassLoader().getResourcesAsStream(...)) and I have basically the same problem. When I print out what is at '/' using the 'getClass().getResourceAsStream(...)', the directory I'm looking for is not there. HOwever, when I 'unzip -l' my dependency jar, it is infact there. – nemo Nov 23 '15 at 23:32
  • I think I've found the problem. It's got to do with me trying to dynamically pick up all the files under the 'xsd' directory. It seems to work in my test cases, but when I use the code as a packaged jar dependency, there seems to be no way to list contents of a 'directory'. Do you know if there is a way to do this? Otherwise, I'll just have to hard code the file names. – nemo Nov 24 '15 at 00:29
  • So what is the test cases doing differently as far as classloaders? The doc I linked indicated it delegates to the classloader, so maybe you get a different class loader in the test scenario. Perhaps you could skip delegation and call the System one directly (like the doc shows). Or maybe groovy and gradle are doing something else with classloading and you need to delegate to them. – danehammer Nov 24 '15 at 04:39