Benutzerhandbuch

Einleitung

Es gibt verschiedene Sichten auf das Framework. Unter Einstieg wird das Framework aus Sicht eines Anwenders beschrieben, indem dargestellt wird, wie eine ladbare Anwendung erstellt werden kann, die dann mit dem Starter des Frameworks ausgeführt werden kann.

Hier soll es mehr um die Internas gehen. Was mache ich, wenn mir der Starter nicht gefällt und ich den anpassen will, oder wie erstelle ich einen eigenen Systemdienst ...

Wer mehr über die Umsetzung erfahren möchte, oder eine Beispiel-Anwendung sucht, sei auf VdrAssistant verwiesen. Das war der erste Anwendungsfall, den ich mit SR-JRC umsetzte und inzwischen gibt es etliche ladbare Anwendungen und div. Hintergrunddienste, die Teile ihrer Abläufe aus dynamisch geladenen JARs zusammen setzen.

Alle Systemdienste können aus der Desktop-Anwendung heraus überwacht, gestartet und beendet werden.

Einrichtung

Der Starter kann in großen Teilen konfiguriert werden, d.h. es ist eine Anpassung ohne größeren Aufwand möglich. Doch bevor es zum Kapitel "Konfiguration" geht, möchte ich beschreiben, wie die Konfiguration funktioniert.

Basis der Konfiguration ist eine XML-Datei, der sogenannte ApplicationContext. Dieser Kontext stammt von springframework und sieht so aus:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://www.springframework.org/schema/beans
              http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 ...
<beans>
Konfiguration per XML zu beschreiben ist an sich nichts Besonderes. Das können viele andere DI-implementierungen auch. So richtig unschlagbar wird die Konfiguration erst durch den Einsatz der Platzhalter-Verwaltung.

Platzhalter-Verwaltung

Ein Platzhalter ist nichts anderes, als eine Variable im XML-Kontext. Variabel in dem Sinne, dass der Inhalt des Platzhalters erst nach dem Einlesen der XML-Datei bestimmt wird.

Auch diese Idee stammt aus dem springframework, wobei ich die Umsetzung etwas verfeinert habe. Ein Platzhalter sieht im ApplicationContext wie folgt aus:

<bean id="dsConfig" class="de.schwarzrot.app.config.DSConfig">
    <property name="defaultAutoCommit" value="false" />
    <property name="dsUser" value="${de/schwarzrot/app/config/SystemDefault/dsUser}" />
    <property name="dsPassword" value="${de/schwarzrot/app/config/SystemDefault/dsPassword}" />
</bean>
Das bedeutet, ein Platzhalter sieht wie eine Bash-Variable aus: ${...}. Im Bereich des ApplicationContext wird der Name des Platzhalters als ein Java Resource-Pfad interpretiert, der auf unterschiedliche Weisen aufgelöst werden kann.

Dazu muss dem ApplicationContext als erstes mitgeteilt werden, wer denn mit der Auflösung der Platzhalter betraut werden soll:

<bean id="placeHolderConfigurer" class="de.schwarzrot.data.access.pref.PreferencesConfigurer">
    <property name="locations" value="de/schwarzrot/app/base/vdrassistant.properties" />
    <property name="searchSystemEnvironment" value="true" />
    <property name="systemPropertiesMode" value="2" />
    <property name="applicationName" value="VDRAssistant" />
    <property name="schemaName" value="va" />
</bean>

Auflösung per Anwendungs-Properties

Dem Platzhalter-Verwalter wird der Pfad einer Properties-Datei übergeben. Dies ist die erste Stufe der Auflösung. Manche Properties-Dateien liegen sogar im Framework und geben allgemeine Anwendungsdefaults, die z.B. den Datenbanktyp vor.

Eine DataSource benötigt unter anderem einen Benutzernamen und ein Kennwort. Dies kann das Framework natürlich nicht wissen, deshalb ist diese Vorgabe schlicht als falsch zu betrachten.

Für eine lauffähige Anwendung muss ein solcher Platzhalter also überschrieben werden können.

Auflösung per Preferences

Java-Preferences sind eine feine Sache, um lokale Einstellungen abzulegen, die nicht in einer Datenbank gespeichert werden sollen oder können.

Bei den Preferences wird unterschieden zwischen System- und Benutzer-Preferences. Erstere sollten für eine Anwendung immer als schreibgeschützt betrachtet werden. Um eine System-Preferences zu ändern, muss die Anwendung in der Regel mit Superuser-Berechtigung laufen (z.B. ein Installer).

Damit eine SR-JRC-Anwendung sich nicht ständig mit der Dualität der Preferences herumschlagen muss, werden alle Zugriffe auf Preferences in SR-JRC derart behandelt, dass bei Preferences die Benutzer-Preferences gelesen werden und wenn der geforderte Schlüssel dort nicht existiert, wird der Schlüssel aus den System-Preferences gelesen.

Auflösung per System-Properties

Bei manchen Platzhaltern ist es nützlich und wünschenswert, dass der gespeicherte Wert kurzfristig und ohne viel Aufwand geändert werden kann. Dazu dienen die System-Properties.

System-Properties sind Parameter, die der JVM beim Start der Anwendung mitgegeben werden.

Damit jetzt nicht jeder Wert beim Start der Anwendung überschrieben werden kann, kann der Modus der System-Properties bei der Definition des Platzhalter-Verwalters im ApplicationContext angegeben werden:

  • 0 == Nie - bedeutet, dass System-Properties nicht beachtet werden
  • 1 == Vorgabe - bedeutet, nur wenn ein Wert nicht anderweitig ermittelt werden kann, wird versucht, ihn über die System-Properties aufzulösen.
  • 2 == Überschreiben - egal, ob der Wert anderweitig aufgelöst werden könnte, oder nicht, sobald er bei den System-Properties angegeben wird, wird der Wert verwendet.