Java getClassLoader().getResourceAsStream(filename) - java

I have a Maven project. My entire code is in the folder {PROJECT_ROOT}/src/main/java. When I write the code:
InputStream input = VertxApp.class.getClassLoader().getResourceAsStream("file.txt");
String result = getStringFromInputStream(input);
System.out.println(result);
I see that the code looks for the file named "file.txt" in the folder:
{PROJECT_ROOT}/src/main/resources.
My question is why. Why doesn't it look for files in {PROJECT_ROOT}/src/main/java or in ${PROJECT_ROOT} for example?

Most Maven projects follow the structure of
src/
main/
java/
resources/
You're intended to keep your non-code resources separate from your code. The getResourceAsStream method assumes this standard is followed, so it looks for your resource starting from the resources/ directory.
See Why are project layout resources are kept separate from Java sources? for some more detailed thoughts.

When you build a maven project or run it from an IDE supporting maven, the java files from src/main/java are compiled to class files and put in PROJECT_ROOT/target/classes.
The files from src/main/resources are copied to PROJECT_ROOT/target/classes as well.
When you call VertxApp.class.getClassLoader().getResourceAsStream("file.txt") you get the classloader for the VertxApp class and this classloader will try to load the given resource from the path where the class was loaded from.
If your VertxAppclass is in the top package, the the class file will be in target/classesand the resource will be searched there as well as you specify a relative path of "file.txt", therefore you must put it in src/main/resources.
If the VertxAppclass is for example in a package named mypackagethen the class file would be in target/classes/mypackage and you should have the file in src/main/resources/mypackage so that it ends up in target/classes/mypackageas well.
If you have the VertxAppclass in a package but want to keep the file in src/main/resources(without a subdirectory), you must reference it as an absolute path like this:
VertxApp.class.getClassLoader().getResourceAsStream("/file.txt")

Related

Not able to get resource, classloader and class returns target path

I am trying to get a properties file from /src/main/resources/properties/ but for some reason the following code returns the path of target classes instead of src files. Can you please help?
System.out.println(PropTest.class.getResource("/properties/app.properties"));
System.out.println(PropTest.class.getClassLoader().getResource("properties/app.properties"));
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
System.out.println(classloader.getResource("properties/app.properties"));
PropTest prop=new PropTest();
System.out.println(prop.getClass().getResource("/properties/app.properties"));
Each line gives the same output which is:
file:/C:/Users/b./eclipse-workspace/ordermonitoring/target/classes/properties/app.properties
file:/C:/Users/b./eclipse-workspace/ordermonitoring/target/classes/properties/app.properties
file:/C:/Users/b./eclipse-workspace/ordermonitoring/target/classes/properties/app.properties
file:/C:/Users/b./eclipse-workspace/ordermonitoring/target/classes/properties/app.properties
The behavior is correct. The resources will be loaded from class path. There wont be any src folder at runtime. What you can do is make the /src/main/resources as a source folder (if you are not using maven) so that the properties will be copied to target folder.
This is the expected behaviour. For maven projects, while running, project is build and is kept in target folder always. you can also change this folder by some configuration. From this target folder, your application runs and thus your path shown in classloader.getResource() method. If you are building a jar , then your resources will be inside the jar and is always available. So classloader.getResource() will be working fine always.

where does java look for files in netbeans? And is it possible to change the directory?

So, I've got some txt files that I want to place in the following folder: src/test/resources/__files
However, when I run my project, I find that the compiler is looking for files in the project folder. Is there anyway of changing this as it becomes problematic when I try to create a JAR file - those files are then needed to be manually added to the target folder.
Thanks
Since you are already placing your resource files in the src/test/resources folder, Maven should make them available on the classpath at runtime. In this case, they should be on the classpath in your test build. You may try the following code:
String fileName = "somefile.txt";
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource(fileName).getFile());
The Mkyong site does a good job of explaining how resources work in Maven.
You seem to be working with the maven build tool, with per convention src/main/java, src/main/resources and for unit tests src/test/java and src/test/resources.
And then the files are not real file system File, but resources, packaged possibly in a jar (as you said): case-sensitive, / path separator and read-only InputStream.
You could keep the file as resource (under /src/main/resources/ then), and use that file as template for a real File, at the application System.getProperty("user.dir") (working directory), or System.getProperty("user.home") (home directory), see System Properties.
InputStream in = .... .class.getResourceAsStream("___files/xyz.txt");
Or you could in maven copy from your own location to the target/distribution directory.
I use NetBeans on Windows I write String url = "src\\test\\resources\\__files"
Folder structure
ProjFolder\src\test\resources\__files

Get parent in the same jar of a classpath resource

I have in the resources of my Maven project an index.html file in the res/html folder.
I am running Jetty as an embedded webserver. I want to tell him that the base resource for static content is the res/ folder.
So, I tried:
ResourceHandler rh = new ResourceHandler();
rh.setResourceBase(getClass().getResource("/res").toURI().toString());
It worked until I included another jar on my classpath which also have a res/ folder.
Jetty started to look for static content in thisotherjar.jar!res/
I would like to avoid having to give literally the path of the jar that contains my res folder. I am looking for something more generic. I tried to start with the classpath of the file index.html and then go up the the res folder using URI.resolve("..") but the same problem happens.
Any ideas to solve this nicely?
Thanks!
You should use a name that is less prone to collisions, exactly like for the Java packages. You do not name a package res because if everyone did that there would be conflicts every time we incorporate two libs.
Instead of the res directory give it a name that is specific to you such as com/mycompany/myproject/res.

getResource will always return null

This is driving me crazy. I have a simple eclipse project with a src folder and a class in it. But I can't seem to get getResource to find it. What am I doing wrong?
import java.net.URL;
public class ContextTest {
public static void main(String[] args) {
URL url = ContextTest.class.getResource("/src/ContextTest.java");
System.out.println(url);
}
}
If I right-click on the class name, the path is /TestsProject/src/ContextTest.java and the default classpath according to the Classpath tab in Run Configurations is TestProject.
It doesn't work with /bin/ContextTest.java , /ContextTest.java , ContextTest.java either.
When you load resources using ContextTest.class.getResource("/....") the leading / is translated as an absolute path. Here absolute means from your root package (i.e. the default package).
In Eclipse the root package is considered the one that is under the src folder. Your compiled classes will be placed under bin folder and if you create a jar you will see that your root package is not the src or bin folders but whatever folders are inside it. (for example com).
So the correct way to load a resource using a class absolute path would be ContextTest.class.getResource("/ContextTest.java");. If the file ContextTest.java is in the root package of wherever your compiled classes are, then it will be found and returned.
I hope this clears the picture.
Update: From the comments below it is not clear what you are trying to do. When you use getResource() you are not loading a file but a resource from the classpath. This would correctly find the resource even if your files were inside a jar file. So for your above example to work the file you are trying to load as a resource should be in the classpath (i.e. under bin folder since this is the root of your classpath when you execute from inside Eclipse). If you are trying to load a file outside of your classpath then don't try to load a resource, you could use File instead.
Resources accessed via getResource() must be on the classpath. Your Java files will be compiled and placed on the classpath. The compiled .java file will be given an extension of .class.
Try
URL url = ContextTest.class.getResource("ContextTest.class");

Java (maven web app), getting full file path for file in resources folder?

I'm working with a project that is setup using the standard Maven directory structure so I have a folder called "resources" and within this I have made a folder called "fonts" and then put a file in it. I need to pass in the full String file path (of a file that is located, within my project structure, at resources/fonts/somefont.ttf) to an object I am using, from a 3rd party library, as below, I have searched on this for a while but have become a bit confused as to the proper way to do this. I have tried as below but it isn't able to find it. I looked at using ResourceBundle but that seemed to involve making an actual File object when I just need the path to pass into a method like the one below (don't have the actual method call in front of me so just giving an example from my memory):
FontFactory.somemethod("resources/fonts/somefont.ttf");
I had thought there was a way, with a project with standard Maven directory structure to get a file from the resource folder without having to use the full relative path from the class / package. Any advice on this is greatly appreciated.
I don't want to use a hard-coded path since different developers who work on the project have different setups and I want to include this as part of the project so that they get it directly when they checkout the project source.
This is for a web application (Struts 1.3 app) and when I look into the exploded WAR file (which I am running the project off of through Tomcat), the file is at:
<Exploded war dir>/resources/fonts/somefont.ttf
Code:
import java.io.File;
import org.springframework.core.io.*;
public String getFontFilePath(String classpathRelativePath) {
Resource rsrc = new ClassPathResource(classpathRelativePath);
return rsrc.getFile().getAbsolutePath();
}
In your case, classpathRelativePath would be something like "/resources/fonts/somefont.ttf".
You can use the below mentioned to get the path of the file:
String fileName = "/filename.extension"; //use forward slash to recognize your file
String path = this.getClass().getResource(fileName).toString();
use/pass the path to your methods.
If your resources directory is in the root of your war, that means resources/fonts/somefont.ttf would be a "virtual path" where that file is available. You can get the "real path"--the absolute file system path--from the ServletContext. Note (in the docs) that this only works if the WAR is exploded. If your container runs the app from the war file without expanding it, this method won't work.
You can look up the answer to the question on similar lines which I had
Loading XML Files during Maven Test run
The answer given by BobG should work. Though you need to keep in mind that path for the resource file is relative to path of the current class. Both resources and java source files are in classpath

Categories