Third party vendors using our software as a component view Windows Logo Certification as an important selection criteria. 90% of the requirements are easy to adhere to given the flexibility in deploying Java programs. Some immediate difficulties present themselves:
Tagging jar files with resource strings for versioning information.
Moving From properties files to .INI files
Short Path Name / Long Path Name / UNC isn't well support by the libraries
Look and feel requirements
These will require some serious recoding to address. I may be interpreting the specifications too closely. I found one decent example of an application that obtained Windows 2000 certification. The look and feel in this instance only refers to any visible installer that we present. Even the specifications themselves imply things in the descriptions that are not really covered in the title of the requirement.
1.5 The application should not read from or write to Win.ini, System.ini, Autoexec.bat or Config.sys
excerpt:
If your application uses information that you do not want to put in the registry, create a private initialization file and place it in the directory with the application's executable files. You can easily manage the installation of a private .ini file, as well as add or remove information from existing .ini files, by using Windows Installer to install your application.
Any feedback would be appreciated.
For the look and feel, call this at the beggining of your main() function:
log.info("Setting java look and feel");
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
log.warn("Could not set system look and feel", e);
}
// Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
Please note that the example of an INI file should not be taken as a mandate. What you call the "title" is really the requirement itself. The reason for this is that the specifications are intended (amongst others) to prevent application installations from interfering with each other. Moving to private configurations (whether in the file system or in the registry) supports this.
In fact, the current suggestion is no longer INI files, but the registry for small parts of the configuration, and XML files in %APPDATA% if you've got a lot.
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'm writing a cross-platform program in Java and want to stick the configuration files in the user's documents folder ("My Documents" under Windows, "Documents" under appropriate Linux, and whatever the folder's called under Mac OS), but I'm not sure how to ask Java for that.
I'd like to stay away from hard-coding things (do X if we're on Windows, Y if we're on Linux, or Z if we're on OS X), as this puts the burden of support on my shoulders rather than the Oracle development team.
I've checked the system properties list, but it doesn't seem to include the user's documents folder.
Sadly there is no easy cross-platform way. You will have to take advantage of native functionality on each OS platform
Here is some info on how to do it in osx
Here is some info on how to do it in windows
For Linux I don't have a convenient link, but given that there isn't necessarily the concept of a Documents folder in Linux, I don't know of a good solution. The system property user.home should at least be valid in Linux.
Partial solution:
boolean isMac = System.getProperty("os.name").equals("Mac OS X");
Or use http://commons.apache.org/vfs/ to get the operating system:
http://commons.apache.org/vfs/apidocs/org/apache/commons/vfs2/util/Os.html
// the folder name is the same whatever the language of Mac OSX.
Mac: System.getProperty("user.home")+File.separator+"Documents");
/Users/david/Documents
Win: System.getenv("APPDATA"));
C:\Documents and Settings\david\Application Data
This is usually not possible in a generic way. You will have to use platform dependent apstractions. I do it like this for AppData e.g., on Windows I detect the AppData/Roaming or AppData/Local, depending on the data I need to store, on other Platforms I create a folder ".myappname" in the userhome, and use this.
For the documents folder, you will have to read the registry. Before Windows Vista using the user.home propery + "/Documents" is not enought, because in other languages it might be "/Dokumente" (german) or something else. Just the registry has the real path to this folder.
On linux platforms it depends on the Desktop environment. You will just have to try it out. Gnome and KDE use different places to store the Documents folder, IMHO. And if you just use FVWM there, there is no predefined place for docs except the user.home property, what is a good fallback.
Assuming this is an application which requires installation, Why not ask the user to specify the location during installation. Generate a run script using this information which would set the appropriate environment variables. As a norm the user is not expected to run the java command!
When the user starts the application using this run script, the application can read the environment variables.
Alternatively, create a jar file with configuration files. Read the config files using Classloader's getResourceAsStream. As long as the configuration jar is under the classpath you can access the files. This also has the added advantage of hiding the configuration from accidental modification. This should work for folders as well (if the config needs to be modified by the user).
Ask the user, somehow, where they want to save data to, or use the current directory (simple relative paths) and provide appropriate instructions for set up. One means of "asking" is having a property that can be set via the command line.
Don't just pollute the user's home directory with your application's stuff - how do you know how they like their document tree organized?
I am absolutely fed up with *nix oriented programs dropping their little config files and data folders into the root of my documents folder.
What is wrong with hardcoding a way to get the path depending on the users operating system?
There can be large variances and OS's work differently with different names.
Simply on launch find the path of the documents folder based on their OS and continue to reference that path wherever it is needed.
I am displaying a list of files; i.e. xls, doc, pdf, odt etc., in my Java application (Eclipse RCP). When the user clicks on the file, I want to launch the appropriate (according to what the OS thinks) native application, just like it happens in Windows Explorer or the Finder.
And while I am here: It would be nice to also display the same icons that Finder or Explorer use for the different file types.
Is there a library or Eclipse plugin for this?
What you want is java.awt.Desktop:
Desktop.getDesktop().open( file );
I have found an API in Eclipse's SWT now that seems to do the trick:
org.eclipse.swt.program.Program "provides access to facilities for discovering operating system specific aspects of external program launching."
It has methods to find the program for a given file extension, get the program's icon, and even launch the program.
Sounds like you're after the Java Activation Framework ("JAF"). This API lets you determine what files are and what actions you can do on them. Or alternatively the Java Desktop Integration Component ("JDIC"). JDIC allows you to create and no doubt query file associations.
Both projects seem to be in a semi-abandoned state howeer (sigh). But that's par for the course for Sun these days. Only other thing I know of is some Windows specific third party library that's based on JNI called Winpack. It does a bunch of other things too.
You can get the associated icon using the FileSystemView class (Java 1.4+).
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.