Craig Walls, Norman Richards. Manning. ISBN 1-932394-05-2. 2004. 600 Seiten
XDoclet selbst stammt von Rickard Öberg, der auch das Vorwort für das Buch geschrieben hat, aber Craig (war selbst XDoclet Committer) und Norman leisten gute Arbeit, XDoclet vollständig zu beschreiben – Öberg hat Korrektur gelesen. Der Ursprung des Buches liegt laut Autoren in der Motivation XDoclet selbst besser zu verstehen, doch die Autoren sind allgemein und gründlich genug, damit Leser unterschiedlicher Bildungsschichten etwas davon haben. (Allerdings hört es in der Tiefe dann irgendwann einmal auf, das hat aber nichts mit XDoclet selbst zu tun, sondern etwa rund um EJB-Assoziationen.) Das erste Kapitel führt die Grundlagen von Codegenerierung ein und wie XDoclet ins Bild passt. Aktiver wird von passiver Codegenerierung unterschieden, unterschiedliche Ursprungsformen werden geschrieben und diskutiert ob und wie XDoclet ins eigene Projekt passt. Kapitel 2 ist technischer und führt Tags und Ant-Tasks ein, um Generierung von Todo-Listen zu zeigen. XDoclet Tasks und Subtasks werden kurz vorgestellt. Es folgt eine Kurzeinführung in Templates für die Codegenerierung, etwas detailliert vielleicht zu Anfang, aber in Ordnung. Im späteren Kapitel kommt das noch sehr genau zur Sprache. Es folgt das Konzept der wichtigen Merge-Points und das Kapitel schließt mit dem Bigger-Picture und der Feststellung, dass Metadaten nur an einer Stelle stehen sollte und Redundanzen minimiert werden müssen. Es folgt der zweite Abschnitt, der sich konkret mit dem EJB-Doclet, und XDoclet fürs Web beschäftigt. Kapitel 3 ist für die klassischen J2EE 1.4 Entwickler das wichtigste Kapitel. Das Beispiel ist mit einem Weblog gut und anschaulich gewählt. Dass die Property im UML-Diagramm allerdings „test“ heißt ist ein Fehler; es sollte „text“ heißen. Alle zentralen Tags werden an Beispielen gezeigt, also wie ein Session-Bean getagt wird, eine Entity-Bean und die Beziehungen der Entiy Bean aufgebaut, und wie eine Fassade und Utility-Klasse generiert werden und was im Prinzip darin steckt (Quellcode wäre gut gewesen hier). Es folgt die Generierung eines Value Objects (VO) was die Autoren hier mit dem Data Transfer Object (DTO) gleichsetzen, aber heutzutage trennt man die Konzepte. Matcher für unterschiedliche VOs kommen zur Sprache genauso wie Aggregationen und Composites, also das auch die assoziierten Objekte einer CMP mit in das VO aufgenommen werden. Die Beschreibung könnte allerdings etwas detaillierter sein und es wäre eine Bereicherung, wenn die Autoren alle Szenarien, also 1:1, 1:n, n:m einem Bi- und einmal Unidirektional durchgespielt hätten. Das Kapitel schließt mit den Sicherheits-Tags, Finder/Selector und einer Übersicht, welche Dateien XDoclet für das Blog-Beispiel generiert, Transaktionsattributen, DAOs für BMP und Message Driven Beans. Gewünscht hätte ich mir noch eine Zusammenfassung mit einer Gegenüberstellung der Tags mit dem Ergebnis im Deployment-Deskriptor bzw. Quellcode. Kapitel 4 widmet sich der Web-Tier. Der Ant-Task webdoclet wird vorgestellt und es beginnt mit dem Tag für Servlets, Filter, Listener und JSP-Tag-Libs, damit die web.xml erstellt wird. Das Beispiel führt die Idee des Blogs fort. Die Qualität der Quellcodebeispiel ist relativ gut wobei mir bei Listing 4.7 auffällt, dass die Autoren folgendes für doEndTag() schreiben:
try {
if(date != null) {
SimpleDateFormat formatter = new SimpleDateFormat(format);
pageContext.getOut().write(formatter.format(date));
}
} catch (IOException e) { }
return EVAL_PAGE;
}
Die IOException zu schlucken ist vielleicht nicht so toll (in den übrigen Beispielen wird schön geloggt) und ich frage mich, warum der String format zwar in der Objektvariablen gehalten wird, aber warum nicht gleich SimpleDateFormat (und dann auch vom Basistyp DateFormat, der für format() reicht). Möglicherweise wissen die Autoren das die java.util.Format-Klassen nicht Thread-sicher sind, vergessen aber, dass die Tag-Objekte nicht wie die Servlet-Klassen geteilt werden, sondern der Servlet-Container wegen des Zustands der Tag-Objekte immer neue aufbaut (sogar bei jedem Request!) und es somit keine parallelen Zugriffe auf doEndTag() gibt. Es folgt das 5. Kapitel, welches die XDoclet-Unterstützung für Struts und Web-Works vorstellt. Es werden zwei wichtige Merge-Points für web.xml vorgestellt, dann folgend Details über die Struts-Actions und Validatoren und WebWork, bei dem sich die Aussage „Another web-layer framework that is gaining in popularity is OpenSymphony’s WebWork“ nicht bewahrheitet hat. Kapitel 6 springt dann wieder in die Welt der Application-Server und beschreibt Tags für die Container-spezifischen Deployment-Deskriptoren exemplarisch an JBoss und WebLogic. Das beendet den zweiten Abschnitt und der dritte Abschnitt beginnt mit spezielleren Technologien Hibernate/JDO/Castor, der alten Axis-Version, JMX, Mock-Objekte und Portlets. Hibernate wird nicht allzu tief vorgestellt, was ein echtes Manko ist, denn die XDoclet-Unterstützung ist/war perfekt und Entwickler griffen gerne zu XDoclet, um sich die .hbm.xml generieren zu lassen. Hier muss dann die Dokumentation aus dem Anhang oder der Webseite aushelfen, denn das Buch kommt über ein paar einfache Properties und Relationen nicht hinaus, denn sofort geht es zu JDO und dann Castor JDO, Castor XML. Es folgen Web-Services mit Apache SOAP (dem Vorgänger von Axis 1) und Axis 1 dann in Kapitel 8 und wie XDoclet die Deployment-Deskriptoren generiert. Es folgt der Hinweis, das für die Serializer und Deserializer keine Tags existieren, stattdessen ein Merge-Point genutzt werden muss. Damit schließt das Kapitel und das Kapitel 9 widmet sich einer Kurzeinführung zu JMX und kommt dann zu Generierung von MLET-Dateien und der unterschiedlichen Descriptoren für Container wie JBoss oder MX4J. Kapitel 10 entfernt sich komplett von Java EE-Technologien und geht auf Mock-Objekte ein; eine Schnittstelle Automobile wird getaggt und XDoclet erzeugt eine Klasse AutomobileMock. Warum die Autoren allerdings eine Schnittstelle mit 15 (!) Operationen deklarieren und nicht 1 und dann auch nicht bei Ihrem Blog-Beispiel bleiben bleibt im Dunkeln. Die 15 Operationen führen jedoch dazu, dass die AutomobileMock.java über 700 Zeilen dick ist und nicht abgebildet werden kann. Anschließend zeigt ein Beispiel wie im JUnit-Testfall das Mock-Objekt initialisiert und genutzt wird. Da XDoclet kein bekanntes Mock-Framework nutzt, ist die Bedeutung der Lösung gering. Kapitel 11 würde eigentlich viel besser an die Java EE Technologie passen, denn es beschreibt Portles und welche XDoclet-Tags es für welche Einträge im Deployment-Deskriptor portlets.xml gibt. Der letzte Abschnitt, beginnend mit Kapitel 12, geht tiefer in die Architektur von XDoclet ein und beschreibt, wie das Templating funktioniert und eigene Tags und Tasks entwickelt werden. Der 4. Abschnitt nimmt viel Raum ein. Zunächst stellte Kapitel 12 heraus, warum man sich mit Codegenerierung beschäftigten sollte. Es beginnt mit der Aggregation, also dem Sammeln von Informationen und einem einfachen Template; dabei werden die Grundelemente vom .xdt-Format der XDoclet-Template-Dateien vorgestellt. Es folgt die Transformation mit einem Factory-Generator – das ist anschaulich und für jeden gut verständlich. Danach spielen die Autoren den Template-Mechanismus für einen Command-Konfiguration weiter und stellen Tags vor um alle Attribute aus den Java-Klassen, etwa Felder, Konstruktoren auszulesen; das ganze erinnert ein wenig an Reflection. Es folgt ein eigener Content-Tag-Handler und Body-Tags, denn nicht alle lässt sich in XDoclet so einfach umsetzen; es ist wie die JSTL unter Verbot von Skriptlets: Nur lesen ist einfach, aber Zwischenzustände halten wird schnell unleserlich. Das Kapitel schließt mit einem Abschnitt, danit eigene Tags wie eingebaute aussehen – Ant steht naturgemäß im Mittelpunkt. Im Kapitel 13 folgenden XDoclet-Erweiterungen und Tools, worunter die Autoren die IDE-Integration in IntelliJ und Eclipse (mit JBoss IDE) meinen und das MDA-Werkzeug AndroMDA und Middlegen, was Datenbanken ausliest und aus dem Schema XDoclet-versehene EJB-CMP-Klassen (oder JDO-Klassen) generiert. Abschließend gibt der Anhang A eine ausführliche Installationsanleitung für Ant und XDoclet und Anhang B listet die Tasks/Subtasks auf, Anhang C gibt auf über 100 Seiten eine schöne Übersicht über alle XDoclet-Tags, Anhang D die XDt-Template-Syntax und zu aller letzt philosophiert Anhang E über die Zukunftsaussichten von XDoclet. So kommt zu Sprache, dass es XDoclet 2 mit einer neuen Code-Generierungs-Engine Generame gibt sowie einem Code-Templating der auf Jelly bzw. Velocity zurückgreift. Dass XDoclet durch Annotationen komplett sterben wird konnten die Autoren 2004 nicht ahnen; nur ein Jahr Mitte 2005 später bleibt die Uhr bei Version 1.2 stehen. Was ist also meine Zusammenfassung für das Buch? Wer mit XDoclet noch in alten Projekten zu tun hat, der wird dieses Buch mögen. Es ist ausführlich und gut und die Beispiele sind hervorragend, fast immer durchgehend und zu abgehoben. Der Quellcode im Buch ist mehrheitlich in Ordnung, es gib immer wieder Kleinigkeiten, die mich an den Allgemeinen Java-API Kenntnissen und Wissen um die gesetzten Java-Idiomen der Autoren zweifeln lassen. Bei:
String logLevel = config.getInitParameter("LogLevel");
if(logLevel.equals("debug"))
muss man sich fragen, ob man wirklich auf einen potenziellen null-Kandidaten equals() aufrufen möchte – die Variante "debug".equals(logLevel) ist da eigentlich angebrachter. Im Listing 7.9 ist eine public Standardkonstruktor als einziger Konstruktor ohne JavaDoc aufgeführt; die paar Zeilen hätte sich die Autoren auch schenken können und im gleichen Beispiel sind die Parametervariablen nicht prickelnd:
public void setEmail(String string) { email = string; }
public void setId(String string) { id = string; }
Das gleiche auch für Property name und owner. Vom Beispiel 8.1 bin ich enttäuscht. Die String-Variable VOWELS ist mit "AEIOUaeiou" vorbelegt und dann folgt in der Methode:
Character c = new Character(word.charAt(i));
if(VOWELS.indexOf(c+"") >= 0)
…
endBuffer.append(c.charValue());
Hier Character-Objekte aufzubauen ist grober Unfug, ein
char c = word.charAt(i);
if(VOWELS.indexOf(c) >= 0)
…
endBuffer.append(c);
hätte es voll getan (die String#contains(CharSequence)-Methode gab es damals noch nicht, sie wurde erst mit Java 5 eingeführt). In Listing 9.2 im JMX-Kapitel ist die Variable home ohne Sichtbarkeitsmodifizierer, aber private final wäre korrekter. Oder Listing 11.5 im Portlet-Kapitel:
private static String[] states = { … }
private static Set stateSet = new HashSet();
static {
stateSet.addAll(Arrays.asList(states));
}
Was soll das? Zunächst kann states und stateSet final sein, aber davon abgesehen ist der static-Block überflüssig denn der Konstruktor von HashSet nimmt gerne eine Collection an. Besser also – und auch großgeschrieben, wie es die Autoren bei den anderen static-Variablen auch gemacht haben – wäre:
private final static Set STATE_SET = new HashSet( Arrays.asList(states) );
Es fallen weiterhin Kleinigkeiten und Flüchtigkeitsfehler auf, etwa bei
public class Widget {
Widget() {
}
// … widget methods …
}
in dem der Konstruktor nicht public ist, die Klasse aber schon, und im Folgenden
public Widget new Widget() {
return new Widget();
}
was mit dem Leerzeichen auf keinen Fall ein gültiger Methodenname ist. In Kapitel 12 steht in Tabelle 12.1 bei „Field“ in der rechten Zelle „Working with method fields“, aber den Autoren ist beim Copy/Paste wohl das „method“ durchgerutscht. Dann ist ifDoesntHaveclassTag falsch geschrieben, es sollte ifDoesntHaveClassTag heißen, ein anderes Mal stimmen die Einrückungen nicht. Aber diese Kleinigkeiten kann man verzeihen und haben kein großes Gewicht. Aber die Gretchenfrage ist: Sollte man sich das Buch kaufen wenn man nicht aus einem Altprojekt XDoclet erbt? Die Antwort ist eindeutig: Nö. Statt Metadaten über JavaDoc zu setzen sind es heutzutage Annotationen der Standard. XDoclet hat den Dreh nicht bekommen, sich zu einem allgemeinen Code-Generator zu mausern. XDoclet 2 erwartet zwar die Metadaten nicht mehr zwingend in den JavaDocs, sondern kann durch seine Modulfähigkeit die Metadaten prinzipiell auch aus Annotationen lesen, aber irgendwie interessiert sich keiner dafür; Das Projekt kam nie aus der Planungsphase. Ein anderer Grund, dass XDoclet heute keine dominante Rolle mehr spielt, ist der Wegfall überflüssiger Klassen und Descriptoren aus modernen Frameworks. XDoclet machte EJB 2 angenehm, doch in EJB 3 ist XDoclet einfach nicht mehr nötig, genauso wenig wie für Hibernate oder Web-Services. Schade um das Buch, ich mag XDoclet aber seit auch Servlet 3.0 auf Annotationen setzt wird auch die web.xml zur Nussschale. Daher wird auch kein Buch-Update mehr geben und so bleiben Versionen für immer eingefroren: JBoss 3.2, Servlet 2.3, Hypersonic Database statt HSQLDB, drei MBean-Typen (es sind nun 4, da Open MBean dazugekommen ist) und MX4J lebt im Buch noch. Wie schnelllebig die IT-Zeit doch ist.