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.
Related
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.
In my web application which I use primefaces+SpringWebflow. I need to add a picture which is scanned or uploaded to every customer registered. I can not think of any good solution to store the files. Criteria is that.
I want only application have access to files and it shouldnt be possible to access the images directly.
I tried to store the files in database but thats not good idea. i store the path in database.
I would like to have relative paths to files. and efficient wy to access the file.
Just store the files in the database. If you try to put them somewhere else, it will be difficult to migrate your application from one server to another, because its data will be spread across multiple sources. Upgrades will be more difficult.
If performance / database size becomes an issue, revisit this decision, but make sure you always measure rather than guess the performance.
Why is it not a good idea to store the files in DB ?
What will happen when you deploy your application on a clustered server environment ? In clustered server environment your solution of keeping images on file-system will not work.
You need to think more on keeping storage of images in DB in mind. Just investigate what performance hit you are getting in storage/retrieval of images in DB. try different kind of storage frameworks like nosql DBs. Essentially you can not get away with storing data at a central location I think.
Say, I have a pretty simple Java application that needs the way to store some user settings. XML is not a really good solution, since I want to store them in binary form. So, what would be the best solution in this case, embedded database (such as Apache Derby) or just plain old serialization?
I know that these are two completely different things, but both allow to persist some application state. So what would you chose, and why?
Edit
As far as storing simple user preferences go, .properties or xml files are fine, I agree with you. But what if I want to store passwords, or some application-specific data?
User settings are typically stored as
properties, using the properties file format
properties using the XML format
preferences, using the Preferences API. This has the advantage of storing and reading user and system preferences for you, without having to think about where to store them, etc. See http://download.oracle.com/javase/1.4.2/docs/guide/lang/preferences.html
As Apache Derby is an embeddable relational database, it makes sense to use it for storing and manipulating relational data. Using an embedded db for persisting a few user settings only is a bit overkill.
If it were me, I would use a simple key/value pair serialization for persisting user settings.
I am creating a few JAX-WS endpoints, for which I want to save the received and sent messages for later inspection. To do this, I am planning to save the messages (XML files) into filesystem, in some sensible hierarchy. There will be hundreds, even thousands of files per day. I also need to store metadata for each file.
I am considering to put the metadata (just a couple of fields) into database table, but the XML file content itself into files in a filesystem in order not to bloat the database with content data (that is seldomly read).
Is there some simple library that helps me in saving, loading, deleting etc. the files? It's not that tricky to implement it myself, but I wonder if there are existing solutions? Just a simple library that already provides easy access to filesystem (preferrably over different operating systems).
Or do I even need that, should I just go with raw/custom Java?
Is there some simple library that
helps me in saving, loading, deleting
etc. the files? It's not that tricky
to implement it myself, but I wonder
if there are existing solutions? Just
a simple library that already provides
easy access to filesystem (preferrably
over different operating systems).
Java API
Well, if what you need to do is really simple, you should be able to achieve your goal with java.io.File (delete, check existence, read, write, etc.) and a few stream manipulations with FileInputStream and FileOutputStream.
You can also throw in Apache commons-io and its handy FileUtils for a few more utility functions.
Java is independent of the OS. You just need to make sure you use File.pathSeparator, or use the constructor File(File parent, String child) so that you don't need to explicitly mention the separator.
The Java file API is relatively high-level to abstract the differences of the many OS. Most of the time it's sufficient. It has some shortcomings only if you need some relatively OS-specific feature which is not in the API, e.g. check the physical size of a file on the disk (not the the logical size), security rights on *nix, free space/quota of the hard drive, etc.
Most OS have an internal buffer for file writing/reading. Using FileOutputStream.write and FileOutputStream.flush ensure the data have been sent to the OS, but not necessary written on the disk. The Java API support also this low-level integration to manage these buffering issue (example here) for system such as database.
Also both file and directory are abstracted with File and you need to check with isDirectory. This can be confusing, for instance if you have one file x, and one directory /x (I don't remember exactly how to handle this issue, but there is a way).
Web service
The web service can use either xs:base64Binary to pass the data, or use MTOM (Message Transmission Optimization Mechanism) if files are large.
Transactions
Note that the database is transactional and the file system not. So you might have to add a few checks if operations fails and are re-tried.
You could go with a complicated design involving some form of distributed transaction (see this answer), or try to go with a simpler design that provides the level of robustness that you need. A possible design could be:
Update. If the user wants to overwrite a file, you actually create a new one. The level of indirection between the logical file name and the physical file is stored in database. This way you never overwrite a physical file once written, to ensure rollback is consistent.
Create. Same story when user want to create a file
Delete. If the user want to delete a file, you do it only in database first. A periodic job polls the file system to identify files which are not listed in database, and removes them. This two-phase deletes ensures that the delete operation can be rolled back.
This is not as robust as writting BLOB in real transactional database, but provide some robustness. You could otherwise have a look at commons-transaction, but I feel like the project is dead (2007).
There is DataNucleus, a Java persistence provider. It is little too heavy for this case, but it supports JPA and JDO java standards with different datastores (RDBMS, object storage, XML, JSON, Excel, etc.). If the product is already using JPA or JDO, it might be worth considering using NataNucleus, as saving data into different datastores should be transparent. I suppose DataNucleus supports splitting the data into several files, creating the sensible directory/file structure I wanted (in my question), but this is just a guess.
Support for XML and JSON seems to be experimental.
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.