Encapsulating Java Preferences API - java

I used to have a custom preferences class for my applications. For my next hobby project i wanted to switch to the Preferences API. But the put and get functions require a default value and i do not want to spread default values all over the source files. Even though my project is small i can not imagine changing default values all over the source code. How do you guys use the api? I am thinking of wrapping the preferences api in another class but then what is the point of using the API because it only takes away the burden of saving the file to disk, which isn't that hard using serialization? Am i missing the point?

You're mixing a few concepts here. The default given in the code should be specific to the local situation as a 'reasonable default'. If you want to have application-wide defaults, then you need a preference-provider that allows you to hook in both the default preferences and an overlaid user-preferences. Something that may be a worthwhile project in itself.
Oh, and "reasonable defaults" is a great way to avoid configuration when it's not necessary but allow the user or packager to provide better values when needed.
#comment, I think I understand.
By 'local situation' I mean in the context of the code. For your GUI, you need a value for display that represents whatever the thread is using. Therefore I'd use something like Worker.DEFAULT_TIMEOUT. Your worker would use the same value internally as the default. That way you are retrieving the configured value or the worker's default when you are setting the worker's behavior.

then you might want to take full control over how Preferences should follow your desired storage by implementing AbstractPreferences. You can see a linux based implementation here:
http://www.docjar.com/html/api/java/util/prefs/FilePreferencesImpl.java.html
Good luck!

Would it be so hard to stick all your defaults in a single class so that they weren't littering your code?
I've used commons configuration in recent projects. I've looked into the Java Preferences API but I like the flexibility of the Commons project. And you don't have to specify default values!

You can put default values in .preferences file which you bundle in your .jar file (or in specialized class or interface with constants).
I use it for things like window positions/sizes, remembering default folder for choosing files, last opened files and such trivia. I can think of some interesting things you get "for free" with preferences API:
doing things in OS-recommended way; OS might not allow you to write "settings files" in your app folder, and users don't like to be asked where on disk they want to save settings, and you don't want to implement your custom logic for every platform
your data is saved for each OS user separately
a way to keep user data even if your application is uninstalled (or during an upgrade)
don't need database or access to file system
Also, I don't like serialization and don't recommend it for this. Serialization means you have to take care when changing your classes in new versions of your application.

Related

Centralized Application properties for multiple system

I am looking for a open-source solutions which allow hosting different properties for different applications and allow changes. On any change of properties it should notify or push the change to the application appropriately.
So, instead every application managing the properties in physical file and deploying physically; these properties can be pushed to a single system. User will have GUI to load and change the properties as per right. Should allow push as mentioned.
If you have already similar open source solutions in mind please advice.
Is this something that Puppet can manage for you?
I don't think what you've described (as nice as it would be) will be likely to exist in an app server. If a program is looking for a file, it's either going to load it with a FileReader (or similar), or it will use ClassLoader.getResourceAsStream(). It might be looking for data that is returned in properties, format, XML properties format, or even something completely different like RDF with which to configure itself. Also many programs read their config on start-up and then hold the values in memory, so you would still need to reboot them to get them to change.
To get something like this to work there would need to be a standard for configuration provisioning and live updates. Once that existed the webapp authors and server vendors would each need to add support for the standard.
If you are the one writing the programs to be managed however, then you can write your programs to request configuration from a service, and have a configuration push feature.... there may be packages out there that can speed up adding that to your code, but I get the impression you are looking to manage programs written by others.
Have you considered to use JMX? I think he could be a good starting point to implement your requirements.
MBeans's attributes can store your application's properties, the MBeanServer will allow you to make them available from remotting, JConsole offers you an GUI to update properties values.
You also can write within the MBean some code that notify the corrrespondig application when a user change any properties using the GUI.

Java File Wrapper API for Simple Data Structures

I want a simple file format to store and retrieve data from disk in Java.
name=value
list=value1,value2,value3
this is mostly going to be used for initial config settings used at startup of the app. I could invision having a watcher on the file to notify the app if it changes so the new settings can be applied potentially but that would be a nice to have. The first part would be pretty easy to write. I just don't want to reinvent the wheel if something is already out there for this and I'd prefer to avoid something as heavy as spring.
Take a look at the java.util.Properties class.
Properties
You can use the Preferences class. It has a notification system, but alas it doesn't notice changes made outside the running JVM or directly to the underlying configuration store (e.g. the config file). It's a really nice class though.
Have a look at OWNER API.
It incorporates most of the feature of java.util.Properties and adds more.
Version 1.0.4 is under development and it will have:
support for arrays and collections (list, set, arrays). It is already implemented on master branch.
"hot reload", when you change the file the config object gets reloaded (it can be synchronous or asynchronous and it does support event notification for reload). Already implemented in master branch.
a lot of features (variable expansion, type conversion). Available since version 1.0.3 and available on maven central repository.
Also for 1.0.4 is planned a validation mechanism that will check the file to be compliant before discarding the old content of the config file during the reload. (not implemented yet)
If you need some particular feature, just ask on github issues or become a contributor.

Application configuration save to file or object serialization

I am working on a project and I need to save user configuration. The configuration is a set of Jchechboxes I need to store their state (true, false). Which do you think is the better way of saving it, in a file and if yes in what (ini, cfg, txt), or it is better to serialize the object with the states?? Or if there is another way, please tell me :)
Cheers
It depends if you need to access the variables many times, and when: at the start of the application or during runtime?
If this configuration is user-related maybe you want to keep separate configuration for each user serialized on a Database so you can load them dynamically when a user loads the form that displays the checkboxes.
If there's just one possible configuration for one user (or such) maybe you should just put everything in a text file (the extension doesn't matter: ini,cfg,txt,lol anything you want) just simplify your life by using standard Java configuration access using the Properties class: http://java.sun.com/j2se/1.4.2/docs/api/java/util/Properties.html
How about a Properties file?
If you decided to store the properties as a serialized object then you will make changing the implementation of the gui much harder and thus less portable. If you save them in a text file then you are free to change the GUI implementation without any disruption to the user, whilst allowing the user to keep their saved properties.
As such, I would always recommend storing preferences in a properties type file. The Properties API, and related commons classes are pretty simple to use.
The best method is to use java.util.prefs to store user preferences

Disable Java reflection for the current thread

I need to call some semi-trustworthy Java code and want to disable the ability to use reflection for the duration of that code's execution.
try{
// disable reflection somehow
someObject.method();
}
finally{
// enable reflection again
}
Can this be done with a SecurityManager, and if so, how?
Clarification/Context: This is a follow-up to another question about restricting the packages that can be called from JavaScript/Rhino. The accepted answer references a blog entry on how to do that, and it requires two steps, the first one using a Rhino API (ClassShutter), the second one turning off reflection and Class.forName(). I was thinking I can do that second step more cleanly using a SecurityManager (learning about SecurityManager, which as has been pointed out, is a complex beast, along the way).
To sum up, I want (from code, not setting file) to turn off Class.forName() and any access to the whole reflection package.
It depends on what you are trying to restrict.
In general, publicly accessible API is not restricted. However, as long as you don't grant the untrustworthy code the ReflectPermission("suppressAccessChecks") permission, it won't be able to get access to non-public API in another package.
If you have a list of packages to which you want to restrict all access, there are two steps. First, in the Security properties, include the restricted package in the package.access list. Then give your trusted code RuntimePermission("accessClassInPackage." + pkg).
A common way to distinguish your untrusted code is to load it from a different location, and refer to the different codebases in your policy file when granting permissions.
The Java security architecture is very powerful, but I know it is also complicated; if you would like a more concrete example, please describe exactly what calls you want to restrict and I'll try to be more explicit.
To do what you want without modifying the java.policy file and/or the java.security file would be very difficult, maybe impossible. The java.security.Policy represents the information in java.policy, but it doesn't offer write access. You could create your own Policy implementation and install it at runtime as long as any existing SecurityManager permits it.
On the other hand, you can specify a custom java.policy file as a command-line option. If you are providing a complete application with some sort of launcher, that might be easily accomplished. It also provides some transparency to your users. A sophisticated user can review the permissions you'd like to have granted to the application.
Well, you can override SecurityManager.checkMemberAccess and give a stricter definition. However, it doesn't really work like that. What happens for instance if the code defines a finaliser?
On the clarification: Other APIs use reflection and other APIs. For instance, java.beans, LiveConnect and Rhino. An adversary could from within a script, say, create a new Rhino context without the shutter and thereby bootstrap into the full JRE. With an open system, a blacklist can never be finished.
In summary: to use the Java security model you need to work with it, not against it.
I wrote a replacement of ClassShutter that allows fine grained access control, per instance, per method, per field:
http://riven8192.blogspot.com/2010/07/java-rhino-fine-grained-classshutter.html

What is the proper way to store app's conf data in Java?

Where do you store user-specific and machine-specific runtime configuration data for J2SE application?
(For example, C:\Users\USERNAME\AppData\Roaming</em> on Windows and /home/username on Unix)
How do you get these locations in the filesystem in platform-independent way?
First on the format:
Java property files are good for key/value pairs (also automatically handle the newline chars). A degree of structure is possible by using 'dot notation'. Drawback is that the structure does not allow you to easily enumerate top-level configuration entities and work in drill-down manner. Best used for a small set of often tweakable environment-specific settings
XML files - quite often used for more complex configuration of various Java frameworks (notably J2EE and Spring). I would advice that you at least learn about Spring - it contains many ideas worth knowing even if you decide not to use it. If you decide to roll your own XML configuration, I'd recommend using XStream with customized serialization options or if you just need to parse some XML, take a look at XOM. BTW Spring also allows you to plug your custom XML configuration language, but it's a relatively complex task. XML configuration is best used for more complex 'internal' configuration that is not seen or tweaked by the end user.
Serialized Java objects - a quick and easy way to persist the state of an object and restore it later. Useful if you write a configuration GUI and you don't care if the configuration is human readable. Beware of compatibility issues when you evolve classes.
Preferences - introduced in Java 1.4, allow you to store typed text, numbers, byte arrays and other primitives in platform-specific storage. On Windows, that is the registry (you can choose between /Software/JavaSoft/Prefs under HKLM or HKCU). Under Unix the same API creates files under the user home or /etc. Each prefs hive can be exported and imported as XML file. You can specify custom implementation of the PreferencesFactory interface by setting the "java.util.prefs.PreferencesFactory" JVM property to your implementation class name.
In general using the prefs API can be a good or a bad thing based on your app scenario.
If you plan to have multiple versions of the same code running on the same machine with different configuration, then using the Preferences API is a bad idea.
If you plan using the application in a restricted environment (Windows domain or tightly managed Unix box) you need to make sure that you have proper access to the necessary registry keys/directories. This has caught me by surprise more than once.
Beware from roaming profiles (replicated home dirs) they make up for some funny scenarios when more than one active machines are involved.
Preferences are not as obvious as a configuration file under the application's directory. most of the desktop support staff doesn't expect and doesn't like them.
Regarding the file layout of the prefs it again depends on your application. A generic suggestion is:
Package most of your XML files inside application's JAR either in the root or under /META-INF directory. These files will be read-only and are considered private for the application.
Put the user modifiable configuration under $APP_HOME/conf . It should consist mainly of properties files and occasionally a simple XML file (XStream serialization). These files are tweaked as part of the installation process and are usually not user serviceable.
Under the user-home, in a dot-directory (i.e. '~/.myapplication') store any user configuration. The user configuration may override the one in the application conf directory. Any changes made from within the application go here (see also next point).
You can also use an $APP_HOME/var directory to store any other mutable data which is specific to this application instance (as opposed to the user). Another advantage of this approach is that you can move and backup the whole application and it's configuration by simple copy of one directory.
This illustrates some standard techniques for managing configuration. You can implement them using different libraries and tools, starting from raw JRE, adding Spring/Guice or going for a full J2EE container (possibly with embedded Spring)
Other approaches for managing configuration are:
Using multiple base directories for running multiple instances of the application using different configurations.
Using lightweight registries for centralized configuration management
A centrally managed Configuration Management Database (CMDB) file, containing the host-specific values for each machine is rsync-ed every night to all production hosts. The application uses a templated configuration and selects from the CMDB during runtime based on the current hostname.
That depends on your kind of J2SE Application:
J2SE executable JAR file (very simple): use user.home System property to find home-dir. Then make a subdir accordingly (like e.g. PGP, SVN, ... do)
Java Web Start provides very nice included methods to safe properties. Always user-specific
Finally Eclipse RCP: There you have the notion of the workspace (also derived from user.home) for users and configuration (not totally sure how to access that tricky in Vista) for computer wide usage
All these approaches are, when used with care -- use correct separatorChar -- OS neutral.
Java has a library specifically for doing this in java.util.prefs.Preferences.
Preferences userPrefs = Preferences.getUserNodeForPackage(MyClass.class); // Gets user preferences node for MyClass
Preferences systemPrefs = Preferences.getSysteNodeForPackage(MyClass.class); // Gets system preferences node for MyClass
Preferences userPrefsRoot = Preferences.getUserRoot(); // Gets user preferences root node
Preferences systemPrefsRoot = Preferences.getSystemRoot(); // Gets system preferences root node
I use this
String pathFile = null;
if(OS.contains("win")){
pathFile = System.getenv("AppData");
}else{
pathFile = System.getProperty("user.home");
}
I save the settings of my application here
C:\Users\USERNAME\AppData\ on windows
user.home (/home/USERNAME) on other platfroms
For user specific config, you could write a config file to the folder pointed to by the "user.home" system property. Would only work on that machine of course.
You might want to look at Resource Bundles.

Categories

Resources