File system storage and servlets

[2010-03-13] dev, hack, webdev, java
(Ad, please don’t block)

One of the blessings of the JVM is that there are many “pure” databases available for it; Sesame (RDF) and Apache Derby (relational) come to mind. Alas, these databases need to save their files somewhere. This becomes a challenge with Servlets: Where should one put these files? Pre-packaged, read-only, files usually reside in SERVER/webapps/app/WEB-INF/, but mutable files? Putting them in WEB-INF makes upgrading a web application more difficult. I can easily imagine myself accidentally removing such data during an upgrade. The best solution, that I was able to come up with, is:

  • By default, the data directory of a web application “app” is SERVER/webapps/ (WEB-INF is necessary to protect against serving secret files).
  • This can optionally be configured via a file SERVER/webapps/ There, one can specify the servlet data directory via a relative or an absolute path. The former case is useful if you want this directory to be a sibling of SERVER/webapps. The latter case is useful for putting this directory anywhere on a system.
I do realize that there are security issues with this scheme: While it worked for me on Tomcat, I would expect other servlet containers to prevent servlets from writing files in this manner. Other options are:
  • Make the data directory a servlet parameter in web.xml: Complicates upgrades.
  • Specify a directory via the Java preference API: Prevents installing the same web application multiple times on the same system.
  • Storing the data in a temporary (as in File.createTempFile()) directory: Not a solution for long-term persistence.
Are there other solutions out there? Let us know in the comments.

Update 2010-12-14: One of the comments already mentioned this solution: I finally opted for storing files in the home directory. In Windows, the home directory is rarely directly accessed, while under Unix you can hide your web-application-specific directory by prefixing its name with a dot. So this solution works out well in both cases and fulfills all of the above requirements.