Reputation:
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.
Upvotes: 6
Views: 12031
Reputation: 337
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();
}
Upvotes: 5
Reputation: 4307
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.
Upvotes: 1