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.
package de.javamagazin.mwd;import javax.swing.JFrame;import org.metawidget.inspector.annotation.MetawidgetAnnotationInspector;import org.metawidget.inspector.composite.CompositeInspector;import org.metawidget.inspector.composite.CompositeInspectorConfig;import org.metawidget.inspector.hibernate.validator.HibernateValidatorInspector;import org.metawidget.inspector.propertytype.PropertyTypeInspector;import org.metawidget.swing.SwingMetawidget;public class Beispiel1{public static void main(String[] args){Project project = new Project();SwingMetawidget mw = new SwingMetawidget();CompositeInspectorConfig config = new CompositeInspectorConfig();config.setInspectors(new MetawidgetAnnotationInspector(),new PropertyTypeInspector(),new HibernateValidatorInspector());mw.setInspector(new CompositeInspector(config));mw.setToInspect(project);JFrame frame = new JFrame("Beispiel 1");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.getContentPane().add(mw);frame.setSize(500,200);frame.setVisible(true);}}
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:
XmlInspectorConfig xmlConfig = new XmlInspectorConfig();xmlConfig.setFile("de/javamagazin/mwd/metawidget-metadata.xml");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:
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:
ResourceBundle rb = ResourceBundle.getBundle("de/javamagazin/mwd/messages");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.















