Konfiguration einer ladbaren Anwendung

Archiv

Das allerwichtigste zuerst: damit eine Jar-Datei überhaupt als ladbare Anwendung akzeptiert wird, müssen folgende Punkte erfüllt sein:

  • Die Datei MANIFEST.MF muss als Implementation-Type "Application" eingetragen haben

  • Die Datei MANIFEST.MF muss einen Eintrag Application-Context haben, der zu einer XML-Datei zeigt. Hierbei gilt für den Pfad die Unix-Notierung, d.h. der Verzeichnis-Trenner ist "/".

  • Die Abhängigkeiten der Anwendung müssen im Class-Path der Datei MANIFEST.MF eingetragen sein.
    Dabei gilt folgende Laufzeit-Umgebung:
    unterhalb des Verzeichnisses, in dem die SRStarter.jar Datei liegt, gibt es ein Verzeichnis lib in dem die notwendigen Bibliotheken installiert sind. Ferner gibt es ein Verzeichnis ext in dem Erweiterungen (u.a. die ladbaren Anwendungen) liegen.

    Pfade im Class-Path müssen relativ angegeben werden, d.h. wenn z.B. die Bibliothek glazedlists_java15.jar verwendet wird, lautet ihr Eintrag im Class-Path der Datei MANIFEST.MF lib/glazedlists_java15.jar

Kontext

Die Grundeinstellungen der Anwendung werden in einem sogenannten Kontext abgelegt. Das ist ein IOC-Container nach springframework und wird wie folgt notiert:

<?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>

Die Details obiger Konstruktion sind weniger interessant - wichtig ist nur, dies als Rahmen der Konfigurationsdatei anzusehen

Die wichtigen Punkte der Kontext-Definition folgen jetzt. Das ist als erstes die Definition des PreferencesConfigurers. Diese Klasse sorgt dafür, dass Werte aus der XML-Datei mit den entsprechenden Werten aus der Benutzerkonfiguration überschrieben werden kann.

<bean id="placeHolderConfigurer" class="de.schwarzrot.data.access.pref.PreferencesConfigurer">
   <property name="locations" value="de/schwarzrot/sample/app/sample.properties" />
   <property name="searchSystemEnvironment" value="true" />
   <property name="systemPropertiesMode" value="1" />
   <property name="applicationName" value="Beispiel" />
   <property name="schemaName" value="sr" />
</bean>

Die Erklärung der einzelnen Parameter:

locations
Der Pfad zu einer Properties-Datei mit den Standardwerten für den Fall, dass es (noch) keine Benutzerdaten gibt.
searchSystemEnvironment
bei "true" wird nach gespeicherten Benutzerdaten gesucht, bei "false" nicht.
systemPropertiesMode
dies bedeutet, dass Parameter auch via Befehlszeile geändert werden können.
applicationName
das ist die oberste Ebene der Java-Preferences. Unter Linux entspricht das einem Verzeichnis
schemaName
der Schema-Bezeichner für Konfigurationsentitäten. Unter Linux ist das auch ein Verzeichnis

Anmerkung: Java-Preferences werden unter SRJRCFrames transparent gehandhabt, ebenso wie die Unterscheidung zwischen System- und Benutzer-Werten. Von daher sind die Preference-Pfade im Kontext nicht von Belang.

Die PreferencesConfigurer-Instanz dient der Verwaltung von Konfigurationsdaten, d.h. die eigentliche Konfiguration kommt erst jetzt:

Sprach- und Bildverwaltung

Um Anwendungen möglichst einfach übersetzen zu können, müssen die Texte unabhängig von den Quelltexten gespeichert werden. Das geschieht in sogenannten Resourcedateien, was nichts anderes bedeutet, als eine Datei, die in ein Java-Archiv gepackt wird, die aber kein übersetzter Javaquelltext ist. Eine Resource kann eine Textdatei (wie z.B. auch die Kontextdefinition), ein Bild oder irgendwas anderes sein.

In SRJRCFrames gibt es 2 Hauptklassen von Resourcedateien: einmal die Bilddefinitionen und zum anderen die Anwendungstexte. Letztere werden in der Anwendung über MessageSource-Dienste angesprochen.

Bei den Textdateien ist es so, dass die Datei "messages.properties" die Standard-Spracheinstellungen enthält. Alle weiteren Sprachdateien erhalten ein Sprachkürzel an den Dateinamen angehängt. Deutsche Texte werden demnach in einer Datei "messages_de.properties" abgelegt.

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
   <property name="basenames">
      <list>
         <value>de.schwarzrot.recmgr.app.ui.messages</value>
         <value>de.schwarzrot.recmgr.app.ui.images</value>
      </list>
   </property>
</bean>

Environment

Konfigurationsdaten werden als Preferences gespeichert - schließlich kann nicht aus der Datenbank gelesen werden, wie die Datenbank angesprochen werden soll. Lokale Benutzereinstellungen sind also unabdingbar. Weil die Unterscheidung aus Anwendungssicht aber nicht von Belang ist, werden Konfigurationsentitäten genauso behandelt, wie andere Entitäten auch. Bei Konfigurationsdaten gilt es noch zwischen Systemeinstellungen und Benutzereinstellungen zu unterscheiden. Systemeinstellungen sind für einen normalen Benutzer nicht veränderbar.

SRJRCFrames verwendet unterschiedliche Pfade für System- und Benutzereinstellungen. Systemeinstellungen werden mit dem Pfad der Klasse SystemDefault abgespeichert. Diese Klasse ist nicht instanziierbar.
Die Pfade der Benutzereinstellungen fangen mit dem applicationName an, gefolgt vom schemaName. Erst dann folgt der Pfad der Konfigurationsklasse.

Konfigurations-Entität

Konfigurations-Entitäten sind Nachfahren der Klasse AbstractConfigBase und der Entitätsmanager, der für die Preferences zuständig ist, ist auf AbstractConfigBase angemeldet.

Gegenüber den "normalen" Entitäten gilt es bei den Konfigurations-Entitäten noch folgendes zu beachten:

Eine Konfigurationsentität ist immer eine Systemklasse, deshalb liefert public final boolean isUserType() von AbstractConfigBase immer false. Um jetzt Attribute als Benutzerdatum zu kennzeichnen, gibt es die Methode getUserAttributes. Das folgende Beispiel stammt aus der Klasse ApplicationConfig und legt fest, dass Position und Größe des Anwendungsfensters als Benutzerwert gespeichert werden darf:

@Override
public List getUserAttributes() {
   List rv = new ArrayList();

   rv.add("startupWidth");
   rv.add("startupHeight");
   rv.add("startupX");
   rv.add("startupY");

   return rv;
}

Alle Datenzugriffe auf Konfigurationsdaten erfolgen identisch wie alle anderen Entitätszugriffe. Um z.B. die Konfiguration aus dem Anwendungsbeispiel zu speichern, genügen diese Zeilen (die Speicherung erfolgt automatisch bei Beenden einer Anwendung):

if (taFactory == null)
    taFactory = ApplicationServiceProvider.getService(TransactionFactory.class);

Transaction ta = taFactory.createTransaction();

ta.add(new TOSave(getAppConfig()));
ta.execute();