Path for creating a file in Tomcat - java

I created a website setting file in the xml format, and the content of this file specifies things like website title, url, meta description, admin email, etc.
In my Java code, I simply defined the file as following:
private static final String webSettingFileName = "WebSettings.xml";
public void saveSetting()
{
File settingFile = new File(webSettingFileName);
// try-catch block to write the XML file omitted
}
After I deploy the war file, I found out that the web Setting xml file was written to the Tomcat bin folder, however, I would like to write the file inside the ROOT folder of webapps in Tomcat. So I am wondering how to specify the file path in my code. Thanks
Edit:
As Jarrod Roberson gave me a red -1 for duplicate question. I disagree with him, because I had checked the post before making this post. I tried the method suggested in that post here, but it does not work for me, because I need to save the web settings file persistently in the same location no matter how many times Tomcat has restarted (so tomcat/webapps serves my purpose!). The file is for saving website settings. In addition, the ServletContext don't seem working in Java 1.8 that I am using for my webapp.
Edit 2:
This is how I finally made it work:
private final static File catalinaBase = new File(System.getProperty("catalina.base")).getAbsoluteFile();
private static final String webSettingFileName = "WebSetting.xml";
private final static File file = new File(catalinaBase, "webapps/" + webSettingFileName);

You can use the method ServletContext.getRealPath("/") to retrieve the absolute filesystem path of the current webapp, e.g.:
File settingFile = new File(getServletContext().getRealPath("/"), webSettingFileName);
Note that this will only work with an exploded (unzipped) war file.

Related

How to have my java project to use some files without using their absolute path?

I have written a project where some images are used for the application's appearance and some text files will get created and deleted along the process. I only used the absolute path of all used files in order to see how the project would work, and now that it is finished I want to send it to someone else. so what I'm asking for is that how I can link those files to the project so that the other person doesn't have to set those absolute paths relative to their computer. something like, turning the final jar file with necessary files into a zip file and then that the person extracts the zip file and imports jar file, when runs it, the program work without any problems.
by the way, I add the images using ImageIcon class.
I'm using eclipse.
For files that you just want to read, such as images used in your app's icons:
Ship them the same way you ship your class files: In your jar or jmod file.
Use YourClassName.class.getResource or .getResourceAsStream to read these. They are not files, any APIs that need a File object can't work. Don't use those APIs (they are bad) - good APIs take a URI, URL, or InputStream, which works fine with this.
Example:
package com.foo;
public class MyMainApp {
public void example() {
Image image = new Image(MyMainApp.class.getResource("img/send.png");
}
public void example2() throws IOException {
try (var raw = MyMainApp.class.getResourceAsStream("/data/countries.txt")) {
BufferedReader in = new BufferedReader(
new InputStreamReader(raw, StandardCharsets.UTF_8));
for (String line = in.readLine(); line != null; line = in.readLine()) {
// do something with each country
}
}
}
}
This class file will end up in your jar as /com/foo/MyMainApp.class. That same jar file should also contain /com/foo/img/send.png and /data/countries.txt. (Note how starting the string argument you pass to getResource(AsStream) can start with a slash or not, which controls whether it's relative to the location of the class or to the root of the jar. Your choice as to what you find nicer).
For files that your app will create / update:
This shouldn't be anywhere near where your jar file is. That's late 80s/silly windows thinking. Applications are (or should be!) in places that you that that app cannot write to. In general the installation directory of an application is a read-only affair, and most certainly should not be containing a user's documents. These should be in the 'user home' or possibly in e.g. `My Documents'.
Example:
public void save() throws IOException {
Path p = Paths.get(System.getProperty("user.home"), "navids-app.save");
// save to that file.
}

Java - load file from web context

I can't figure out why fi.exists() returns false here. I can browse to the file via the browser at contextPath+"/images/default.png
String contextPath = req.getContextPath();
File fi = new File(contextPath+"/images/default.png");
exists = fi.exists();
I think you missunderstood what the context path is.
If you application is deployed on yourdomain.com/app, the context path will be /app.
It is used to tell the client where to look for resources.
When you do contextPath+"/images/default.png", you the path would be dependent of the deployment path (in this case it would be the file /app/images/default.png).
If you want the file next to the installation of your application server, you can use "images/default.png".
If you want to access resource files, you may want to try Thread.currentThread().getContextClassLoader().getResource("images/default.png") instead of files.
If you want to check if a context related resource exist, you can do it as stated here:
boolean exists=req.getServletContext().getResource("images/default.png")!=null;`
or
String path=req.getServletContext().getRealPath("images/default.png");`
Rather than getContextPath(), I needed to use getRealPath():
String path = req.getServletContext().getRealPath("/images/default.png");
File fi = new File(path);

Reading files from relative paths on Tomcat

I need to run a web-app on Tomcat, but it cannot read the txt files(from a relative paths as below) on Tomcat. However, it does work if I use a full path.
So I am wondering where can I put these txt files so that when Tomcat started, the app can successfully read the txt files from a relative path.
Currently, the project structure is as follows, the txt files is located on the same directory as src file in Project Explorer in Eclipse.
Project_Name
src
java files
EDGES.txt
NODES.txt
The code is as follows, I am appreciated if someone can give me an answer in details, since I am quite new to Java.
The code is as follows:
public class RouteingDao {
NodeJSONReader nodeInput = new NodeJSONReader("NODES.txt");
EdgeJSONReader edgeInput = new EdgeJSONReader("EDGES.txt");
...
}
The NodeJSONReader/EdgeJSONReader class is as follows:
public class EdgeJSONReader {
private EdgeEntity[] edgeEntity;
// constructor
public EdgeJSONReader(String JSON_FILE) {
edgeEntity = readEntityFromFile(JSON_FILE);
}
// load the JSON data from local file
public EdgeEntity[] readEntityFromFile(String JSON_FILE) {
try {
Reader reader = new FileReader(JSON_FILE);
Gson gson = new Gson();
edgeEntity = gson.fromJson(reader, EdgeEntity[].class);
}
...
}
}
If you are using a servlet, then access the servlet context and the getRealPath method.
this.getServletContext().getRealPath("WEB-INF/nodes.txt")
The relative path sent to getRealPath will be expanded to the location of the files for your web app. You can add any path you like, even to a hidden file in WEB-INF.
From a JSP you can use
${pageContext.servletContext.getRealPath("WEB-INF/nodes.txt")}
Be careful, this will be in the build directory, so any changes to nodes.txt will not be saved to the original file.

Property file not reflecting the modified changes using Apache Commons Configuration

I am trying to explore Apache commons configuration to dynamically load the property file and do modification in the file and save it.
I wrote a demo code for the same.
Code Snippet
package ABC;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
public class Prop {
public static void main(String[] args)
{
try {
URL propertiesURL = Prop.class.getResource("/d1.properties");
if (propertiesURL == null) {
System.out.println("null");
}
String absolutePath=propertiesURL.getPath();
PropertiesConfiguration pc = new PropertiesConfiguration(absolutePath);
pc.setReloadingStrategy(new FileChangedReloadingStrategy());
String s=(String)pc.getProperty("key_account_sales");
System.out.println("s is " + s);
pc.setAutoSave(true);
pc.setProperty("key_account_sales", "Dummy");
pc.save();
System.out.println("Modified as well");
String sa=(String)pc.getProperty("key_account_sales");
System.out.println("s is " + sa);
}catch(ConfigurationException ce)
{
ce.printStackTrace();
}
}
}
Although when I run the code multiple times, the updated value for the property is being properly shown but the changes are not seen in the Property file.
I tried refreshing the entire workspace and the project but still the property file shows the previous entry whereas this code displays the updated entry in console.
Why my property file is not getting updated?
Well I noticed that a new file with same name was formed inside bin
directory of my IDE workspace. This new file contains the required
changes.
However I still want that the old file should be updated with the new
value and instead of creating a new file, it should update in the old
file itself.
My property file is located inside a Web Application package say
Dem1
by the name of
Prop1.prop
I want to read this property file from in another class say
Reading.java
located inside another package
Dem2
, do changes in this same property file and show it to another user. It is a web application being deployed on an application server.
Even after using the absolute path in a simple file (main function) it is not reflecting the changes in the same file but updating it in new file.
I am doing a very slight mistake but can someone please help.
Using absolute path I am not able to make changes in the same property file in normal main method also. Please suggest.
New file in bin directory is created instead of updating the same file
in src folder.
You should be able to solve this using absolute paths. The PropertiesConfiguration class is finding your properties file somewhere on the classpath and only knows to write back to "d1.properties"; hence you have a file appearing in your bin directory.
The absolute path can be obtained by querying resources on the classpath. Something like the following:
URL propertiesURL = Prop.class.getResource("/d1.properties");
if (propertiesURL == null) {
// uh-oh...
}
String absolutePath = propertiesURL.getPath();
// Now use absolutePath

Programmatically reading static resources from my java webapp [duplicate]

This question already has answers here:
How to find the working folder of a servlet based application in order to load resources
(3 answers)
Closed 6 years ago.
I currently have a bunch of images in my .war file like this.
WAR-ROOT
-WEB-INF
-IMAGES
-image1.jpg
-image2.jpg
-index.html
When I generate html via my servlets/jsp/etc I can simple link to
http://host/contextroot/IMAGES/image1.jpg
and
http://host/contextroot/IMAGES/image1.jpg
Not I am writing a servlet that needs to get a filesystem reference to these images (to render out a composite .pdf file in this case). Does anybody have a suggestion for how to get a filesystem reference to files placed in the war similar to how this is?
Is it perhaps a url I grab on servlet initialization? I could obviously have a properties file that explicitly points to the installed directory but I would like to avoid additional configs.
If you can guarantee that the WAR is expanded, then you can use ServletContext#getRealPath() to convert a relative web path to an absolute disk file system which you can further use in the usual Java IO stuff.
String relativeWebPath = "/IMAGES/image1.jpg";
String absoluteDiskPath = getServletContext().getRealPath(relativeWebPath);
File file = new File(absoluteDiskPath);
InputStream input = new FileInputStream(file);
// ...
However, if you can't guarantee that the WAR is expanded (i.e. all resources are still packaged inside WAR) and you're actually not interested on the absolute disk file system path and all you actually need is just an InputStream out of it, then use getServletContext().getResourceAsStream() instead.
String relativeWebPath = "/IMAGES/image1.jpg";
InputStream input = getServletContext().getResourceAsStream(relativeWebPath);
// ...
See also:
getResourceAsStream() vs FileInputStream
Use the getRealPath method of ServletContext.
Ex:
String path = getServletContext().getRealPath("WEB-INF/static/img/myfile.jpeg");
This is relatively straight forward you simply use the class loader to fetch the files from the class plath. :
InputStream is = YourServlet.class.getClassLoader().getResourceAsStream("IMAGES/img1.jpg");
There are a few other getResoruce classes that are worth looking at. Also you don't have to fetch the class loader through the class variable on your servlet. Any class that you happen to know has been loaded by the container should work .
If you know the relative location of the files you could ask the runtime about the exact location using
Thread.currentThread().getContextClassLoader().getResource(<relative-path>/<filename>)
This would give you an URL to the location where the specified image can be found. This URL can be used to read the specified file or you can split it to use the different parts of the URL for further processing.

Categories

Resources