Load resource from anywhere in classpath
If all else fails you could use two different file names, say props-default.properties
inside myJar.jar
and props.properties
to override on the command-line. In your code, you'd try loading the props.properties
file first and fallback to props-default.properties
if it wasn't found.
can I load resource from classpath if set to any directory?
One thing to pay attention to when using getResourceAsStream
is the format of the resource name that you are retrieving. By default if you do not specify a path, e.g., "autopublisherpath.cfg", the classloader will expect that the resource being specified is within the same package as the Class on which you executed the getResourcesAsStream
method. The reason for this behavior can be found in the JVM documentation for getResourceAsStream:
- If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'.
- Otherwise, the absolute name is of the following form:
modified_package_name/name
In your particular example, if the Config
class was located in the com.test.config package, then the resource name of "autopublisherpath.cfg" would be converted to "/com/test/config/autopublisherpath.cfg" (period in package is replaced with a '/' character). As a result, keeping with your original project hierarchy, you would need to place the file into the location:
autopublisher/resources/config/com/test/config
where autopublisher/resources/config
was added as part of application's execution classpath.
If you are looking to add a specific config directory to your classpath and want the file to be located in the root of that directory, then you need to prefix the name of the file with a '/' character, which specifies that the resource should be in the root package of the classpath.
InputStream iStream = Config.class.getResourceAsStream("/autopublisherpath.cfg");
Using this code, you should be able to add the resource/config
directory to your classpath and read the file as expected.
On a side note, the getResourceAsStream
method loads the resource using the Classloader of the class from which it was executed (in this case Config). Unless your application uses multiple class loaders, you can perform the same function from any of your class instances using this.getClass().getResourceAsStream(...)
.
Accessing resource files from external modules
While you are using the java
command to launch an application as follows:-
java -p target/classes:target/dependency -m framework.core/com.framework.Main
you are specifying the modulepath using the option
-p
aternate for--module-path
which would look up into target/classes and target/dependency for your modules.Alongside, using
-m
alternate for--module
specifies the initial module to resolve with the nameframework.core
and constructs the module graph with the main class to execute explicitly listed ascom.framework.Main
.
Now, the problem here seems to be that the module framework.core
doesn't requires
or read playground.api
module because of which the module graph doesn't include the desired module consisting of the actual resource config.yml
.
As suggested by @Alan, a good way to list out the module resolution output during startup is to make use of the --show-module-resolution
option.
I just naively tried to opens src/main/resources, doesn't compile ofc
Since the resource in your module is at the root level, it is, therefore, not encapsulated and does not need to be opened or exported to any other module.
In your case, you just need to make sure that the module playground.api
ends up in the module graph and then the resource would be accessible to the application. To specify root modules to resolve in addition to the initial module, you can make use of the --add-modules
option.
Hence the overall solution to work for you along with some debugging shall be :
java --module-path target/classes:target/dependency
--module framework.core/com.framework.Main
--add-modules playground.api
--show-module-resolution
Reading a file from a jar, or anywhere on the classpath?
I don't understand your problem. Resources from src/main/resources
are automatically copied over to target/classes
and are thus available on the classpath under Maven and Eclipse relatively to the root level at the same location (unless your Eclipse project is not properly configured).
And when packaged inside a JAR, the content of target/classes
is packaged "as is" so nothing is changed.
In other words, accessing your file.txt
like this is perfectly fine (and this is actually how things are documented):
// Retrieve resource
InputStream is = getClass().getResourceAsStream( "/file.txt" );
// Do something with the resource
...
If you have a problem somewhere, please clarify.
Update: I did a quick test with the maven-eclipse-plugin and I can't reproduce your problem:
$ mvn archetype:generate -DgroupId=com.stackoverflow -DartifactId=q2467362 -Dversion=1.0-SNAPSHOT
...
$ cd q2467362
$ mkdir -p src/main/resources
$ mvn eclipse:eclipse
...
$ cat .classpath
<classpath>
<classpathentry kind="src" path="src/test/java" output="target/test-classes" including="**/*.java"/>
<classpathentry kind="src" path="src/main/java" including="**/*.java"/>
<classpathentry kind="src" path="src/main/resources" excluding="**/*.java"/>
<classpathentry kind="output" path="target/classes"/>
<classpathentry kind="var" path="M2_REPO/junit/junit/3.8.1/junit-3.8.1.jar" sourcepath="M2_REPO/junit/junit/3.8.1/junit-3.8.1-sources.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
</classpath>
The directory src/main/resources
is added as source folder as expected. Can you show your POM (especially the resources
element if you define one)?
How do I load a file from resource folder?
Try the next:
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream("test.csv");
If the above doesn't work, various projects have been added the following class: ClassLoaderUtil
1 (code here).2
Here are some examples of how that class is used:
src\main\java\com\company\test\YourCallingClass.java
src\main\java\com\opensymphony\xwork2\util\ClassLoaderUtil.java
src\main\resources\test.csv
// java.net.URL
URL url = ClassLoaderUtil.getResource("test.csv", YourCallingClass.class);
Path path = Paths.get(url.toURI());
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
// java.io.InputStream
InputStream inputStream = ClassLoaderUtil.getResourceAsStream("test.csv", YourCallingClass.class);
InputStreamReader streamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(streamReader);
for (String line; (line = reader.readLine()) != null;) {
// Process line
}
Notes
- See it in The Wayback Machine.
- Also in GitHub.
How to locate all resources in classpath with a specified name?
You can use Enumeration getResources(String name) on the class loader to achieve the same.
For example:
Enumeration<URL> enumer = Thread.currentThread().getContextClassLoader().getResources("/Path/To/xyz.properties");
while (enumer.hasMoreElements()) {
System.out.print(enumer.nextElement());
}
Java: Loading resources from the file system
What I would do, if possible, is package your images in with your Jar.
That way you don't have to worry about where your Jar is launched from.
You would then need to load images similar to the following:
InputStream stream = this.getClass().getClassLoader().
getResourceAsStream("/images/logo.png");
Related Topics
Integer.Valueof() VS. Integer.Parseint()
How to Manage Exceptions Thrown in Filters in Spring
How to Build Sources Jar with Gradle
What Does the "Assert" Keyword Do
How to Create a Sub Array from Another Array in Java
Spring Cache @Cacheable - Not Working While Calling from Another Method of the Same Bean
Generic Type Parameter Naming Convention for Java (With Multiple Chars)
Timer & Timertask Versus Thread + Sleep in Java
Why Can't I Declare Static Methods in an Interface
Synchronization of Non-Final Field
Spring Boot Multiple Datasource
How to Change an Eclipse Default Project into a Java Project
Java Arraylist - How to Tell If Two Lists Are Equal, Order Not Mattering
Differencebetween Closeablehttpclient and Httpclient in Apache Httpclient API
Barcode Scanner Implementation on Java
How to Solve "Java.Io.Ioexception: Error=12, Cannot Allocate Memory" Calling Runtime#Exec()
How to Terminate a Thread Blocking on Socket Io Operation Instantly