How to load one of same named resources from different jars in a classpath?

java load image from resource folder
resourceutils.getfile not working in jar
access resources in jar
how to add resource folder in jar file
get resource folder path in java
spring read file from resources folder
java load properties file from resources
jar cannot find resource file

Let's say there is a jar main.jar which depends on two other jars - dep1.jar and dep2.jar. Both dependencies are in a classpath in MANIFEST.MF of main.jar. Each of dependency jars has a directory foo inside with a file bar.txt within:

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

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

Here is a main class of 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 two bar.txt files will be loaded? Is there a way to specify in a resource URL a jar the file should be loaded from?

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

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

to get them both (all). The URL in the Resource will tell you which jar they are in (though I don't recommend you start programming based on that information).

Loading same-name resource from multiple JARs, Loading same-name resource from multiple JARs. To get access to all of these resources in different jars, one has to use a ClassLoader, which has a method for this. The returned Enumeration can be conveniently converted to a List using a Collections function. Enumeration<URL> resEnum = MyClass. Resource with same path and name may exist in more than one JAR file on the classpath. Common cases are resources following a convention or that are part of a packaging specification. Examples for such resources are. META-INF/MANIFEST.MF; META-INF/beans.xml (CDI Spec) ServiceLoader properties containing implementation providers

Flip a quarter, that's the one you'll get. Most likely, it will be the one highest alphabetically, so in your case the one inside dep1.jar. The files both have identical classpaths (foo.Bar), and while this should look to throw a compile time exception, it will not because it will just package both jars up and not try to compile/look at the (this specific file) file as it is a .txt file.

Java Language, Resource with same path and name may exist in more than one JAR file on the classpath. Common cases are resources following a convention or that are part  John Coss wrote:My conclusion, for the time being is, that on classpath only resources from jar than contains requested static main method are loaded. Resources from other jar files are unavailable, except for java compiled class files. I would disagree, as I was able to load XML files from other jars using your getResourceAsStream().

You wouldn't expect a compile time exception as resource loading is a run time process.

You can't specify which jar the resource will come from in code, and this is a common issue, particularly when someone bundles something like log4j.properties into a jar file.

What you can do is specify the order of jars in your classpath, and it will pick up the resource from the first one in the list. This is tricky in itself as when you are using something like ivy or maven for classpath dependencies, you are not in control of the ordering in the classpath (in the eclipse plugins at any rate).

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

ClassPath doesn't support duplicated resource names · Issue #1267 , INF file which is contained in every jar file). In Java, loading multiple resources with the same name is accomplished via the ClassLoader. Realistically, no one uses '$' so I won't feel bad if we decide to ignore that possibility. Java . A comparison of different ways of resources loading in Java. Followings are the preferred ways to load resources in classpath. this.getClass().getResource(resourceName): It tries to find the resource in the same package as 'this' class unless we use absolute path starting with '/'

The specification says that the first class/resource on the class path is taken (AFAIK).

However I would try:

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

As Class.getResource works cannot take resources from another jar, as opposed to the system class loader.

With a bit of luck, you will not need to play with ClassLoaders and hava a different class loader load dep2.jar.

Accessing Resources, The name of a resource is independent of the Java implementation; each directory, ZIP file, or JAR file entry in the CLASSPATH for the resource file, and, if found, A resource may be found in a different entry in the CLASSPATH than the location The Class class implements several methods for loading resources. This article deals with different approaches to load multiple versions of the same class. The problem: . Many times during the development you will need to work with different libraries versions

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

    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());
        }
    }

Setting the class path, For .class files in a named package, the class path ends with the directory that The JDK, the JVM and other JDK tools find classes by searching the Java You only need to set the class path when you want to load a class that's (a) not in the classes and resources in foo are loaded before JAR files in foo , or vice versa. The ClassLoader methods search each directory, ZIP file, or JAR file entry in the CLASSPATH for the resource file, and, if found, returns either an InputStream, or the resource name. If not found, the methods return null. A resource may be found in a different entry in the CLASSPATH than the location where the class file was loaded.

Understanding the Tomcat Classpath, Tomcat does not resolve classpaths in the same way as other Java programs Incidentally, this is the one place where environment variables do matter, These resources are only visible to the web application that loads them. The Common class loader loads all classes and JAR files contained in $​CATALINA_HOME/lib. This is counterintuitive but in hindsight makes sense: We can create two different classes with the same package and name, ship them in two jars and put them in two different class loaders. One

6. Resources, File if the class path resource resides in the file system, but not for classpath It's useful for loading content from any given byte array, without having to Similarly, one can force a UrlResource to be used by specifying any of the Try this test with files that have the same name but are placed inside two different locations. Resource with same path and name may exist in more than one JAR file on the classpath. Common cases are resources following a convention or that are part of a packaging specification. Examples for such resources are. META-INF/MANIFEST.MF; META-INF/beans.xml (CDI Spec) ServiceLoader properties containing implementation providers

JAR (file format), A JAR (Java ARchive) is a package file format typically used to aggregate many Java class files and associated metadata and resources (text, images, etc.) into one file for distribution. For instance, a Classpath entry can be used to specify other JAR files to load with the It contains name-value pairs organized in sections. With the traditional classpath approach of instructing an application to load classes from JARs, the JAR file containing the .class file needs to end with the .jar extension. The next screen snapshot demonstrates what happens when the HelloWorld.jar is renamed HelloWorld.backup in the same classpath-referenced directory.

Comments
  • @Jenson Two classes: bar.txt is not a class, so there won't be any conflict.
  • That's not true, .getResource() called on a class with an absolute path (slash at the beginning) looks at the root of the classpath. The first .jar with the internal structure /foo/bar.txt will be chosen.
  • @cobby thanks, that seems to be a misconception I acquired since long ago. Maybe because of getClass().getResource("foo.txt") being dangerous; maybe because of class loaders.