Finding paths for packaged non-java files at runtime - java

So this might be a stupid question but...
I want to package a specific WSDL file in with an EJB project within eclipse. What would be the best way to refer to this file in my code?
I would like to use a relative path but the current directory starts off in the /bin directory of my JBOSS installation. It seems like there should be a way to refer to the file in relation to the project file structure.
Any ideas?

getClass().getResource(String path) uses a relative path to locate a classpath resource. It returns a java.net.URL. Alternatively, you can use getResourceAsStream(..) to obtain the InputStream to the resource.

Related

How is current working directory determined when running from Eclipse? [duplicate]

I was trying to load a file in a webapp, and I was getting a FileNotFound exception when I used FileInputStream. However, using the same path, I was able to load the file when I did getResourceAsStream().
What is the difference between the two methods, and why does one work while the other doesn't?
The java.io.File and consorts acts on the local disk file system. The root cause of your problem is that relative paths in java.io are dependent on the current working directory. I.e. the directory from which the JVM (in your case: the webserver's one) is started. This may for example be C:\Tomcat\bin or something entirely different, but thus not C:\Tomcat\webapps\contextname or whatever you'd expect it to be. In a normal Eclipse project, that would be C:\Eclipse\workspace\projectname. You can learn about the current working directory the following way:
System.out.println(new File(".").getAbsolutePath());
However, the working directory is in no way programmatically controllable. You should really prefer using absolute paths in the File API instead of relative paths. E.g. C:\full\path\to\file.ext.
You don't want to hardcode or guess the absolute path in Java (web)applications. That's only portability trouble (i.e. it runs in system X, but not in system Y). The normal practice is to place those kind of resources in the classpath, or to add its full path to the classpath (in an IDE like Eclipse that's the src folder and the "build path" respectively). This way you can grab them with help of the ClassLoader by ClassLoader#getResource() or ClassLoader#getResourceAsStream(). It is able to locate files relative to the "root" of the classpath, as you by coincidence figured out. In webapplications (or any other application which uses multiple classloaders) it's recommend to use the ClassLoader as returned by Thread.currentThread().getContextClassLoader() for this so you can look "outside" the webapp context as well.
Another alternative in webapps is the ServletContext#getResource() and its counterpart ServletContext#getResourceAsStream(). It is able to access files located in the public web folder of the webapp project, including the /WEB-INF folder. The ServletContext is available in servlets by the inherited getServletContext() method, you can call it as-is.
See also:
Where to place and how to read configuration resource files in servlet based application?
What does servletcontext.getRealPath("/") mean and when should I use it
Recommended way to save uploaded files in a servlet application
How to save generated file temporarily in servlet based web application
getResourceAsStream is the right way to do it for web apps (as you already learned).
The reason is that reading from the file system cannot work if you package your web app in a WAR. This is the proper way to package a web app. It's portable that way, because you aren't dependent on an absolute file path or the location where your app server is installed.
FileInputStream will load a the file path you pass to the constructor as relative from the working directory of the Java process. Usually in a web container, this is something like the bin folder.
getResourceAsStream() will load a file path relative from your application's classpath.
The FileInputStream class works directly with the underlying file system. If the file in question is not physically present there, it will fail to open it. The getResourceAsStream() method works differently. It tries to locate and load the resource using the ClassLoader of the class it is called on. This enables it to find, for example, resources embedded into jar files.
classname.getResourceAsStream() loads a file via the classloader of classname. If the class came from a jar file, that is where the resource will be loaded from.
FileInputStream is used to read a file from the filesystem.
I am here by separating both the usages by marking them as File Read(java.io) and Resource Read(ClassLoader.getResourceAsStream()).
File Read -
1. Works on local file system.
2. Tries to locate the file requested from current JVM launched directory as root
3. Ideally good when using files for processing in a pre-determined location like,/dev/files or C:\Data.
Resource Read -
1. Works on class path
2. Tries to locate the file/resource in current or parent classloader classpath.
3. Ideally good when trying to load files from packaged files like war or jar.

How to create exe/jar file in netbeans that can be easily run on any other system

i hv created the .jar file by building my project in netbeans.
The .jar file exist in "dist/myproject.jar". But when i move it to
any other system will it find the paths specified for images etc in
project?
As i am giving the paths like
(C:/Users/Lucky/Documents/NetBeansProjects/CoverageAnalyzer/src/coverageanalyzer/icons/icon.png).
OR When i write path just to approach root directory as
(icons/icon.png), so then also?
Summary: What is the actual way that i can write/copy my .jar file to
any other system without spoiling the paths and program run correctly
on any other system. Thanks in advance.help will be appriciated
You can use one of the following approaches:
Use relative paths (relative to the executable file location) instead of absolute paths.
Use paths under a known absolute path (an installation folder, path from environment variable / configuration file / registry key, the user's directory (user.home) etc.)
Use resources embeded into your jar. See Class.getResource() and Class.getResourceAsStream()
Note that you should consider cross-platform (Windows/Linux/Mac) and resource hiding issues when selecting a suitable approach.
The solution is to put the auxiliary files as resources into to jar. The program must then load them from the class path instead of the file system.
Have a look at Class.getResourceAsStream.

Finding XML file path in hibernate project

I am working on an hibernate project in which I need to read an xml. I placed those xmls in the same folder as the servlet from which I am trying to access those xmls. Now I don't know what is the correct path to access those xmls. Here is my project file structure. As can see, xmls are placed in com.strategycreator folder.
I can't place the xmls in a public directory as they need to be in a secure location.
If you need these files to be inaccessible to web page requests, you need to put them in your classpath and use them as resources.
The easiest way to find out the path to use for a classpath resource, is to generate the WAR, look inside the WAR in the appropriate JAR and see what path it ended up having and use that. If the file is "next to" a the class that needs to load it, you can use a relative path, otherwise you need to use the full "/com/strategycreator/groups.xml" path.

Java read a folder from project base directory

I have a maven project with typical project structure. At the base of the project, I have a directory names res that has some resources (> 500 MB).
I am trying to use
this.class().getClassLoader().getResourceAsStream("res/xxx")
this code fragment to read from that folder, but it returns a null resource stream.
I have a few workarounds below, but none of these are acceptable due to reasons explained below.
I can move the folder to {base}/target/classes, and it will be read, but it will also get cleaned when I do a mvn clean. Hence, this approach doesn't work. For some reason, specifying the path as ../../res/xxx also doesn't work.
I can move the folder to {base}/src/resources, but then it will get copied to target/classes and the jar. Hence this is also not acceptable.
Though I am open to trying some other java APIs, I may have to use the class loader mechanism only as there is some external library component that is also trying to access the res folder using the similar approach.
Is there some way I can read the res folder from projects base directory? Is there some setting in pom.xml file that can help me with that?
Use this.class().getClassLoader().getResourceAsStream("/res/xxx") and then you will be reading from the root of the classpath irrespective of the actual file/folder location in windows or Linux. This is actually one of the safest ways to read files especially when you do not know how your application will eventually be deployed.
It means though that your classpath must include the parent of res and that res/ must be copied over when you deploy your app
Otherwise, if you want to use relative paths, try this snippet (taken from this SO answer):
String filePath = new File("").getAbsolutePath();
filePath.concat("path to the property file");
If you use this.class().getClassLoader().getResourceAsStream("/res/xxx"), it is going to try to load resources from the classpath. If that's not want you want to do, you're going to need to specify an absolute path.
Resource on Classpath
If you don't want the resource built into your JAR, I'd suggest having a different maven project with the file in it, under the src/main/resources directory. This will create a jar file with the file in it, which will be ~500MB.
After this, you can include a dependency on this project in your project containing your application code. This will then be able to reference it from the jar file using getResourceAsStream(...).
If you don't want this large jar file to ship with your application, make sure you mark the dependency with <scope>provided</scope>.
File from Absolute Path
You will need to take the file location as a parameter in your main method, and then use new File("C:\\path\\to\\your\\file.txt") and then use a FileReader to read it in.

getResourceAsStream() vs FileInputStream

I was trying to load a file in a webapp, and I was getting a FileNotFound exception when I used FileInputStream. However, using the same path, I was able to load the file when I did getResourceAsStream().
What is the difference between the two methods, and why does one work while the other doesn't?
The java.io.File and consorts acts on the local disk file system. The root cause of your problem is that relative paths in java.io are dependent on the current working directory. I.e. the directory from which the JVM (in your case: the webserver's one) is started. This may for example be C:\Tomcat\bin or something entirely different, but thus not C:\Tomcat\webapps\contextname or whatever you'd expect it to be. In a normal Eclipse project, that would be C:\Eclipse\workspace\projectname. You can learn about the current working directory the following way:
System.out.println(new File(".").getAbsolutePath());
However, the working directory is in no way programmatically controllable. You should really prefer using absolute paths in the File API instead of relative paths. E.g. C:\full\path\to\file.ext.
You don't want to hardcode or guess the absolute path in Java (web)applications. That's only portability trouble (i.e. it runs in system X, but not in system Y). The normal practice is to place those kind of resources in the classpath, or to add its full path to the classpath (in an IDE like Eclipse that's the src folder and the "build path" respectively). This way you can grab them with help of the ClassLoader by ClassLoader#getResource() or ClassLoader#getResourceAsStream(). It is able to locate files relative to the "root" of the classpath, as you by coincidence figured out. In webapplications (or any other application which uses multiple classloaders) it's recommend to use the ClassLoader as returned by Thread.currentThread().getContextClassLoader() for this so you can look "outside" the webapp context as well.
Another alternative in webapps is the ServletContext#getResource() and its counterpart ServletContext#getResourceAsStream(). It is able to access files located in the public web folder of the webapp project, including the /WEB-INF folder. The ServletContext is available in servlets by the inherited getServletContext() method, you can call it as-is.
See also:
Where to place and how to read configuration resource files in servlet based application?
What does servletcontext.getRealPath("/") mean and when should I use it
Recommended way to save uploaded files in a servlet application
How to save generated file temporarily in servlet based web application
getResourceAsStream is the right way to do it for web apps (as you already learned).
The reason is that reading from the file system cannot work if you package your web app in a WAR. This is the proper way to package a web app. It's portable that way, because you aren't dependent on an absolute file path or the location where your app server is installed.
FileInputStream will load a the file path you pass to the constructor as relative from the working directory of the Java process. Usually in a web container, this is something like the bin folder.
getResourceAsStream() will load a file path relative from your application's classpath.
The FileInputStream class works directly with the underlying file system. If the file in question is not physically present there, it will fail to open it. The getResourceAsStream() method works differently. It tries to locate and load the resource using the ClassLoader of the class it is called on. This enables it to find, for example, resources embedded into jar files.
classname.getResourceAsStream() loads a file via the classloader of classname. If the class came from a jar file, that is where the resource will be loaded from.
FileInputStream is used to read a file from the filesystem.
I am here by separating both the usages by marking them as File Read(java.io) and Resource Read(ClassLoader.getResourceAsStream()).
File Read -
1. Works on local file system.
2. Tries to locate the file requested from current JVM launched directory as root
3. Ideally good when using files for processing in a pre-determined location like,/dev/files or C:\Data.
Resource Read -
1. Works on class path
2. Tries to locate the file/resource in current or parent classloader classpath.
3. Ideally good when trying to load files from packaged files like war or jar.

Categories

Resources