Accessing relative files in Tomcat - java

I am using a third party library in my WebApp on tomcat.
The problem is that a class of that third party library requires initialization with an XML file
LibraryClass lb = new LibraryClass("file path.xml");
So where should I put files in tomcat directories in order to be able to access them from inside the webapp??
(Note that the class requires a String for the absolute path, not a FileStream for example)

If you don't want the file to be downloadable, make it a resource by placing it somewhere in your Java source directory and let it be copied into WEB-INF/classes. Then use ServletRequest.getRealPath("/WEB-INF/classes/...") to turn the relative path into an absolute path.

You can keep them under WEB-INF/classes folder.You can see complete discussion about this here:
Where to place configuration properties files in a JSP/Servlet web application?

Like the other answers, I agree that the best place for these files is inside your war bundle. Unlike the other answers, I would not recommend putting the file in WEB-INF/classes as that directory is for class files, not XML files.
If path.xml is located in the war's root, then you can get access to it with something like this:
String servletDirectoryPath = this.getServletConfig().getServletContext().getRealPath("");
String xmlConfigurationFileName = "path.xml";
File xmlConfigurationFile = new File(servletDirectoryPath, xmlConfigurationFileName);
initializeThirdPartyLibrary(xmlConfigurationFile);

Related

Using relative path in a maven project

I have a maven project with these standard directory structures:
src/main/java
src/main/java/pdf/Pdf.java
src/test/resources
src/test/resources/files/x.pdf
In my Pdf.java,
File file = new File("../../../test/resources/files/x.pdf");
Why does it report "No such file or dirctory"? The relative path should work. Right?
Relative paths work relative to the current working directory. Maven does not set it, so it is inherited from whatever value it had in the Java process your code is executing in.
The only reliable way is to figure it out in your own code. Depending on how you do things, there are several ways to do so. See How to get the real path of Java application at runtime? for suggestions. You are most likely looking at this.getClass().getProtectionDomain().getCodeSource().getLocation() and then you know where the class file is and can navigate relative to that.
Why does it report "No such file or dirctory"? The relative path should work. Right?
wrong.
Your classes are compiled to $PROJECT_ROOT/target/classes
and your resources are copied to the same folder keeping their relative paths below src/main/resources.
The file will be located relative to the classpath of which the root is $PROJECT_ROOT/target/classes. Therefore you have to write in your Pdf.java:
File file = new File("/files/x.pdf");
Your relative path will be evaluated from the projects current working directory which is $PROJECT_ROOT (AFAIR).
But it does not matter because you want that to work in your final application and not only in your build environment. Therefore you should access the file with getClass().getResource("/path/to/file/within/classpath") which searches the file in the class path of which the root is $PROJECT_ROOT/target/classes.
No the way you are referencing the files is according to your file system. Java knows about the classpath not the file system if you want to reference something like that you have to use the fully qualified name of the file.
Also I do not know if File constructor works with the classpath since it's an abstraction to manage the file system it will depend where the application is run from. Say it is run from the target directory at the same level as source in that case you have to go one directory up and then on src then test the resources the files and finally in x.pdf.
Since you are using a resources folder I think you want the file to be on the classpath and then you can load a resource with:
InputStream in = this.getClass().getClassLoader()
.getResourceAsStream("<path in classpath>");
Then you can create a FileInputStream or something to wrap around the file. Otherwise use the fully qualiefied name and put it somewere like /home/{user}/files/x.pdf.

Sharing a Java Object Stream

I've got a project to do with 2 other classmates.
We used Dropbox to share the project so we can write from our houses (Isn't a very good choice, but it worked and was easier than using GitHub)
My question is now about sharing the object stream.
I want to put the file of the stream in same dropbox shared directory of the code.
BUT, when i initialize the file
File f = new File(PATH);
i must use the path of my computer (C:\User**Alessandro**\Dropbox)
As you can see it is linked to Alessandro, and so to my computer.
This clearly won't work on another PC.
How can tell the compiler to just look in the same directory of the source code/.class files?
You can use Class#getResource(java.lang.String) to obtain a URL corresponding to the location of the file relative to the classpath of the Java program:
URL url = getClass().getResource("/path/to/the/file");
File file = new File(url.getPath());
Note here that / is the root of your classpath, which is the top of the directory containing your class files. So your resource should be placed inside the classpath somewhere in order for it to work on your friend's computer.
Don't use absolute paths. Use relative paths like ./myfile.txt. Start the program with the project directory as the current dir. (This is the default in Eclipse.) But then you have to ensure that this both works for development and for production use.
As an alternative you can create a properties file and define the path there. Your code then only refers to a property name and each developer can adjust the configuration file. See Properties documentation.

Java get folder in same directory as Jar

Say I have an exported Jar file on my Desktop, and then a folder I want to access so my jar file can load files from it. How can I access that folder without hard coding the path?
See here: https://stackoverflow.com/a/6849255/514463
Pick one of your classes that you want the directory of, e.g.: Test:
String path = Test.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = URLDecoder.decode(path, "UTF-8");
If I clearly understand, you may use relative path when you try to access folder. For example, if you run your jar as a standalone application, relative path "." will be a folder that contains your jar. So, when you place names.txt file next to your jar, you can get access to it with:
new File("./names.txt");
Hope I understood you right way and this will help.
The following code should provide the directory containing the JAR file:
URL url = getClass().getProtectionDomain().getCodeSource().getLocation();
File directory = new File(url.toURI()).getParentFile();
Hmmm...
I heard this question so often, and it always boils down to this: How to load resources at runtime?
The main reason for this type of question is, that one is developping an application and now wants to create a distributable package. This normally ends in something like that:
... / my-application-folder
| -- lib / *.jar
| -- main.jar
| -- config.properties
There could be several configuration files. A configuration for the application itself, a configuration for a logging framework that is used, etc. It does not matter. If you want to access such resources, you should do it in two steps:
1) Make sure all folders containing your resources (such configuration files are resources) are part of the classpath. If you run your JAR file (here main.jar) with a java -jar main.jar command, this JAR file should contain a manifest file containing the directory . and all needed library JARs in the class-path entry. [Alternative: Maybe all your config files are located in a config/ subfolder. Then this folder must be part of the class-path.]
2) Inside your application you access such resources with a class loader:
ClassLoader loader = Thread.currentThread().getContextClassLoader();
URL url = loader.getResource(neededResource);
// do something with url, e.g. open stream, read from it, and close stream
If you have a user customizable path, there are several possibilities. You could for example pass a system property to the application, as Reddy suggested in his comment. You could also have a property in a configuration file, which you are loading in the beginning part of your application. However, you have the path to this customizable folder in hand (at runtime). Then you do the following:
String customizablePath = getCustomizablePath();
URL customizablePathURL = new File(customizablePath).toURI().toURL();
ClassLoader loader = new URLClassLoader(new URL[] {customizablePathURL});
Then you can continue like above.
File f = new File("Folder")
This File object points to "Folder" directory in the the working directory of the Jar.

The correct place to put the config file in Eclipse

I have created a Dynamic Web Project in Eclipse and I have a following Java statement that needs to read a config file:
Document doc= new SAXReader().read(new File(ConstantsUtil.realPath+"appContext.xml"));
Basically, ConstantsUtil.realPath will return an empty string.
I tried putting "appContext.xml" under both "src" folder and under "WEB-INF" folder. However, I will always get the following error:
org.dom4j.DocumentException: appContext.xml (The system cannot find the file specified)
I am really confused: in Eclipse, where is the correct place to put my config xml file?
Thanks in advance.
Your concrete problem is caused by using new File() with a relative path in an environment where you have totally no control over the current working directory of the local disk file system. So, forget it. You need to obtain it by alternate means:
Straight from the classpath (the src folder, there where your Java classes also are) using ClassLoader#getResourceAsStream():
Document doc= new SAXReader().read(Thread.currentThread().getContextClassLoader().getResourceAsStream("appContext.xml"));
Straight from the public webcontent (the WebContent folder, there where /WEB-INF folder resides) using ServletContext#getResourceAsStream():
Document doc= new SAXReader().read(servletContext.getResourceAsStream("/WEB-INF/appContext.xml"));
The ServletContext is in servlets available by the inherited getServletContext() method.
See also:
Where to place and how to read configuration resource files in servlet based application?
getResourceAsStream() vs FileInputStream
What does servletcontext.getRealPath("/") mean and when should I use it
You can embed your config files into your jar/war files
InputStream is = MyClass.class.getResourceAsStream("/com/site/config/config.xml");
You could either create a folder with all your configurations and reference it on the class path of the web application when published on the server, or place them under the WebContent folder, in both cases you need to reference them relatively.
There can be multiple places where you could place your property files. The selection of the location depends on the architeture of the project.
Commonly used location are:
/YourProjectRootFolder/src/main/webapp/WEB-INF/properties/XYZ.properties
: in the same folder where you have your java class files.
YourProjectConfFolderNAme/src/main/resources/XYZ.properties: here all the property files are kept in a seperate location than your project class files.
Both are the same as you need to move all your property files to you server's conf folder.

Java file path in web project

I need to access the resource files in my web project from a class. The problem is that the paths of my development environment are different from the ones when the project is deployed.
For example, if I want to access some css files while developing I can do like this:
File file = new File("src/main/webapp/resources/styles/some.css/");
But this may not work once it's deployed because there's no src or main directories in the target folder. How could I access the files consistently?
You seem to be storing your CSS file in the classpath for some unobvious reason. The folder name src is typical as default name of Eclipse's project source folder. And that it apparently magically works as being a relative path in the File constructor (bad, bad), only confirms that you're running this in the IDE context.
This is indeed not portable.
You should not be using File's constructor. If the resource is in the classpath, you need to get it as resource from the classpath.
InputStream input = getClass().getResourceAsStream("/main/webapp/resources/styles/some.css");
// ...
Assuming that the current class is running in the same context, this will work regardless of the runtime environment.
See also:
getResourceAsStream() vs FileInputStream
Update: ah, the functional requirement is now more clear.
Actually I want to get lastModified from the file. Is it possible with InputStream? –
Use getResource() instead to obtain it as an URL. Then you can open the connection on it and request for the lastModified.
URL url = getClass().getResource("/main/webapp/resources/styles/some.css");
long lastModified = url.openConnection().getLastModified();
// ...
If what you're looking to do is open a file that's within the browser-visible part of the application, I'd suggest using ServletContext.getRealPath(...)
Thus:
File f = new File(this.getServletContext().getRealPath("relative/path/to/your/file"));
Note: if you're not within a servlet, you may have to jump through some additional hoops to get the ServletContext, but it should always be available to you in a web environment. This solution also allows you to put the .css file where the user's browser can see it, whereas putting it under /WEB-INF/ would hide the file from the user.
Put your external resources in a sub-directory of your project's WEB-INF folder. E.g., put your css resources in WEB-INF/styles and you should be able to access them as:
new File("styles/some.css");
Unless you're not using a standard WAR for deployment, in which case, you should explain your setup.
Typically resource files are placed in your war along with your class files. Thus they will be on the classpath and can be looked up via
getClass.getResource("/resources/styles/some.css")
or by opening a File as #ig0774 mentioned.
If the resource is in a directory that is not deployed in the WAR (say you need to change it without redeploying), then you can use a VM arg to define the path to your resource.
-Dresource.dir=/src/main/webapp/resources
and do a lookup via that variable to load it.
In Java web project, the standard directory like:
{WEB-ROOT} /
/WEB-INF/
/WEB-INF/lib/
/WEB-INF/classes
So, if you can get the class files path in file system dynamic,
you can get the resources file path.
you can get the path ( /WEB-INF/classes/ ) by:
this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath()
so, then the next ...

Categories

Resources