Das SR-Richclient-Framework Ziel war es, für Richclient-Anwendungen einen ähnlichen Rahmen zu erstellen, den ein Anwendungsserver für Webanwendungen bereit stellt. Ferner wollte ich eine Persistenzschicht haben, bei der der Anwendungsentwickler kein SQL mehr codieren muss (wo und wie auch immer). Da die persistenten Objecte irgendwie auch vom Anwender bearbeitet/verändert werden sollen, entschied ich mich, alle als Model im Sinne von jgoodies zu implementieren, d.h. jede Setterfunktion erzeugt PropertyChangeEvent s. Ein Wunsch bei der Umsetzung war, möglichst wenig Zwänge zu etablieren und die Funktionalität eher anzubieten. Herausgekommen ist ein schlankes Framework zur Erstellung von Anwendungen mit grafischer Benutzeroberfläche. Anwendungen können zur Laufzeit aus JAR-Dateien geladen werden. Ebenso kann die Funktionalität des Anwendungsrahmens über ladbare Archive erweitert werden, bzw. neue Services können hinzugefügt werden. Der Grad der Dokumentation entspricht dem Alphastadium der Anwendung. Dafür bitte ich um Nachsicht. Sowie es meine Zeit zuläßt werde ich Dokumentation und Code verbessern. Als Grundlage für das Framework (und natürlich die Anwendung) habe ich mich für folgende Bibliotheken entschieden: - springframework - es wird zwar nur ein (kleiner) Teil verwendet, es kann jedoch nicht schaden, sich diese Bibliothek einmal anzuschauen. Verwendet wird insbesondere der
ApplicationContext und dessen Hilfsklassen um ihn flexibler zu konfigurieren. - jgoodies eine Swingbibliothek die mich vom Fleck weg begeistert hat
- glazedlists was jgoodies für die Oberfläche ist, ist glazedlists für Listen. Unschlagbar!
- JDBC - zuerst hatte ich auch hier springframework eingesetzt, mich dann aber doch entschieden, eine eigene Datenabstraktion zu entwickeln. Diese basiert auf JDBC direkt. Im Moment wird nur mysql unterstützt (Unterstützung für andere Datenbanken ist angedacht und vorbereitet, aber nicht getestet). postgresql ist implementiert, leider funktioniert keine der Versprechungen, sodass ich nur sagen kann, mit der stabilen Version geht es nicht. Derby halte ich persönlich schlichtweg für eine Beleidigung und für weitere Datenbanken fehlte mir bislang die Zeit.
| Das SR-Richclient-Framework besteht aus: - SRDAlib
- die Datenzugriffsschicht, bzw. das Fundament der Anwendung
Hauptantrieb, eine neue Datenabstraktionsschicht selbst zu entwickeln war der Wunsch, für die Business-Objekte nur eine (Java-)Datei pflegen zu müssen gepaart mit dem Wusch, in der Anwendung kein SQL mehr kodieren zu müssen. Das fing als kleine Technologiestudie an und mittlerweile funktionieren offene und geschlossene virtuelle Entitäten (mehrere Klassen in einer Tabelle), verschiedene Kind-Beziehungen, die Verwendung teilgelesener Entitäten und das Speichern einzelner Attribute oder ganzer Entitätshierarchien. Ebenso funktioniert das transparente Verwenden von unterschiedlichen Datenquellen (auch gleichzeitig), wie auch ein Migrationspfad, bei dem von einer Datenquelle gelesen und in eine andere Datenquelle geschrieben wird. Aus Anwendungssicht sind die Business-Objekte Javabeans, die ein Entity -Interface implementieren. Es kann eine abstrakte Entitätsklasse als Elternklasse verwendet werden. Persistenz-Schnittstelle der Anwendung ist ein Repository , dem man eine Entität zum speichern gibt, oder Argumente zum Lesen von Entitäten, um dann eine Liste von Entitäten zu erhalten. Mögliche Abhängigkeiten werden vom Persistenzlayer autark aufgelöst. Entitäten sind eine Art Singleton, d.h. von einer Entität kann es keine 2 verschiedenen Instanzen mit derselben Id geben. Zumindest nicht innerhalb der Anwendung. Damit es zwischen unterschiedlichen Anwendungen, bzw. JVMs nicht zu Inconsistenzen kommt, haben Entitäten einige Schlüsselfelder. Schließlich sind Transaktionen auch transparent für die Anwendung. Wer sich um Transaktionen kümmern mag, dem steht die Funktionalität zur Verfügung. Ansonsten werden Transaktionen automatisch dann erzeugt, wenn sie benötigt werden. - SRGuiLib
- grafische Basisklassen und Standarddialoge, um ein einheitliches Look&Feel der Anwendung zu erreichen.
Für den Anwendungsrahmen werden 3 verschiedene Varianten der Fensterverwaltung angeboten: MDIDesktop - "multiple document interface", d.h. es wird ein Anwendungsfenster erzeugt und alle Teilanwendungen erzeugen Fenster innerhalb dieses Fensters. MWIDesktop - "multiple window interface", d.h. hier erhält jede Teilanwendung ein eigenes "echtes" Fenster, sodass die Zusammengehörigkeit nur indirekt zu erkennen ist. SWIDesktop - "single window interface", ähnlich wie beim MDIDesktop gibt es nur ein Anwendungsfenster, nur dass diesmal die Teilanwendungen nicht frei verschiebbar sind, sondern alle die gleiche Fläche für die Darstellung nutzen und zwischen den Anwendungen wird umgeschaltet Die Wahl der Fensterverwaltung kann benutzerabhängig geändert werden, d.h. sie ist völlig transparent für die Anwendung. Toolbars, Statusbars und Menübars werden vom Fensterverwalter automatisch angepasst. Alle Benutzeraktionen werden über Action -Klassen abgebildet. Zur Verwaltung implementiert jede Anwendung einen ActionHandler , der im einfachsten Falle nur der Veröffentlichung der Aktionen dient. - SRAppBaselib
- Die Schicht der Anwendungsdienste und Basisklassen für die Anwendungen, oder auch neudeutsch: der ServiceLayer.
Alle Dienste, die das Framework, oder eine der geladenen Module bereitstellt, werden über einen zentralen Mechanismus verwaltet und veröffentlicht. Die Schnittstelle dazu ist die ApplicationServiceProvider -Klasse. Über die Konfigurationsbeschreibung, den "applicationContext" werden die Basisdienste veröffentlicht. Eine Anwendung, die einen Dienst verwenden möchte, ruft getService und erhält den angemeldeten Dienst. Eine Anwendung, die zur Laufzeit einen Dienst bereitstellen will, ruft registerService auf. Auf diese Weise kann auch ein bestehender Dienst ausgetauscht werden. - SRAppFrame
- Die main()-Funktion und eine Beispiel-Anwendung
| Konsequenzen für die Anwendungsentwicklung - Die Beispielanwendung (VdrAssistant) kommt völlig ohne SQL-Code aus. Die Persistenzschicht dürfte über 90% der meisten Datenbankanwendungen abdecken. Werden komplextere Konstrukte benötigt, können diese leicht hinzugefügt werden.
- jede Businessklasse ist eine Implementierung von
Entity , bzw. eine Kindklasse von AbstractEntity . Die Datenabstraktionsschicht arbeitet viel mit Generics und Reflection. Daher hat jede Businessklasse die Regeln für Javabeans zu befolgen. - Das Framework arbeitet viel mit dependency injection oder auch IOC (inversion of control). Das bedeutet, dass Fabrikklassen ihrer Dienste nicht über statische Methoden, sondern über Instanzmethoden anbieten und als Service veröffentlicht werden. Dadurch können Fabrikklassen einfach ausgetauscht werden.
- viele Zusammenhänge sind nur eine gegenseitige Vereinbarung und nicht direkt aus dem (Anwendungs-)Code ablesbar. Hier hilft nur der Blick in die Dokumentation, bzw. für eigene Anpassungen der Blick in den Code.
- Jede Benutzeraktion ist für die Anwendung nur ein
Enum -Wert, der mit einer Anwendungsfunktion verknüpft wird. Dafür ist der ActionHandler zuständig. Die Auflösung des Enum-Wertes in Texte der Sprache des Benutzers wird über Hilfsklassen erreicht. Ebenso die Auflösung des Enum-Wertes in Bilder, etc. - Für viele Aufgaben gibt es fertige Dialoge, bzw. Grundgerüste (abstrakte Klassen) die nur überladen werden müssen. Z.B. gibt es eine Farbauswahl, bei der auch der Transparentwert einer Farbe eingestellt werden kann, oder eine Fontauswahl, bei der der Font anhand eines eigenen Textes überprüft werden kann, ...
| |