Where to store application data (non-user specific) on Linux - java

In my OSGi-based Java application I am developing a bundle to provide the rest of the system with access to the file system. In addition to providing access to the user home directory, I also wish to provide access to a non-user specific area. Exactly what this area will be used for is as yet undetermined, but it will not be for preferences (handled by a different bundle), however it may be used to store data that could change at runtime.
I intend on using the following directories for this purpose:
Windows Vista and Windows 7: “\ProgramData”.
Windows XP: “\Documents and Settings\All Users“.
Mac OS X: “/Library/Application Support”.
Where is a sensible equivalent in Linux and how do I get a handle on it from my Java code?

It depends on what kind of data you're planning on storing. This answer is under the premise that you're storing and modifying data at run time.
Contrary to what others have suggested, I would recommend against using /usr/share for storage. From the Filesystem Hierarchy Standard:
The /usr/share hierarchy is for all
read-only architecture independent
data files.
As you're modifying data, this goes against the read-only nature of the /usr subsystem.
A seemingly better place to store your application state data would be /var, or more specifically, /var/lib. This also comes from the Hierarchy Standard. You could create a /var/lib/myapp, or if you're also using things like lock files or logs, you could leverage /var/lock or /var/log.
Have a deeper look at the standard as a whole (linked to above)—you might find a place that fits what you want to do even better.
Like Steve K, I would also recommend using the Preferences API for application preference data.

It depends.
Global configuration → /etc/appname
Read-only, independent of machine architecture → /usr/share/appname
Read-only, machine specific → /usr/lib/appname
Read-write → /var/lib/appname
There isn't any guarantee for completeness. Please
check the Filesystem Hierarchy Standard.

Since you are using Java, look at the Preferences API.
From the introduction:
Applications require preference and configuration data to adapt to the needs of different users and environments. The java.util.prefs package provides a way for applications to store and retrieve user and system preference and configuration data. The data is stored persistently in an implementation-dependent backing store. There are two separate trees of preference nodes, one for user preferences and one for system preferences
I'd let the built-in API do the work.

The freedesktop.org (previously known as the X Desktop Group) project has defined some standards for this in the XDG Base Directory Specification.
In your case, I'd have a look at $XDG_DATA_DIRS:
$XDG_DATA_DIRS defines the preference-ordered set of base directories to search for data files in addition to the $XDG_DATA_HOME base directory. The directories in $XDG_DATA_DIRS should be seperated with a colon ':'.
If $XDG_DATA_DIRS is either not set or empty, a value equal to /usr/local/share/:/usr/share/ should be used.
I warmly suggest to read the XDG Base Directory Specification.

In the /usr/share or /usr/local/share folders.

According to Filesystem Hierarchy Standard
(which seems to be updated and correct as of July 2015)...
Assuming that the datafiles are understood to not meet the requirements of /tmp or /var/tmp then /usr/local/share/theApp or /usr/local/theApp.

If it is non-user-specific, you can probably store it under /usr/share/appname

You could use the System.getProperty("user.home") to get the users home, so it's more platform independent.

Related

Best way to get values from a external file in java

I have a java code which I'm currently running as a jar. This code checks for a specific file in the given directory which is currently hard coded in the code.
To give more flexibility and not to touch the code. I would like to have the folers list managed by a different file and the code reads this config file and gets the list of folders each time and execute it.
I would like to know which is the best possible option of maintaining the folder list outside the code so that anyone can update it. Can a properties be used for this ? can we dynamically take values from a property file
In Java you have the java.util.Properties that allow you to load flat key/value data from external resources.
If you need something that can be dynamically updated, there's also the more sophisticated Preferences library. This one allows you to:
Keep data organized in tree structures (it's a tree of nodes, each node storing its own key/value preferences).
Make use of basic types (primitive types, strings and binary data).
Make use of platform-dependent "native" stores transparently (under the hood, it's going to use the file system on Unix systems and registries on Windows by default).
Plug in your own backing store if needed.
Get any data changes performed within the application persisted transparently.
Register node/preference change listeners and react to any change if needed.
The API is quite old and hasn't been updated, but it doesn't mean it's deprecated. It is used mostly with GUI applications (notably, IntelliJ IDEA was storing its configuration using Preferences the last time I checked).
There's also an attempt to revive this library that I made with a project called cross-preferences by integrating modern distributed config stores (such as zookeeper, etcd or consul) as backing stores for java.util.prefs.Preferences and providing a web console for preference management.

Properties location

I need to create a properties file to store username/passwords for DBs and other websites for my application.
Is there a good place to put this?
I was thinking of putting in /usr/local/myapp/myapp.properties
However...this doesnt really make much sense for Windows boxes. However, I don't want to store it under a particular user's account as I want it to be global for all users.
Any thoughts?
Store it wherever you like, and point your application to it via a vm parameter: -Dproperties.location=/usr/local/...
Then you can read it with System.getProperty("properties.location")
If you use the built-in Preferences class, the values will be automatically saved in the appropriate place on the user's system.
Edit:
Oops, I missed the "global to all users" requirement. This will not work on all systems in that case.
I have written on this property framework for the last year.
It will provide of multiple ways to load properties, and have them strongly typed as well. Which also include a way to encrypt/decrypt a password property.
Have a look at http://sourceforge.net/projects/jhpropertiestyp/
JHPropertiesTyped will give the developer strongly typed properties.
Easy to integrate in existing projects.
Handled by a large series for property types.
Gives the ability to one-line initialize properties via property IO implementations.
Gives the developer the ability to create own property types and property io's.
Web demo is also available, screenshots shown above.
Also have a standard implementation for a web front end to manage properties, if you choose to use it.
Complete documentation, tutorial, javadoc, faq etc is a available on the project webpage.

What is the right location to store persistent objects?

I am developing a medium Java desktop application, without using a database.
I am using xml, serializable objects, etc. to store the user/application data, but what is the right location to save these files to (system-independent)?
If you really don't want to store them in a data base take a look at the Preferences API it is platform neutral.
Why aren't you using a database? Use file-system database (like hsqldb) and an object relational mapping layer. You probably won't even need to write a mapping file of any kind, or arbitrarily make your classes serializable.
Store data in %APPDATA%/appName on windows, and probably ~/.appName on linux.
User/Library/Application/appName could work on macs.
Most, if not all, OSes have a concept of a home directory where you end up having a lot of hidden configuration directories of one form or another. You could create a hidden directory under the users home directory and store your configuration/data files there.

Where to store preferences in a Java application?

I need just a solution to retrieve a path for storing desktop application settings (e.g. a sqlite database) that meets following needs:
cross platform
works from jar and from "normal" invocation
I've spent a lot of time googling and experimenting with getting the codebase path via X.class.getProtectionDomain().getCodeSource().getLocation() and java.util.pref.Preferences
class, but return values gave sometimes different results, returned null or just "/" as path.
"Cross Platform" is kind of hard to define. A solution called "best practice for each platform" won't be easy to achieve. Making a difference between user-specific and shared data would be sensible.
java.util.prefs.Preferences is the proper way to do it. It works perfectly fine (I've used it in a desktop application without any problems). It is cross-platform and is available without any extra jars. It also differentiates between user-specific and global data. Perhaps shed some light on your particular problems with it (or ask another question)
Of course, you can use java.util.Properties as well, and store files in System.getProperty("user.dir").
System.getProperty("user.dir") returns a path to the user directory for most modern systems.

Where/how to store persistent data with tomcat?

Where should I store persistent files in a Tomcat web app ?
javax.servlet.context.tempdir is not feasible, it's erased when the app is redeployed/removed
Don't want to use an absolute path in e.g. servlet init parameters
Storing the files in a database is not an option
Our team does this a lot. A general rule we follow is outside the web app and outside Tomcat.
Our sysadmin set up a directory on our server that the tomcat user has rw permissions to (e.g. /var/tomcat/persist). We have a built a directory structure under this that tomcat uses to store files, read app-specific init files, etc.
If you don't want to use an absolute path in your init-params for your servlet, consider setting a system property when tomcat is started up. The good thing about that is every application running under tomcat will have access to it. The bad thing about that is every application running under tomcat will have access to it. You could set a property named base.persist.dir and build subdirectories for each application underneath it. We set system properties in the setenv.sh script in the bin/ directory under the CATALINA_OPTS environment variable.
Answering the title of the question, what about using a database, a DataSource and JDNI? Even in a web only context, writing to files using java.io is not really recommended because of concurrency, threading, security, clustering, portability issues. Some of these problems can be "workarounded" but still, this is not really a best practice. The standard approach is to use a database and I'd suggest to reconsider this option, throwing "file-based" lightweight database like HSQLBD or JavaDB into the mix.
(EDIT: For an unknown reason, database is not an option. Using JNDI or context parameters or init parameters to pass an absolute path - which are the less worse options IMHO - is excluded too. For a relative path, maybe look at user.home or user.dir then - or any other system property that you could pass on the command line. I don't like it, I wouldn't do it, and this doesn't solve the issues previously mentioned, but it's your choice after all.)
Storing the files in a webapp directory under the home directory of the user running Tomcat is a good and convenient option. It is outside of Tomcat, which means it will survive redeployment, and it is usually a writable directory (because it is created under the users' home dir).
But it is always a good idea to allow overriding the location of such directory via system property.
Generally, this would go to the database. But since the OP insists on not using a database, I'd try a different approach:
Filesystem path which is known: ${user.home}/.myapp. Applications sometimes use this for e.g. search indices which can be recalculated based on data in the database. Might be okay for your use case to use the user's home.
Store the configurable filesystem path in a configuration repository such as the database or perhaps Java Preferences (if you don't like to use servlet init params). Commercial applications such as Atlassian JIRA use a configurable (but absolute) filesystem path where they store issue attachments. If they don't know a better way, i don't know who does :)
I generally would suggest to use a database to store persistent data and expose it via a DataSource.
If you don't want to do that, I guess you could consider using the "user.home" system property (I have seen this used in a few circumstances). But... there are no guarantees that your servlet will be run with permission to write access unless you configure that yourself.

Categories