I am in need of a few special file types for my Spring application hence I raised this specific question on how to do a foolproof file I/O in both my local machine and once the WAR
file is uploaded to the server.
I did a few research myself and found some slightly helpful articles:
The question "Absolute file access in Spring Service layer" asks how to do file I/O in a Spring
Service
class.The accepted answer suggests to use Spring's
Resource
but it requires that the files needed to be inside/WEB-INF/classes
and unfortunately it contradicts one of the comments with the highest vote-ups:Don't write inside your web content or
WEB-INF
folder. There is no guarantee that the war file will be exploded on the filesystem. Write to a well known (probaly configurable) file location.Okay so where do I put it???
Doesn't matter, find a nice location for your files. Maybe a user directory for your application, inside the TMP directory or whatever you like. Everything but writing inside your
web-apps
directories.So I guess putting the file in
/src
is okay.The poor guy asked again but this time it needs to be in the Tomcat server: "Tomcat server absolute file access in war webapp".
This answer said to NOT DO FILE I/O INSIDE A
WAR
FILE.The accepted answer by OP is not helping either because a comment said that:
This solution will not work unless your webapp is deployed as an exploded-
WAR
file. It is therefore fragile. Using theClassLoader
orServletContext
to fetch resources is a more robust solution. This solution appears to use theClassLoader
but then mangles the URL and loads the resource using standard file I/O. :(Okay so I saw a link provided by the guy who suggested not to do file I/O in a
WAR
called "How to really read text file from classpath in Java".The problem with this one is that the file needs to be somewhere outside the whole Spring project given by the accepted answer and the second highest suggests
Resource
again.
What I tried so far
According to DwB's answer, I tried using the ServletContext
technique in my Service
layer because that's where it's needed (internal computations not appropriate for Controller
or DAO
). I slipped the following:
private String myFile = null;
protected void init(final ServletConfig config) {
ServletContext context = config.getServletContext();
String contextPath = context.getContextPath();
myFile = contextPath + "resources/test.txt";
}
protected void doGet() {
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(myFile));
writer.append("Lorem ipsum dolor sit amet");
writer.close();
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
I call doGet()
in one of my functions but it returned
THE TIME org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [spring] in context with path [/bosom] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException
Why are the codes below not working?
Simple writing
BufferedWriter bw = new BufferedWriter(new FileWriter("/src/resources/test.txt")); bw.append("Lorem ipsum dolor sit amet"); bw.close(); bw.flush();
InputStream
worked withBufferedReader
but now I'm lost withBufferedWriter
orOutputStream
(source)InputStream is = getClass().getResourceAsStream("/test.txt"); BufferedWriter bw = new BufferedWriter(new FileWriter(is)); bw.append("Lorem ipsum dolor sit amet"); bw.close(); bw.flush();
Spring's
Resource
is not helping either (source).I have tried using
resource.toString()
,resource.getURI()
,resource.getURI().toString()
,resource.getURL()
,resource.getURL().toString()
and still errors and errors.Resource resource = new ClassPathResource("/src/resources/test.txt"); BufferedWriter bw = new BufferedWriter(new FileWriter(new File(resource.toString()))); bw.append("Lorem ipsum dolor sit amet"); bw.close(); bw.flush();
It just returns:
java.io.FileNotFoundException: class path resource [src\resources\test.txt] (The system cannot find the path specified) java.io.FileNotFoundException: class path resource [src/resources/test.txt] cannot be resolved to URL because it does not exist java.io.FileNotFoundException: class path resource [src/resources/test.txt] cannot be resolved to URL because it does not exist
I made an
ENVIRONMENT_VARIABLE
inControl Panel >> System >> Environment Variables
and createdmyData
which is inD:/resources
but the code below is not writing anything to the file (no errors though).File file = new File(System.getenv("myData"), "test.txt"); try { BufferedWriter bw = new BufferedWriter(new FileWriter(file.getAbsolutePath())); bw.write("Lorem ipsum dolor sit amet"); bw.flush(); bw.close(); } catch (IOException e) { e.printStackTrace(); }
Updated based from the current answers
Now I have more questions and doubts than answers because of these. Please note that I intend to do file I/O for a project exported as a WAR
file.
Is it possible to do a successful file I/O whilst the project is in the local machine and server (
WAR
file)?based from the answers, Yes
If it's possible, in what folder is the most ideal place to put these particular files?
no particular folder was mentioned
What actual function/s should I use to read and write to these files?
???
Here is my Spring application's structure, as seen in Windows Explorer in the Eclipse Workspace (take note):
root
|----> .settings
|----> build
|----> src
|--------> package.name
|--------> resources
|------------> THE_FILES
|----> WebContent
|----> .classpath
|----> .project
Note that I also need the absolute file path in
String
orInputStream
form because I use theweka.core.SerializationHelper
'sread
method.
I just want to have a solid file I/O that both works in my local machine and even when uploaded as its WAR
file in the server (I can feel that's possible).