Tomcat server absolute file access in war webapp

absolute-path, file-io, java, spring, tomcat

Solution

To read files:

ServletContext application = ...;
InputStream in = null;

try {
  in = application.getResourceAtStream("/WEB-INF/web.xml"); // example

  // read your file
} finally {
  if(null != in) try { in.close(); }
   catch (IOException ioe) { /* log this */ }
}

To write files:

ServletContext application = ...;
File tmpdir = (File)application.getAttribute("javax.servlet.context.tempdir");

if(null == tmpdir)
  throw new IllegalStateException("Container does not provide a temp dir"); // Or handle otherwise

File targetFile = new File(tmpDir, "my-temp-filename.txt");
BufferedWriter out = null;

try {
  out = new BufferedWriter(new FileWriter(targetFile));

  // write to output stream
} finally {
  if(null != out) try { out.close(); }
  catch (IOException ioe) { /* log this */ }
}

If you don't want to use the tmpdir provided by the servlet container, then you should use someplace that is entirely outside of the servlet context's purvue, like `/path/to/temporary/files` or something like that. You definitely don't want to use the container's temporary directory for anything other than truly temporary files which are okay to delete on re-deployment, etc.

Problem

I have a Spring webapp whose `.war` file has been uploaded to a Tomcat server. Most of the basic functions are working as intended - page views and form submission. My problem now is that my webapp needs to read and write files and I am clueless as to how I can achieve this (the file I/O returns `java.lang.NullPointerException`). I used the following code to get the absolute path of a given file suggested by Titi Wangsa Bin Damhore to know the path relative to the server: ``` HttpSession session = request.getSession(); ServletContext sc = session.getServletContext(); String file = sc.getRealPath("src/test.arff"); logger.info("File path: " + file); ``` Here is the output path: ``` /home/username/tomcat/webapps/appname/src/test.arff ``` But when I checked the file directory via WinSCP, the file's actual path is: ``` /home/username/tomcat/webapps/appname/WEB-INF/classes/test.arff ``` Here are my questions: - How do I transform these paths into something like `C:/Users/Workspace/appname/src/test.arff` (the original path in my local machine that works perfectly)? It's servers are `Apache Tomcat 6.0.35` and `Apache Tomcat 6.0.35`. - Why is the code returning a different path as opposed to the actual path? - If file I/O is not applicable, what alternatives can I use? PS I just need to access two files (< 1MB each) so I don't think I may need to use a database to contain them as suggested by minus in this thread. File I/O Below is the code I use for accessing the file I need. ``` BufferedWriter writer; try { URI uri = new URI("/test.arff"); writer = new BufferedWriter(new FileWriter( calcModelService.getAbsolutePath() + uri)); writer.write(data.toString()); writer.flush(); writer.close(); } catch (IOException e) { e.printStackTrace(); } catch (URISyntaxException e) { e.printStackTrace(); } ```

Original source

Related problems