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
Related
I am building a Java Application with the intention of packaging it to be a windows executable in the future. My NetBeans project structure can be seen
here.
I am currently reading from config.properties using getResourceAsStream(). I was not aware that this file cannot be written to in a similar manner. Would anyone be able to advise a way to achieve this or is a different approach to my problem required? Thanks.
I think you can use java.util.properties to solve your problem; to write to your properties first create a new Properties object, load them via your InputStream, use methods such as setProperty to add to your configuration and finally use store to write to them.
Example:
File appConfig = new File("a_file");
FileInputStream propsInput = new FileInputStream("a_file");
Properties prop = new Properties();
prop.load(propsInput);
try (Writer inputStream = new FileWriter(appConfig)) {
// Setting the properties.
prop.setProperty("A_PROP", "A_VALUE");
// Storing the properties in the file with a heading comment.
prop.store(inputStream, "INFORMATION!!!");
} catch (IOException ex) {
ex.printStackTrace();
}
There's no straightforward answer to the question how to externalize configuration -- it depends on the application and the environment in which it will be deployed.
The Java preferences API is an attempt to get around this problem by providing a platform-neutral API for preferences. On Linux, the data is actually stored in an XML file in a subdirectory of $HOME/.java but, of course, the programmer isn't supposed to be concerned about this. Using this API is convenient, but doesn't allow complex data to be stored, and doesn't easily allow the programmer to provide the application with a way to read configuration from some specific place.
Rather than use the preferences API you can read/write files explicitly. For simple 'name=value' configuration, you can use a Properties object, which has methods for handling files. This method does allow a specific file location but, of course, controlling the file location does require some adaptation for the various platforms you might support.
If your configuration is more complex than 'name=value', you could read/write it in a format of your choice -- JSON, YAML, XML, etc. All these file formats are well-supported by Java. Using a text-based format allows users to edit the configuration using other tools, if they so wish.
In practice, I nearly always externalize configuration in serialized Java objects, into a file whose location I control. This allows configuration of arbitrary complexity without additional coding, since you're storing Java data directly. It takes a bit of work to structure a program to be serialized, but it's worth it in the long run. Unfortunately, this approach does not allow for easy editing of the configuration outside the program.
If you ever intend to run the application in a container (Docker, etc), then completely different considerations apply. You'll need to use a method of externalizing configuration that is compatible with the container platform -- simply reading and writing files is often inappropriate in such an environment.
If you're unsure how you want to handle configuration, do it in a class that implements an interface you define. Then, if you later change your mind, you can supply a different class that implements the same interface.
Problem
We use java WAR files and keep config files in s3 buckets. Our environments: DEV,QA, Stage, and PROD each have their own config files and s3 buckets. If I add a new field, such as "Polling_RATE=5000", it must be manually added to each env because these config files also store passwords so they can not be tied to the application or kept inside Github. Not every engineer has access to each env so you must remember to inform the upper level engineers (DEVOPS) before the prod deployment date to add the new field for the application to work. Its a really messy process currently.
Question
Is there a utility or architectural design pattern meant to deal with this? How do you "version control" sensitive configuration fields that you can not store within github?
Recognizable problem.
Usually config fields with sensitive information like passwords change a lot less often than non-sensitive configuration fields. A possible solution is to split the config in two parts:
Config that's environment-specific but doesn't contain sensitive information. I would advise you to keep these files together with your source code and if possible, generate the files and automatically upload then to your configuration store (S3 in your case) at build time. They must be versioned and tied to the version of your application.
Config that contains sensitive information. Looking at the question, not all team members are allowed to read/write this information. You could store these in S3 with specific access rights so that only authorized members can access them. You would need a mechanism to join the files back together at deployment, or change the app to read from different config files.
However, this will only solve part of your problem. The ops guys will still need to perform changes when sensitive config keys change. Whether this is acceptable depends on how often sensitive config keys change.
An alternative to S3 could be to run a private Git repository (AWS's CodecCommit, for example). You'd have better version control and easier access for the devs to perform changes, since you're already using Git. You'll still have to fix the split access rights between dev and ops, or let that go (since DevOps is about trust and cooperation, that might be a good idea). You could apply a similar pattern here as I described above.
Another solution could be to move the configuration of sensitive values from property files to the system configuration. When you already use a provisioning system like Puppet or Chef, this will feel natural for the ops guys. Or set all sensitive values like passwords as environment variables and have the app read it as system properties.
Hope this helps!
We have been using dynamodb for keeping config values. The advantage with this approach is that the values are easily readable from console and validated.
Also another advantage is that we periodically check the values from dynamodb so if any value needs to be changed we just change it and the app automatically picks the new value instead of starting it again.
Sensitive values are stored encrypted using KMS keys and only the ec2 role that is running the application has right to decrypt using that Key.
We enhanced the Netflix archiaus project to fit our needs. May be you can check that out.
I am trying to implement a simple database configuration editor (to change host, port, user, etc.), but after saving the /WEB-INF/classes/server.properties file, changes do not seem to be recognized (the old configuration is still there when I access the built-in database configuration page). How can I tell SmartGWT to reload the database configuration?
Usually Application reads properties at sturtup and sets theese properties to java objects. So if you are changing properties during your application lifetime you need to take care about rereading them after your change and recreating (refreshing) objects that use them.
For more specific example please provide some code.
You can use the Config class to do this. Simply call the following static method to reload the global config.
Config.initGlobalConfig();
See http://www.smartclient.com/smartgwtee-latest/server/javadoc/com/isomorphic/base/Config.html for more information.
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.
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.