Reading files from relative paths on Tomcat - java

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.

Related

Deployed WAR can't access a file

I have a spring application, and i'm trying to access a json file with the following code :
try (FileReader reader = new FileReader("parameters.json")) {
Object obj = jsonParser.parse(reader);
parameterList = (JSONArray) obj;
}
I have put the parameter.json file in the project folder and I'm accesing the file data from an angular app through a rest api, and that works fine when I run the application on local machine, but when I deploy the war file on tomcat, my application can't load the file, should I put parameter.json file somewhere else on tomcat or what is the best solution for it.
Your question states you are attempting to access a file called parameter.json, while your code excerpt shows parameters.json. Perhaps that discrepancy indicates a typo in your source code?
If not, there are various ways to access a file from the classpath in Spring, with the first step for each being to ensure the file is in the project's src/main/resources directory.
You can then use one of the Spring utility classes ClassPathResource, ResourceLoader or ResourceUtils to get to the file. The easiest approach, though, may be to put your properties in a .properties file (default file name application.properties) and access the values using Spring's #Value annotation:
#Value("${some.value.in.the.file}")
private String myValue;
You can use other file names as well by utilizing #PropertySource:
#Configuration
#PropertySource(value = {"classpath:application.properties",
"classpath:other.properties"})
public class MyClass {
#Value("${some.value.in.the.file}")
private String myValue;
...
}
Make sure your parameters.josn filename is exactly same in the code.
Move you parameters.json file in the resources folder and then use the classpath with the filename.
try (FileReader reader = new FileReader("classpath:parameters.json")) {
Object obj = jsonParser.parse(reader);
parameterList = (JSONArray) obj;
}
Try to put the file under resources folder in your spring project. You should be able to access the file from that location.
FileReader is looking for a full-fledged file system like the one on your computer, but when your WAR is deployed, there just isn't one, so you have to use a different approach. You can grab your file directly from your src/main/resources folder like this
InputStream inputStream = getClass().getResourceAsStream("/parameters.json");

Listing resources from a resource folder

I created a data folder beside the js folder in resource/static at the backend of my spring boot application.
I want to list its content in a selection for the user.
I was able to list it if I use the File and Path functions of the base Java. But I don't like this solution, because the path could change in different environment of our system.
I can load a file with org.springframework.core.io.ResourceLoader. I like this solution better as it is independent of the file path of my system. But I did not found the way to list the files in a given resource folder.
Do you have any idea?
Finally I moved my data folder to the WEB-INF.
And I can list the content of it with the following code:
#Autowired
ServletContext context;
public Collection<String> getFileList(String path) {
Collection<String> result = new ArrayList<String>();
Set<String> paths = context.getResourcePaths(path);
for (String p : paths) {
String[] parts = p.split("/");
result.add(parts[parts.length-1]);
}
return result;
}
And I call it with the following parameter:
getFileList("/WEB-INF/data");
This solution works if the WEB-INF folder is unpacked during deploy. And also works when the data folder remains in the war archive.
Check this out :)
You can also read about Java Reflection

Path for creating a file in Tomcat

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.

load a folder from a jar

I am trying to access a directory inside my jar file. I want to go through every of the files inside the directory itself. I tried using the following:
File[] files = new File("ressources").listFiles();
for (File file : files) {
XMLParser parser = new XMLParser(file.getAbsolutePath());
// some work
}
If I test this, it works well. But once I put the contents into the jar, it doesn't because of several reasons. If I use this code, the URL always points outside the jar.
structure of my project :
src
controllers
models
class that containt traitement
views
ressources
See this:
How do I list the files inside a JAR file?
Basically, you just use a ZipInputStream to find a list of files (a .jar is the same as a .zip)
Once you know the names of the files, you can use getClass().getResource(String path) to get the URL to the file.
I presume this jar is on your classpath.
You can list all the files in a directory using the ClassLoader.
First you can get a list of the file names then you can get URLs from the ClassLoader for individual files:
public static void main(String[] args) throws Exception {
final String base = "/path/to/folder/inside/jar";
final List<URL> urls = new LinkedList<>();
try (final Scanner s = new Scanner(MyClass.class.getResourceAsStream(base))) {
while (s.hasNext()) {
urls.add(MyClass.class.getResource(base + "/" + s.nextLine()));
}
}
System.out.println(urls);
}
You can do whatever you want with the URL - either read and InputStream into memory or copy the InputStream into a File on your hard disc.
Note that this definitely works with the URLClassLoader which is the default, if you are using an applet or a custom ClassLoader then this approach may not work.
NB:
You have a typo - its resources not ressources.
You should use reverse domain name notation for your project, this is the convention.

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

Categories

Resources