How do I load one of the named resources from different jars in the classpath?

Let's say there is a jar main.jar

that depends on two other jars - dep1.jar

and dep2.jar

. Both dependencies are in the classpath in MANIFEST.MF from main.jar

. Each of the dependency jars has a directory foo

inside with a file bar.txt

inside:

dep1.jar
|
\--foo/
   |
   \--bar.txt

dep2.jar
|
\--foo/
   |
   \--bar.txt

      

Here is the main class main.jar

:

public class App
{
    public static void main( String[] args ) {
        ApplicationContext ctx = new StaticApplicationContext();
        Resource barResource = ctx.getResource("classpath:foo/bar.txt");
    }
}

      

Which of the two files bar.txt

will be downloaded? Is there a way to specify in the url of the jar resource from which the file should be loaded?

+5


source to share


5 answers


Which one you get is undefined. However, you can use

Resource[] barResource = ctx.getResources("classpath*:foo/bar.txt");

      



to get them both (all). URL

c Resource

will tell you where jar

they are (although I do not recommend that you start programming based on this information).

+2


source


Flip the quarter over, the one you get. It will most likely be one of the highest in alphabetical order, so in your case, one inside dep1.jar. Both files have the same classpaths (foo.Bar), and while it should look like throwing a compile-time exception, this is not going to happen because it will just package both banks, and not try to compile / view the file (this particular file) since it is a file. txt.



+1


source


You would not expect a compile-time exception, since resource loading is a run-time process.

You cannot specify which jar resource will come from the code and this is a common problem, especially when someone is linking something like log4j.properties in the jar file.

What you can do is specify the order of the jars in your classpath and it will take the resource from the first one in the list. This is tricky because when you use something like ivy or maven for the classpath dependencies, you have no control over the order in the classpath (in all eclipse plugins).

The only reliable solution is to name the resources something else, or put them in separate packages.

+1


source


The spec states that the first class / resource on the classpath is accepted (AFAIK).

However, I would try:

Dep1Class.class.getResource("/foo/bar.txt");
Dep2Class.class.getResource("/foo/bar.txt");

      

Since Class.getResource cannot take resources from another jar, unlike the system class loader.

With a little luck, you won't need to play ClassLoader

around with and hava loading the loader of another dep2.jar class.

0


source


As @Sotirios said, you can get all resources with the same name using ctx.getResources(...)

code like this:

    ApplicationContext ctx = new StaticApplicationContext();
    Resource[] resources = ctx.getResources("classpath*:/foo/bar.txt");

    for (Resource resource : resources) {

        System.out.println("resource file: " + resource.getURL());

        InputStream is = new FileInputStream(resource.getFile());

        if (is == null) {
            System.out.println("resource is null");
            System.exit(-1);
        }

        Scanner scanner = new Scanner(is);

        while(scanner.hasNextLine()) {
            System.out.println(scanner.nextLine());
        }
    }

      

0


source







All Articles