I am working on a Java Desktop program which upon its installation will designate a default database directory and working directory. Where should I save such information so that the next time the user open the program, the program knows where to look for database and working directory?
Things that come to mind:
store everything in the registry (well, did that in MATLAB version and if there is another way, definitely will not go there).
set up another database attached in the jar file to store everything
Is this a so called persistence problem? What are Java Persistence or Java Data Object? Do they have the way to make it working?
any other suggestions?
Take a look at the Java Preferences API. It is a standard Java SE mechanism for storing preferences that does so in a platform specific, but application neutral way. Uses the Registry on Windows, Preferences files on OS X, and I believe ~/.files on Unix.
The Preferences class was created to store things like... preferences in an OS-neutral fashion.
You could also just specify a directory location manually, through a launcher script, or create a default directory in the user's home, and keep both configuration and DB files there.
Your persistent memory is your hard drive, of course, so you need to store data there if you want it to persist from execution to execution. Really, anything goes. You could store the configuration in an XML file -- makes it user-readable outside of the application, which is really nice for debugging, and Java comes with libraries for XML parsing and generation. It would be OS-independent, unlike a registry solution, which is Windows specific. And you could use the XML approach to share information between apps, if that matters. Something to consider.
Update: Preferences are cool! Never saw that one before.
Related
In UNIX and its derivatives, application config files live under /etc/, whereas they live elsewhere on Windows and other systems. The philosophy behind java is "Write once, run everywhere" and an app ideally shouldn't have to care what OS it's on. But I want my application to load a config file on startup and I need to provide a path. Right now, I'm loading different file locations switching off of the OS name, but this doesn't feel like it's best practices for Java. How do I reconcile this?
When I am making a game/app I just put a resources folder in the same path as the app. For example in the code, the directory would be "res/config.yml". In the same folder as the jar you put the resource folder named "res". you then put the file in the res file. So the app should get the file.
I usually put configuration files in a directory .<appName> (note the leading dot) in the user home, which is read at runtime via System.getProperty("user.home"). This is the expected location for Linux users, while on Windows it feels a bit exotic (compared with profile directories like AppData/Local or AppData/Roaming) even if it's an extremely popular choice for cross-platform tools. Using the current user's home means you won't usually have troubles with filesystem access rights, and using user.home is preferred instead of a custom property because it's provided out of the box by the system (and still it can be overridden)
Another approach is using the installation directory, but then you have to use an environment variable that points to that, like $APP_HOME, because it can't generally be inferred while the application is running (actually you can get the installation directory pretty easily for typical JAR deployments by playing with URLs returned by the main ClassLoader, but I consider it a hack and think it shouldn't be used). Your application can read the variable with System.getenv("APP_HOME"), and this variable must be set by the platform-dependent scripts you provide to start your application. This strategy has the downside that the current user may not have the rights to read/write to the named directory.
In our application we use different locations for configuration on each OS.
On Linux
/etc/applicationname
On Windows
[Use Selected Install Dir]/conf
We control where the application looks via a system property
-Dconf.dir=path
I don't necessarily think there is a correct answer in this case.
Is there a way to change working dir for JVM when running Java Webstart?
When i use system.setProperties("user.dir", newDir) it sets it(system.getProperties() shows it does) but ignores it.
Is this a limitation in Java Webstart to always use the working dir where i started the jnlp file?
I am using all permissions in the jnlp file.
Please help!
EDIT: Whatever i do now, my webstart always uses user.dir to save files. Frustrating!
I've had this question in the past myself, but I've always found that, in the end, I didn't need it. Why do I say this?
Because your java web start app is not like an executable run from Program Files. It doesn't even exist on your computer like most programs (it is broken up into a bunch of different files and reassembled by the JVM). Therefore, you cannot say that the program has its own directory to do what it needs.
But it doesn't need to. Here's why:
Java has the Preferences API to help when you need to store data. The under-workings of the Preferences API is as mysterious as JWS, thus they are really a perfect fit. Either way, if you need to write things to a file, you should check this API to see if it can meet your needs.
If you need to write files for the user, then prompting them and allowing them to choose the location obviously means you won't use your current working directory to read/write files.
If you need to serialize objects, you should just create a program directory using the user.home resource as #AndrewThompson suggested. This will be "your" directory and is as good (in fact, better) than a directory in Program Files (if you're running on Windows, as an example).
In conclusion, in all cases (that I've come across), there's no need to change your current working directory. If you need your own folder, create one in user.home (because you won't run into file permissions issues there).
..all my settings file i use is created in the user.dir.
There is the mistake. Put them in a sub-directory of user.home & the problem is solved.
In the hypothesis you really really need to divert user.dir property for Java WebStart execution, here is the only option I have found: set this system environment variable (so system wide):
_JAVA_OPTIONS="-Duser.dir=C:\Temp"
But care about it, this option is read and applied to any JVM executions.
Why was it required in my context ? Because Java WebStart ClassLoader was looking for any single resource (class, properties...) in user profile before getting it from jar files in cache. As the user profile has been moved to a network storage, application start up became terribly slow. I am still investigating Java sources to understand (and avoid) this behavior. So my applications work perfectly without setting user.dir but that was the only work-around for the performance issue we got at the moment.
The recommended way to pass runtime parameters or user specific setting is through the jnlp argument
<application-desc main-class=".....">
<argument>user.home</argument>
..............
I have finished writing a Java Desktop application with a mySQL database. I want to make the application run outside netbeans and let it be installed on other computers. I know about building the project and creating the runnable jar file, however this requires me to export the database itself to the other computer I want the application to run on.
My question is two parts:
1)Is there a way I can create a setup file that also installs the database and the application together?
2)Also my database path is hard coded, does that mean I have to change the code every time I install my application for someone, what is the better way to do that?
Thanks
Yes. You can use some setup builder, like InnoSetup, for example. Personally, however, I like giving my customers a zip file, which they extract wherever they like. The executable jar should be able to handle everything by itself (I like it where there is no need to install the software, just unpack and run).
If it is hardcoded, then yes (but, what do you mean by hardcoded? path to file? ip address?). You should use properties or configuration files for paths and other external things your software depends on. The software should read from those files. Upon startup check for presence of such file(s) - if missing, the user should be shown a window in which the config can be entered.
As for deploying MySQL with your code - consider using a server for that, so that your users are not forced to install MySQL, instead they connect to it over the net. If you need the database only for storing data locally, why not using SQLite or a similar, file-based db engine?
The above answers are just suggestions and more-less reflect the way I am thinking. I would be happy to hear from someone with more experience. Nonetheless, I hope the answers help a little :)
I agree with Sorrow.
If I have to use MySQL, it is normally over the net since I don't want to allow my clients pass through the hazzles of installing MySQL themselves. If however you am stuck with using MySQL locally, investigate MySQL unattended installations + NSIS Installer.
If you can use any db you want, I just use javadb/derby. It comes bundled with most Java installations these days and if not all you need is to add a jar file to you application.
As per 'hardcoding' paths, I really don't understand what you mean. You really don't have 'paths' as it were, I am assuming what you mean is connection string. You don't have to hardcode your connection string, just put some parameters in a properties file and construct your connection string from them.
1) Is there a way I can create a setup file that also installs the database and the application together?
See my answer to Java based Standalone application.
2) Also my database path is hard coded, does that mean I have to change the code every time I install my application for someone, what is the better way to do that?
Have the DB installer pop a JFileChooser to ask the user where they want to install the DB. Store that path using the JNLP API PersistenceService. Here is my demo. of the PersistenceService.
I have a Java app that runs on a Windows mobile device. At startup the app talks to our server to see if any files need updating and downloads them if they do. If any of the files are dlls they need to be stored in a temp directory and the device is rebooted because they might be currently in use. When the app starts it reads an xml file that lists all of the temp files and where they need to go and copies them into place.
A new requirement has come up that involves also updating the JVM files as part of this process. Since the code that does the copying is run on the JVM there is no way to do it since the files will always be in use. So we are looking at writing something in native code to do this copying process.
Before we start, I was just wondering if anyone knew of an already existing application or technique that does this (someone suggested a registry entry that tells the device to copy files on startup for example). Basically the requirement is to read some sort of configuration file that details the location of the source file and the destination then performs the copy. Any ideas before I reinvent the wheel by writing an app myself?
If your target handsets are handheld barcode scanners (Symbol, Intermec, etc.) they already have a framework in place for this. I don't have all the details, but I know from previous projects that they have a "protected" memory location that allows application to essentially re-configure / copy themselves from hard boots and similar problems. It might be worth seeing if any of that would work on your existing targets.
The scanners use either Windows CE or Windows Mobile.
In the absence of another answer, I have written a simple app to do it and put it in the startup directory. Was pretty easy, just didn't want to reinvent the wheel.
You can also rename your running executable file by the running-application itself. After this you can copy the file into the directory and simply restart your application.
My Java application is saving stuff in 'user.home' but on windows this does not seem to be the correct path to save application information (as a friend told me). An other option is using the preferences api but it's not possible to set up the hsqldb location using the preferences api. Also, I want all files to be available in the same folder (local database, config, cache, ...).
I'm looking for some example code or a framework that takes care of os-specific stuff.
On my WinXP Pro SP3 system, user.home points to C:\Documents and settings\<username>
Lot of applications just store their data there (instead of this path + Application data, but some others go down to there), creating a directory in Unix style, ie. dot + application name (examples: .antexplorer, .sqlworkbench, .squirrel-sql, .SunDownloadManager, .p4qt, .gimp-2.4, etc.).
Looks like a decent, common practice...
It's unusual for a window app to save data in user.home but not "wrong". Windows applications love to spread their data all over the place (a bit in the registry, a bit in the application's install directory, a bit in the Windows directory, a bit in System32, a bit here and a bit there). In the end, this makes it impossible to cleanly backup or remove something which results in the famous "Windows rot" (i.e. you have to reinstall every few months).
Anyway. If you really don't want to use user.home (and I see no reason not to), use code like this from Apache commons-lang to figure out if you're running on Windows. If this yields true, pop up a directory selection dialog where the user can specify where they want to save their data.
Save this information in Preferences and use this path the next time when your app is started. This way, users can specify where they want their data and you only have to leave one bit of information in the prefs.
For an application "foo" I'd create a directory named ".foo" inside user.home. For Windows it will look slightly strange, but almost noone ever looks in that directory (and it's filled with obscure directories anyway) and on Linux/Solaris/... it will result in a hidden directory that doesn't clutter the users home directory visually.
dynamically read (from your code) the value of APPDATA environment variable, and store your config files in %APPDATA%\\.myapp\config
==> value is platform dependent, do not use any hard-coded paths, always read the env. var.
The problem is not Wiindows but the standard java setup.
Long Discussion
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4787931>Here
I would advise picking this up on a '-D MYLOC=%USERPROFILE%' property on the command line.
Note that you will only get a "USERPROFILE" if the user did a desktop login, this does not get set if the user logged in remotly with citrix or similar or via ssh, also, coprporate desktops mess around with this setting and may set it to something unusable.