In unterschiedlichsten Programmiersprachen gibt es Standardkonfigurationsdateien für deinen Code. Eine der üblichsten Formate für Konfigurationsdateien sind die .env Files, die geparste werden können, um Environment Variablen in deiner Anwendung zur Verfügung zu stellen. In jeder der gängigen Programmiersprachen gibt es entsprechende Lösungen.
In anderen Sprachen gibt es zusätzliche Dateien wie in Python die TOML Unterstützung, die Files für Konfigurationen z. B. von einem Formatter und Linting. Oder in JavaScript mit der Package.json für NPM Pakete. Zusätzlich dazu gibt es wieder anwendungsspezifische Fälle, die sich in diesen Standard Konfigurationsdateien nicht unbedingt abbilden lassen, da diese nach der offiziellen Konvention nichts an diesen Stellen zu suchen hat. Dafür gibt es je nach Sprache zusätzliche Dateien und Optionen. In Java kann man dieses zum Beispiel über ein Propertiesfile lösen.
Mit der Java Properties Klasse stellt Java ein mächtiges Tool für eigene Konfigurationen bereit, zum einen kann es zur Laufzeit im Memory verwendet werden, zum anderen kann es von einer Initialen-Datei befüllt oder auch dort hineingeschrieben werden. Ein Vorteil von Java Properties ist, dass diese in der Standard-Bibliothek vorhanden ist und keine extra Installation benötigt.
Beginnen wollen wir nur mit der grundlegenden Syntax, so wie bei allen anderen Paketen für Java muss auch dieses erst einmal importiert werden. Die Properties sind ein Teil vom Utils Paket in Java und somit ohne zusätzliche Installationen vorhanden.
import java.util.Properties;
public class Testing {
public static void main(String[] args) {
Properties properties = new Properties();
...
Das Paket enthält einige Optionen, um auf Werte zuzugreifen, diese zu Schreiben, zu manipulieren und zu prüfen, diese wollen wir nun betrachten.
In dem folgenden Beispiel siehst du einmal, wie wir zwei Werte befüllen, die in unsere Anwendung von großer Relevanz sind, z. B. der Server Zugriff für eine externe API könnte so definiert werden.
properties.put("server_ip_v4", "192.000.000.001");
properties.put("server_port", "8080");
Es können verschiedenste Typen verwendet werden, zum Beispiel: String, Integer, Double und Booleans. Anzumerken ist, dass die Rückgabe, wenn ein Wert ausgelesen wird, wieder geparste werden muss, um sie in ihren ursprünglichen Datentypen zu verwenden. Intern werden die Werte immer als String gespeichert.
Um nun auf Werte zuzugreifen, haben wir die getProperty Methode, mit dieser erhalten wir den entsprechenden Wert zurück und können ihn zum Beispiel mit Integer.parseInt(value)
wieder in einen Integer Typen umwandeln (error handling nicht vergessen!)
System.out.println(properties.getProperty("server_active")); // ausgabe: null
System.out.println(properties.getProperty("server_active", "ok")); // ausgabe: ok
Falls wir den Wert definitiv benötigen und uns nicht darauf verlassen können, dass der Wert gesetzt wurde oder wir wollen einen bestimmten Standard definieren, können wir als Zweites ein Standardwert übergeben.
Manchmal wollen wir explizit prüfen, ob ein Key bereits verwendet wurde, natürlich können wir die getProperty Methode mit null abgleichen.
Alternative gibt es dafür bereits eine Methode für diesen Zweck, und zwar containsKey
diese gibt entsprechend ein Boolean zurück, ob vorhanden oder nicht.
if (properties.containsKey("server_active")){
System.out.println("key ist vorhanden!");
}
Zusätzlich kann man sich auch alle Key, Values ausgeben lassen oder auch verändert wieder speichern. Dafür gibt es, etwa die forEach Methode diese kann einfach über alle Keys Iterieren und dieses Ausgeben.
properties.setProperty("server_ip", "192.168.0.1");
properties.setProperty("server_port", "8080");
properties.setProperty("server_active", "true");
properties.forEach((key, value) -> {
System.out.println("Key: " + key + ", Value: " + value);
});
Standardmäßig gibt es zwei Strukturen, wie die Daten geschrieben und gelesen werden können. Einmal das XML Format und einmal das Properties Format, das wie .env Files auch ein Key Value pair Format ist. Mit dem Unterschied, dass .env
Files eher für Daten sind, die im gesamten Environment relevant sind. In der Praxis besteht kein Unterschied.
Um nun die Datei zu Schreiben öffnen wir uns einen File Output Stream, definieren unseren Dateinamen, können bei der Methode store
noch ein Kommentar für die zu erstellende Datei definieren, unsere Daten werden abgespeichert.
try (OutputStream output = new FileOutputStream("config.properties")) {
properties.store(output, "konfiguration");
System.out.println("erfolgreich");
} catch (IOException e) {
System.err.println("fehlgeschlagen: " + e.getMessage());
}
Beispielausgabe aus unseren Eingaben, aus dem vorherigen Beispiel in einer Properties Datei.
#konfiguration
#Thu Jun 29 20:04:07 CEST 2023
server_active=true
server_ip=192.168.0.1
server_port=8080
Falls du eher ein Freund davon bist deine Daten als XML zu speichern, hast du die Methode storeToXML
zur Verfügung. Bis auf die Methode für das Schreiben von store
zu storeToXML
ändert sich nichts an unserem Quelltext.
try (OutputStream output = new FileOutputStream("config.xml")) {
properties.storeToXML(output, "konfiguration");
System.out.println("erfolgreich");
} catch (IOException e) {
System.err.println("fehlgeschlagen: " + e.getMessage());
}
Unsere Ausgabe von dem XML würde folgendermaßen aussehen.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>konfiguration</comment>
<entry key="server_ip">192.168.0.1</entry>
<entry key="server_port">8080</entry>
<entry key="server_active">true</entry>
</properties>
Natürlich können wir auch XML und Properties Dateien verwenden, um unsere Properties Objekte mit Werten zu füllen. Dieses muss wiederum vorher bereits angelegt worden sein. Um es anschließende befüllen zu lassen. Falls du die XML-Variante bevorzugst, verwende statt der load
Methode die loadFromXML
Methode. Ansonsten verändert sich auch wie bei dem Schreiben von Properties zu XML Dateien nichts.
Properties properties = new Properties();
try (InputStream input = new FileInputStream("config.properties")){
properties.load(input);
}catch(IOException e){
System.err.println("fehlgeschlagen: " + e.getMessage());
}
Durch die vielen Möglichkeiten der Properties, kannst du dynamisch neue Konfiguration hinzuladen und verschieden Werte setzen. Es ist vor allem auch eine einfache Möglichkeit, Konfigurationen zu laden und zu speichern, mit einer hohen Flexibilität.
Hinterlasse mir gerne einen Kommentar zum Artikel und wie er dir weitergeholfen hat beziehungsweise, was dir helfen würde das Thema besser zu verstehen. Oder hast du einen Fehler entdeckt, den ich korrigieren sollte? Schreibe mir auch dazu gerne ein Feedback!
Es sind noch keine Kommentare vorhanden? Sei der/die Erste und verfasse einen Kommentar zum Artikel "Java Properties – Einstellungen, Speichern und Wiederverwenden"!