Nutzungsvorgaben Konfiguration

IFS-Logo Diese Seite ist ein Teil der IsyFact-Standards. Alle Inhalte der Seite, insbesondere Texte und Grafiken, sind urheberrechtlich geschützt. Alle urheberrechtlichen Nutzungs- und Verwertungsrechte liegen beim Bundesverwaltungsamt.

Creative Commons Namensnennung Die Nutzung ist unter den Lizenzbedingungen der Creative Commons Namensnennung 4.0 International gestattet.

Java Bibliothek / IT-System

Name Art Version

isy-konfiguration

Bibliothek

v3.3.x

Deprecation

Dieser Baustein ist veraltet und wird in einem zukünftigen Release entfernt. Die Inhalte dieser Seite sollten zur Entwicklung neuer Anwendungen nicht mehr berücksichtigt werden.

Einleitung

Dieses Dokument enthält die Nutzungsvorgaben zur Konfiguration von Anwendungen gemäß den IsyFact Standards.

1. Aufbau und Zweck des Dokuments

In diesem Dokument werden konkrete Nutzungs- und Implementierungsvorgaben beschrieben.

Die Vereinheitlichung der Konfiguration erleichtert nicht nur die Entwicklung der Anwendungen, sondern stellt vor allem eine Erleichterung des Betriebs der Anwendungen da.

Alle Vorgaben orientieren sich an den in den jeweiligen Kapiteln aufgeführten Anforderungen und gelten für alle Anwendungen nach IsyFact-Architektur.

2. Vorgaben für Konfigurationen

In diesem Kapitel wird die Nutzung von Konfigurationen für Anwendungen der IsyFact-Architektur beschrieben. Für das zugrundeliegende Konzept siehe Konfiguration - Konzept. Dazu gehören Vorgaben für die Ablage von Konfigurationsdateien und Implementierungshinweise zum Lesen der Konfigurationen. Außerdem werden Besonderheiten für die Konfiguration der eingesetzten Bibliotheken und Frameworks beschrieben.

Der Speicherort der Ordner Resources und Config wird in Kapitel Datei-basierte Konfigurationen beschrieben.

2.1. Vorgaben für die Ablage und Verwendung von Konfigurationen

Dieses Kapitel enthält die Vorgaben wo Konfigurationen abgelegt und wie diese verwendet werden.

2.1.1. Datei-basierte Konfigurationen

Die datei-basierte Konfiguration orientiert sich an den Vorgaben von Spring Boot. Konfigurationsparameter, die nicht durch die Anwendung geschrieben werden, sollen in Dateien und nicht in der Datenbank gespeichert werden. Als Format kommen bevorzugt Property-Dateien zum Einsatz.

Alle datei-basierten Konfigurationen werden im Klassenpfad abgelegt. Dazu werden die Ordner config und resources verwendet. Alle Konfigurationen werden in der Entwicklung unterhalb von src/main/resources abgelegt.

Dort werden Unterordner wie folgt angelegt:

  • Resources-Ordner: In src/main/resources/resources/ liegen die statischen Konfigurationen. Zur Strukturierung sollen hier Unterordner für gleichartige Konfigurationen angelegt werden (z.B. nachrichten, sicherheit).

  • Config-Ordner: In src/main/resources/config/ liegen alle betrieblichen Konfigurationen. Hier wird auch die Konfigurationsdatei application.properties abgelegt.

2.1.1.1. Namenskonventionen für Konfigurationsparameter

Für die Benennung von Konfigurationsparametern werden Zeichenketten ohne Sonderzeichen verwendet. Parameternamen bestehen aus mehreren Teilen, welche durch Punkte getrennt werden. Die Teile werden mit dem am wenigstens spezifischen Begriff beginnend sortiert aufgeschrieben:

datenbank.kennwort datenbank.benutzername

So entsteht eine Hierarchie von Parameternamen (alle mit datenbank beginnenden Parameter beziehen sich auf die Datenbankkonfiguration).

Komponentenspezifische Parameter beginnen mit dem Namen der Komponente, die sie konfigurieren.

verwaltung.regelwerk.regelpfad=…

Im Übrigen sind möglichst aussagekräftige Bezeichner zu verwenden. Die Sprache sollte deutsch sein, sofern es sich nicht um feststehende englische Begriffe handelt (z.B. „Session“).

2.1.1.2. Dokumentationskonventionen für Konfigurationsparameter

In Kapitel Handhabung von Default-Werten wird beschrieben, wie Default-Werte zu handhaben sind. Damit wird gleichzeitig eine sinnvolle Dokumentation von Default-Werten sichergestellt. Davon abgesehen kann es hilfreich sein zu wissen, ob ein Konfigurationsparameter zur Laufzeit änderbar ist (siehe Kapitel Konfigurationsänderungen zur Laufzeit), oder für die Änderung ein Neustart der Anwendung nötig ist. Außerdem ist die Angabe eines gültigen Wertebereichs bei vielen Konfigurationsparametern sinnvoll.

Die fachliche Beschreibung, die in Form eines Kommentars für jeden Konfigurationsparameter angegeben sein sollte, soll um folgende Angaben ergänzt werden (variable Werte sind in <> dargestellt):

  • Änderung erfordert Neustart: Ja/Nein

  • Wertebereich:

    • bei Wahrheitswerten: true/false

    • bei numerischen Werten: <min. Wert> - <max. Wert>

Der Wertebereich ist bei vielen, jedoch nicht bei allen Konfigurationsparametern sinnvoll. Werden z.B. Anzeigetexte oder Links konfiguriert, so kann die Angabe des Wertebereichs entfallen. Die Angabe, ob ein Neustart bei Änderung erforderlich ist, sollte jedoch immer erfolgen.

2.1.1.3. Typsichere Bereitstellung von Konfiguration

Zur Bereitstellung von Konfigurationsparametern in der Anwendung wird der von Spring Boot bereitgestellte Mechanismus verwendet. Hierzu werden für Konfigurationsparameter logisch zusammenhängende Klassen erstellt, die die Konfigurationswerte aufnehmen und mit @ConfigurationProperties annotiert werden.

Beim Start der Anwendung befüllt Spring automatisch die Werte der Objekte mit den entsprechenden Properties aus application.properties. Die Konfigurationswerte werden dabei in Java Standard-Typen (String, int, boolean, usw.) konvertiert. Für Zeitdauern, Zeitperioden und Dateigrößen wird eine erweiterte Syntax für die Konfigurationswerte verwendet. Die Werte dieser Konfigurationstypen werden automatisch in die komplexen Datentypen Duration, Period und DataSize umgewandelt.

Details hierzu können in der Spring Boot Dokumentation zu "Properties Conversion" nachgelesen werden.

Zur Überprüfung der Konfigurationswerte sollte Bean Validation eingesetzt werden. Damit können Werte auf Vorhandensein und korrektes Format geprüft werden.

Zur Verwendung in der Anwendung wird die Konfigurationsklasse als Bean instanziiert und dann in der Anwendung per Dependency Injection gesetzt. Ein Beispiel für eine Konfigurationsklasse ist in Listing 1 zusehen. Die dazugehörige Property lautet dann projekt.meine-anwendung.person.firstName=<Wert> und muss aufgrund von @NotNull gesetzt sein.

Listing 1. Konfigurationsklasse (@ConfigurationProperties)
@Component
@ConfigurationProperties("projekt.meine-anwendung.person")
@Validated
public class PersonProperties {

    @NotNull
    String param;

    public String getParam() {
        return param;
    }

    public void setParam(String param) {
        this.param = param;
    }
}

Spring löst die Namen der Properties der Konfigurationsparameter über Relaxed Binding auf. Die damit möglichen Schreibweisen für einen Parameternamen sind in Tabelle 1 dargestellt.

Tabelle 1. Schreibweisen von Parameternamen
Schreibweise Anmerkung

projekt.meine-anwendung.person.first-name

Kebab case (Trennung mit '-'). Für die Verwendung in Property-Dateien empfohlen.

projekt.meineAnwendung.person.firstName

Standard Camel Case Syntax.

projekt.meine_anwendung.person.first_name

Trennung mit Unterstrichen. Alternative für die Verwendung in Property-Dateien.

PROJEKT_MEINEANWENDUNG_PERSON_FIRSTNAME

Empfohlen für Systemumgebungsvariablen.

Für die Auswahl werden hier nur Empfehlungen gegeben. Die gewählte Schreibweise sollte durchgehend in der Anwendung verwendet werden.

2.1.1.4. Handhabung von Default-Werten

Default-Werte werden in den Konfigurationsklassen (mit @ConfigurationProperties annotierte Klassen) festgehalten.

Für systemabhängige Werte dürfen keine Default-Werte hinterlegt werden. Wichtig ist, dass die Anwendung die Existenz dieser Werte (z.B. URLs zu genutzten Services) bereits bei der Initialisierung durch Validierung prüft (siehe Typsichere Bereitstellung von Konfiguration). Dadurch wird vermieden, dass das Fehlen von Einstellungen erst bei späteren Zugriffen erkannt wird.

Konfigurationsparameter, die nicht zur Laufzeit änderbar sind (siehe Kapitel Konfigurationsänderungen zur Laufzeit), können zur Performance-Optimierung in Instanzvariablen gehalten werden. Dabei kann auch gleich das Vorhandensein der Einstellung geprüft werden, d.h., die Komponente liest bereits bei Ihrer Initialisierung den Parameterwert aus und speichert ihn in einer Instanzvariablen.

2.1.2. Datenbank-basierte Konfigurationen

Konfigurationen, welche durch die Anwendung geschrieben werden, sind in der Datenbank abzulegen. Die Tabellen hierfür sind Teil des Datenmodells der Anwendung. Der Zugriff erfolgt genau wie der auf die übrigen Entitäten. Für weitere Details siehe Umsetzung des Datenzugriffs.

2.2. Verwendung von isy-konfiguration

Die Bibliothek isy-konfiguration ist veraltet, wird nicht mehr weiterentwickelt und wird in einem zukünftigen Release entfernt.
Deprecation

Dieser Teil der Dokumentation ist veraltet und wird in einem zukünftigen Release entfernt. Die Inhalte sollten zur Entwicklung neuer Anwendungen nicht mehr berücksichtigt werden.

Zur Bereitstellung von Konfigurationsparametern in der Anwendung kann die Bibliothek isy-konfiguration verwendet werden.

Die Konfigurationsbibliothek enthält Interfaces und Implementierungen für das Laden von Property-Dateien und das typsichere Auslesen von Konfigurationsparametern. Die Konfiguration wird der Anwendung als querschnittliche Spring-Bean (im Folgenden Konfigurations-Bean genannt) bei der Verwendung von isy-konfiguration automatisch bereitgestellt:

Die Liste der Property-Dateien, die von isy-konfiguration gelesen werden sollen, wird in application.properties angegeben (Listing 2).

Listing 2. Property zur Konfiguration von isy-konfiguration
isy.konfiguration.properties = /config/A.properties, /config/B.properties

Die Klasse […​].konfiguration.common.impl.ReloadablePropertyKonfiguration stellt über das Interface de.bund.bva.isyfact.konfiguration.common.Konfiguration einen typsicheren Zugriff auf die Konfigurationsparameter zur Verfügung.

Alle Parameter aus den in der Liste aufgeführten Property-Dateien werden der Anwendung als eine gemeinsame Sicht aller Konfigurationsparameter zur Verfügung gestellt. Sind Parameter in mehreren Dateien aufgeführt, so überschreiben Werte aus Dateien, die in der Liste hinten stehen, solche von Dateien, die zuvor aufgelistet wurden.

Die Konfigurations-Bean wird den Komponenten per Spring-Dependency-Injection bereitgestellt.

Für den Fall, dass sehr viele Konfigurationsparameter benötigt werden, können komponentenspezifische Konfigurations-Beans verwendet werden.

Der Zugriff auf einzelne Konfigurationsparameter erfolgt dann über Methoden des Konfigurations-Interfaces, siehe Listing 3.

Listing 3. Zugriff auf Konfigurationsparameter
String url = konfiguration.getAsString (KonfigurationSchluessel.SERVICE_URL);

Das Interface bietet für verschiedene Datentypen (String, Integer, Long, Double und Boolean) jeweils typsichere Zugriffsmethoden an. Für jeden Datentyp wird zusätzlich eine Methode angeboten, welche die Übergabe eines Default-Werts ermöglicht. Dieser wird verwendet, falls der Konfigurationsparameter nicht in der Konfigurationsdatei vorhanden ist. Wird die Variante ohne Default-Wert aufgerufen und ein Konfigurationswert nicht vorhanden sein, wird eine Exception geworfen.

2.2.1. Konfigurationsänderungen zur Laufzeit

Betriebliche Konfigurationen werden in Dateien gespeichert und nur beim Starten der Anwendung geladen. Im Normalfall werden Konfigurationsparameter beim Start der Anwendung ausgelesen und in Instanzvariablen gehalten. Die Bibliothek isy-konfiguration bietet die Möglichkeit, Konfigurationsparameter zur Laufzeit neu einzulesen.

Sollen Konfigurationsparameter zur Laufzeit änderbar sein, müssen besondere Vorkehrungen getroffen werden:

  • Konfigurationsänderungen gelten nicht zeitgleich für den gesamten Cluster, es muss daher ausgeschlossen werden, dass kurzzeitige Konfigurationsunterschiede zwischen den einzelnen Knoten zu fachlichen oder technischen Inkonsistenzen führen.

  • Konfigurationsparameter, für die Änderungen zur Laufzeit vorgesehen sind, werden im Betriebshandbuch gesondert ausgewiesen.

  • Solche Konfigurationsparameter werden vorzugsweise nicht in Instanz-Variablen gehalten, sondern bei jeder Verwendung aus der Konfigurations-Bean ausgelesen.

  • Falls aufwändige Initialisierungen bei Konfigurationsänderungen durchgeführt werden müssen, kann die entsprechende Komponente sich als Listener bei der Konfigurations-Bean registrieren und so aktiv über Konfigurationsänderungen informiert werden (siehe Kapitel Reagieren auf Konfigurationsänderungen).

2.2.1.1. Konfigurationsdateien auf Änderungen prüfen

Damit die Anwendung Änderungen an betrieblichen Konfigurationsdateien erfährt, wird ein Polling auf die betrieblichen Konfigurationsdateien durchgeführt. Dazu implementiert die Konfigurations-Klasse ReloadablePropertyKonfiguration das Interface ReloadableKonfiguration.

Die vom Interface deklarierte Methode

public boolean checkAndUpdate();

sorgt beim Aufruf dafür, dass alle Konfigurationsdateien auf Änderungen geprüft und bei Bedarf neu geladen werden. Änderungen werden durch den Änderungszeitstempel der Dateien festgestellt.

Die zuvor genannte Methode muss regelmäßig aufgerufen werden. Dazu stellt die Bibliothek isy-task einen Task bereit. Die Konfiguration dieses Tasks ist in den Nutzungsvorgaben Task Scheduling beschrieben.

2.2.1.2. Reagieren auf Konfigurationsänderungen

Wie zu Beginn des Abschnittes beschrieben, sollen Konfigurationsparameter, für die Änderungen zur Laufzeit zugelassen sind, vorzugsweise bei jeder Verwendung aus der Konfigurations-Bean ausgelesen werden. Somit wird automatisch immer der aktuelle Wert verwendet.

In einigen Fällen sind aufgrund von Konfigurationsänderungen jedoch aufwändige Initialisierungen notwendig. Ein Beispiel hierfür wäre das Reinitialisieren von Connection-Pools, wenn eine URL geändert wurde. In solchen Ausnahmefällen kann daher das im Folgenden beschriebene und von der Konfigurationsbibliothek realisierte Listener-Pattern angewandt werden.

Um bei Änderungen informiert zu werden, registriert sich die betroffene Komponente als Listener bei der Konfigurations-Bean. Dafür bietet das von der Konfigurations-Bean implementierte Interface ReloadableKonfiguration die Methode an:

public class ReloadableKonfiguration {
    // ...
    public void addKonfigurationChangeListener(KonfigurationChangeListener listener);
    // ...
}

Die Komponente muss ihrerseits das Interface KonfigurationChangeListener implementieren und die zuvor genannte Methode aufrufen. Als Parameter wird die eigene Instanz übergeben.

Bei Änderung der Konfiguration ruft die Konfigurationsbibliothek nun automatisch die Methode

public class KonfigurationChangeListener {
    // ...
    public void onKonfigurationChanged(Set<String> changedKeys);
    // ...
}

der registrierten Listener auf. Als Aufruf-Parameter werden die Schlüssel aller geänderten Konfigurationsparameter übergeben.

Zu beachten ist, dass der Methoden-Aufruf im Thread-Kontext des Timers, der die Konfigurationsdateien überwacht, erfolgt.

2.3. Spezielle Konfigurationen

In diesem Kapitel werden einige spezielle Aspekte der Konfiguration von Anwendungen beschrieben.

2.3.1. Web-Kontext-Konfiguration (web.xml)

Die Web-Kontext-Konfiguration web.xml ist eine statische Konfiguration. Hierin dürfen keine betrieblichen Parameter aufgenommen werden. Die Datei kann aus technischen Gründen nicht im Resources-Ordner abgelegt werden. Sie wird daher direkt im Ordner WEB-INF/ abgelegt.

2.3.2. Tomcat-Kontext-Konfiguration (context.xml)

Diese Konfiguration ist nur notwendig, wenn die Anwendung über symbolische Links auf Dateien außerhalb des Verzeichnisses zugreift, in dem sie deployt ist.

Zur Auflösung von symbolischen Links muss der Tomcat, auf dem die Anwendung deployt wird, konfiguriert werden. Dazu wird eine Datei (META-INF/context.xml) mit jeder Webanwendung ausgeliefert. Für eine Beispiel-Anwendung hat die Datei folgenden Inhalt:

<Context>
    <Resources allowLinking="true" />
</Context>

Zur Vereinfachung des Deployments wird die Datei nicht im Tomcat-Installationsverzeichnis abgelegt, sondern als Datei context.xml im Verzeichnis META-INF der Webanwendung abgelegt. Dort wird die Datei automatisch von Tomcat gefunden und verwendet.

2.3.3. Umsetzen des Auskunftsmodus

In jeder Geschäftsanwendung muss ein Auskunftsmodus implementiert werden. In diesem Modus dürfen keine bestandsverändernden Aktionen möglich sein. Rein lesende Operationen sind weiterhin erlaubt.

Der Modus wird genutzt, um während längerer Datenmigrationen Änderungen der Bestandsdaten zu unterbinden, während gleichzeitig Auskünfte möglich sind.

Die Anforderung wird durch Einfügen eines Konfigurationsparameters anwendung.auskunftsmodus.aktiviert in die betriebliche Konfigurationsdatei umgesetzt.

Die Option kann die Ausprägungen false (Alle Funktionen sind aktiv) und true (Schreibzugriffe sind deaktiviert) annehmen.

In den Komponenten, die Schreibzugriffe implementieren, wird vor dem Aufruf der Anwendungsfälle geprüft, ob der Parameter auf true gesetzt ist. Ist dies der Fall, wird eine technische Exception vom Typ KomponenteDeaktiviertException geworfen.

Im Falle eines aktivierten Auskunftsmodus sollten die Benutzer einer grafischen Benutzeroberfläche frühzeitig informiert werden – insbesondere nicht erst durch die technische Exception, nachdem sie alle Daten erfasst und abgeschickt haben. Je nach Aufbau der Dialoge kann hierbei ein Hinweis auf den Masken dargestellt werden, oder ganze Dialoge durch einen Hinweisdialog ersetzt werden.

Bevor eine Anwendung in den Auskunftsmodus versetzt werden kann, sind alle nutzenden Anwendungen ebenfalls in den Auskunftsmodus zu versetzen. Zum Wiederherstellen des vollen Funktionsumfangs wird in umgekehrter Reihenfolge vorgegangen, d.h. schreibende Zugriffe werden zunächst in den genutzten Anwendungen wieder erlaubt und danach die nutzenden Anwendungen umgestellt.