Artikel

 
November 2009 | Artikel

Metawidget: King of the Hill Fortsetzung, Teil 4

Teil 1   Teil 2   Teil 3   Teil 4   

In unserem Beispiel mappen wir nur primitive Datentypen. Es stellt sich daher natürlich die Frage, wie man mit Assoziationen umgeht. In unserem Beispiel könnte ein Projekt genau einen Projektmanager haben. Metawidget würde in diesem Fall innerhalb des eigentlichen Formulars etwas eingerückt einen eigenen Abschnitt als Subformular für die Eingabefelder des Managers erstellen. Wenn dieses Verhalten nicht gewünscht ist, kann es mit der Annotation @UiDontExpand unterdrückt werden. Etwas komplizierter sieht der Fall aus, wenn wir eine 1:n-Relation vorliegen hätten. Als Beispiel könnten hier die Projektmitarbeiter dienen. Hierbei müsste man das vorgesehene Eingabefeld mit einem eigenen Eingabefeld, wie etwa einem JTable, überschreiben.

  1. package de.javamagazin.mwd;
  2. import javax.swing.JFrame;
  3. import org.metawidget.inspector.annotation.MetawidgetAnnotationInspector;
  4. import org.metawidget.inspector.composite.CompositeInspector;
  5. import org.metawidget.inspector.composite.CompositeInspectorConfig;
  6. import org.metawidget.inspector.hibernate.validator.HibernateValidatorInspector;
  7. import org.metawidget.inspector.propertytype.PropertyTypeInspector;
  8. import org.metawidget.swing.SwingMetawidget;
  9. public class Beispiel1
  10. {
  11. public static void main(String[] args)
  12. {
  13. Project project = new Project();
  14. SwingMetawidget mw = new SwingMetawidget();
  15. CompositeInspectorConfig config = new CompositeInspectorConfig();
  16. config.setInspectors(
  17. new MetawidgetAnnotationInspector(),
  18. new PropertyTypeInspector(),
  19. new HibernateValidatorInspector()
  20. );
  21. mw.setInspector(new CompositeInspector(config));
  22. mw.setToInspect(project);
  23. JFrame frame = new JFrame("Beispiel 1");
  24. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  25. frame.getContentPane().add(mw);
  26. frame.setSize(500,200);
  27. frame.setVisible(true);
  28. }
  29. }

Wie gelangt man nun von der Domänenklasse zum Formular? Listing 4 zeigt den gesamten Code, der benötigt wird, um das Formular zu erzeugen. Als Erstes gilt es, die eingesetzte Front End-Technologie zu wählen, in diesem Fall ein Swing Client. Daher wird eine Instanz der Klasse SwingMetawidget erzeugt, bei Android würde an dieser Stelle z.B. die Klasse AndroidMetawidget zum Einsatz kommen. Die nächsten Zeilen gehören der Konfiguration von Metawidget. Dabei muss vor allem bestimmt werden, welche Backend-Technologien eingesetzt werden. Für jede Backend-Technologie gibt es einen eigenen Inspector, der das Auslesen der Informationen übernimmt. Da diese jedoch auf mehrere Technologien verteilt sein können, gibt es die Möglichkeit, über den CompositeInspector mehrere Inspectors zu kombinieren, wie das auch in unserem Beispiel erfolgt. Die Klasse MetawidgetAnnotationInspector übernimmt das Auslesen der Metawidget-Annotationen, PropertyTypeInspector liest die Typen der Properties aus und schließlich ist der HibernateValidatorInspector für die Annotationen des Hibernate Validators zuständig. Die Informationen werden miteinander kombiniert und fließen alle in die Generierung des Formulars ein. Als Alternative zum MetawidgetAnnotationInspector könnte der XmlInspector verwendet werden, der wie weiter oben beschrieben, die Informationen aus der XML-Datei von Listing 3 ausliest:

  1. XmlInspectorConfig xmlConfig = new XmlInspectorConfig();
  2. xmlConfig.setFile("de/javamagazin/mwd/metawidget-metadata.xml");
  3. XmlInspector xmlInspector = new XmlInspector(xmlConfig);

Auch die Konfiguration der Inspectors kann in eine eigene XML-Datei ausgelagert werden. Listing 5 würde daher der in Listing 4 gezeigten Konfiguration entsprechen und die nachfolgende Codezeile zeigt, wie die XML-Datei in Metawidget eingebunden wird:

  1. mw.setInspectorConfig("de/javamagazin/mwd/inspector-config.xml");

Anschließend müssen wir Metawidget noch die Domänenklasse bekanntgeben. Dies erfolgt mit der Methode setToInspect. Außerdem kann mit dem nachfolgenden Code die Internationalisierung aktiviert werden, in dem wir Metawidget ein ResourceBundle übergeben:

  1. ResourceBundle rb = ResourceBundle.getBundle("de/javamagazin/mwd/messages");
  2. mw.setBundle(rb);

Der restliche Code entspricht dem typischen Swing-Code für die Erstellung eines Frames. Wenn wir die Applikation nun kompilieren und starten, sollte das Ergebnis unserer harten Arbeit (auch wenn uns natürlich Metawidget den Großteil davon abgenommen hat) wie in Abbildung 1 aussehen. Noch sieht das Formular jedoch etwas leer aus, denn es fehlen die Daten. Weder werden sie ins Formular hineingeschrieben noch herausgeholt. Man kann zwar über die Methode getValue auf jedes Eingabefeld zugreifen, doch würde dies bedeuten, dass man wieder einiges an Code zu schreiben hat. Daher unterstützt Metawidget mit Beans Binding und BeanUtils zwei Binding-Tools. Mittels mw.setBindingClass(BeansBinding.class); wird Metawidget mitgeteilt, dass Beans Binding verwendet werden soll. Wenn nun innerhalb eines ActionListeners die Methode save aufgerufen wird, werden automatisch alle Daten aus dem Formular in ursprüngliche Objekte geschrieben. Andersherum können jederzeit die Daten mit der Methode rebind aus dem Objekt ausgelesen und ins Formular übertragen werden.

Fazit

Dieser Artikel hat versucht, anhand eines kleinen Beispiels einen ersten Einblick in Metawidget zu vermitteln und Neugierde auf dieses Tool zu wecken. Der Vergleich mit Frameworks, die die komplette CRUD-Funktionalität abdecken, mag auf den ersten Blick wie ein Vergleich zwischen Äpfeln und Birnen erscheinen, da sich Metawidget rein auf die Generierung der Eingabeformulare beschränkt und daher nur einen Teil der Funktionalität anbietet. Dies war aber auch gar nicht das Ziel, da Metawidget nicht mit diesen Technologien konkurrieren will. Stattdessen sollten einfach zwei bestehende Ansätze aufgezeigt werden, um Metawidget besser einordnen und auch beurteilen zu können, wo sich sein Einsatz lohnt. Metawidget ist zweifelsohne ein interessanter und vielversprechender Ansatz für die Generierung von Formularen. Es fügt sich problemlos in bestehende Technologien ein, schränkt den Entwickler dabei jedoch im Vergleich zu anderen Ansätzen bei der Entwicklung nicht ein, sondern lässt ihm so viel Freiheit wie möglich. Gerade auf der Clientseite kann es im Zusammenspiel mit dem Swing Application Framework und Beans Binding die Entwicklung deutlich beschleunigen. Zwar wird laut Website Metawidget in der aktuellen Version 0.85 schon in ersten Applikationen eingesetzt, doch für einen Produktiveinsatz ist es noch etwas zu früh und man sollte zumindest Version 1.0 abwarten.

Wolfgang Gruber arbeitet als Softwareentwickler auf verschiedenen Plattformen und versucht dabei stets dem KISS-Prinzip treu zu bleiben. Derzeit beschäftigt er sich vor allem mit geografischen Informationssystemen und serviceorientierten Architekturen.
  1. http://www.metawidget.org/
  2. http://www.grails.org/
  3. http://www.nakedobjects.org/
  4. http://metawidget.sourceforge.net/doc/faq/comparison.html
  5. http://www.hibernate.org/412.html
  6. https://beansbinding.dev.java.net/
  7. http://commons.apache.org/beanutils/

Teil 1   Teil 2   Teil 3   Teil 4   

Anzeige

Kommentare

Gravatar RPR 25.11.2009
um 20:24 Uhr
Für einfache Prototypen ist so was ja ganz nett; aber:1. Für ausgefeilte Endkunden-GUIs die komplexe Business-Logik darstellen sollen ist so was nicht geeignet.2. Schon die GUI des einfachen Beispiels sieht - pardon - besch... aus; die Labels gehören z.B. rechtsbündig.3. Der Code des Beispiels wäre mit Swing allein auch nicht länger gewesen; höchstens die Validierung (die auch nur in einfachsten Fällen so geht - wie siehs z.B. mit dynamischen Lookups aus?) bringt ein paar Zeilen Code; verstopft aber die Übersichtlichkeit; pro Property 10 Annotations? Nein danke.4. Durch die ganzen Interzeptoren XML-Einlesearbeit etc. wird das Programm sicher nicht schneller (starten).Woher kommen wohl seit 10 Jahren die "Gerüchte" dass Java-GUIs hässlich und langsam sind? Nicht zuletzt von solchen "Vereinfachungen".Nein Leute lasst euch sagen: Wenn ein Programm erfolgreich werden soll dann braucht es eine ausgefeilte Benutzerführung dass die Leute sagen: Geil das macht das genau so wie ich mir das vorstelle. Ansonsten werden die Benutzer das Programm von Anfang an hassen. Ergo: Für die nächste Franken-GUI durchaus eine Überlegung wert ;-) #zitieren
Gravatar RPR 25.11.2009
um 20:26 Uhr
Jetzt geht der vermaledeite Zeilenumbruch hier schon wieder nicht welche Stümper programmieren das hier eigentlich? #zitieren
Gravatar Wolfgang Gruber 26.11.2009
um 15:37 Uhr
ad 1. nein, dazu ist es auch gar nicht gedacht. Es soll die Entwicklung von Standard-Formularen vereinfachen, die meist einen großen Teil von Applikationen einnehmen. Komplexe GUIs erfordern natürlich weiterhin "Handarbeit".
ad 2. Stimmt, es ist aber nur ein kurzes Beispiel. Auf http://metawidget.sourceforge.net/screenshots.html gibt es einige schönere GUIs.
ad 3. Bei kurzen Beispielen machen sich die Einsparungen an Source Code natürlich nicht bemerkbar. Zum Vergleich: Wenn man den Code für ein einfaches JDBC-Select-Statement mit dem Code vergleicht, den JPA für die gleiche Funktionalität benötigt, dann schneidet JPA auch nicht gerade gut ab. Es geht aber auch darum repetativen Code zu eliminieren, so dass man sich als Entwickler mehr auf den Kern konzentrieren kann. Im Fall von Metawidget eben die Anordnung der Widgets, sowie deren Aussehen. Ob man alle Metadaten als Annotationen direkt in der Entität angibt oder in XML-Dateien auslagert (wie das auch von Metawidget angeboten wird), bleibt jedem Entwickler selbst überlassen. Momentan ist es eben einfach der Trend alles in Annotationen zu packen. Ob das der ideale Weg ist, ist natürlich eine andere Frage :-)
ad 4. das Problem ist, dass solche Gerüchte einmal aufkommen und dann nicht mehr hinterfragt werden. Inzwischen sind 10 Jahre vergangen, in denen sich sowohl Java, als auch die darunterliegende Hardware weiterentwickelt haben. Ansonsten kommen langsame Java-GUIs sehr oft von suboptimaler Programmierung, z.B. dass zu viel Arbeit im Event Dispatch Thread erfolgt, die GUI dadurch "einfriert" und nicht mehr auf den Benutzer reagiert.
Metawidget bildet einen Wrapper um vorhandene Technologien und ist mit knapp 300 KB nicht besonders groß. Von daher ist die Performance-Einbuße beim Start zwar sicherlich vorhanden, aber nicht wesentlich (die Initialisierung von z.B. JPA nimmt da sicherlich mehr Zeit in Anspruch).
Wie im Artikel beschrieben, handelt es sich nicht um eine All-inclusive-Lösung, sondern einfach um ein Tool, dass die Arbeit mit Formularen erleichtern soll.
#zitieren
Gravatar Jan Lessner 26.11.2009
um 22:48 Uhr
Ich kann nur bestätigen, dass solche Ansätze funktionieren. Wie ich seinerzeit in dem zitierten Artikel über Naked Objects geschrieben hatte, ließt an dem Framework nicht das Konzept sondern nur die konkrete Umsetzung zu wünschen übrig. Inzwischen haben wir bei arvato services ein eigenes Framework nach Naked-Objects-Pattern entwickelt, das tadellos im produktiven Einsatz funktoniert, enorm Zeit spart und trotzdem flexibel und offen ist, so dass selbst die kritischen Entwickler das Ding richtig "cool" finden. Entscheidender Trick dabei: die zur Laufzeit erzeugten Maskenlayouts (basierend auf JGoodies FormLayout) werden - sofern man es nicht explizit unterdrückt - in Dateien abgelegt und lassen sich anschließend mit einem sehr komfortablen GUI-Designtool nachbearbeiten. Dadurch sind auch hohe Ansprüche an die äußerliche Gestaltung erfüllbar und es können eine ganze Reihe von Annotatinen im Sourcecode vermieden werden, die reine Oberflächenthemen betreffen, z.B. Default-Buttons, Tab-Reihenfolge, Ausblenden von Feldern usw. Bei nachträglichen Ergänzungen der Domänenklassen werden Felder für neue Attribute in die bestehenden Layouts vom Framework zur Laufzeit hinein gemerged.
Mit dieser Technik erschlagen wir 80% aller GUIs. Wichtig ist natürlich die Offenheit der Umgebung für die restlichen 20%, wo tiefe Eingriffe notwendig sind. Mit ein bisschen Kenne lässt sich auf Basis der vielen verfügbaren Toolkits in der Java-Welt ein sehr schlankes Naked-Objects-Framework bauen. Wir setzen z.B. auf AjaxSwing, um unsere generisch erzeugten Swing-Oberflächen ins Web zu kriegen.
#zitieren
Gravatar RPR 28.11.2009
um 12:09 Uhr
Hallo Jan,
nun gut, wenn man die GUIs nachbearbeiten kann, ohne den Bezug zum Original zu verlieren (was ein wirklich beeindruckendes Feature ist - die meisten UML-Tools können das nicht mal) und nachträglch reinmergen kann und das gut funktioniert, ist es sicher ne Möglichkeit, sich hier Zeit zu sparen und konsistent zu bleiben. Das Ding ist nicht zufälligerweise open source oder kann man mal wo testen?

Ein Schmunzeln entlockte mir der Satz "Mit dieser Technik erschlagen wir 80% aller GUIs" - so wie viele Java-GUIs aussehen, muss man wirklich von "Erschlagen" sprechen ;-)
#zitieren
Gravatar Jan Lessner 30.11.2009
um 11:40 Uhr
Das stimmt schon - viele GUIs werden von Entwicklern gestaltet, und die haben in der Regel nicht Gestaltung studiert, und das sieht man dann auch ;-)
Ich find's aber OK, das Hauptaugenmerk auf die wirklich wichtigen Dinge zu lenken und an "Nebenkriegsschauplätzen" nicht von vornherein Aufwand für Usability zu spendieren. insbesondere ist es gut, wenn sich da im Nachgang ohne Codeänderung einiges drehen lässt, und das ist genau unsere Intention gewesen. Wir setzen übrigens als GUI-Designtool den JFormDesigner ein, der so komfortabel ist (und insbesondere losgelöst von einer fetten IDE), dass die Fachbereiche es sich nach einer Weile auch selber zutrauen, die Controls an die richtigen Stellen zu schubsen.

Das Toolkit ist leider noch nicht Open Source obwohl es das werden soll. Ich muss unseren Abteilungsleiter noch ein bisschen bearbeiten - das ist mir mit einem anderen Framework in der Vergangenheit auch schon gelungen, deswegen sollte das diesmal auch klappen ;-)
Im Moment schleifen wir noch ein paar Ecken rund. Wenn es Dich sehr interessiert, kann ich checken, ob Du's gegen ein NDA mal haben kannst.
#zitieren

Anzeige

zurück zum Seitenanfang