Web Frameworks – Selbstdefinierte Tags mit Spring Roo

Sonntag, 25. März 2012 von  
unter Fachartikel Architektur

Das Auslagern von sich in Java/J2EE Frontends wiederholenden Code-Fragmenten oder Funktionalitäten, wie z.B. JSPs oder Facelet-basierten JSF-Seiten in .xhtml, kann mit Hilfe von tags geschehen. Solche Funktionalitäten, die vielleicht in genau der erforderlichen Ausprägung noch nicht in vorhandenen Tag-Bibliotheken, wie z.B. der JSTL (Java Server Pages Standard Tag Library), vorhanden sind, aber mehrfach in final als HTML-Ausgabe in vom Browser gerenderten Webseiten verwendet werden, können also extrahiert und wenn diese Fragmente nicht zu Laufzeit Performance-intensiv sind, als .java Klassen, als (JSP-)Tags bzw. Tag Definitionen u. Tag Libraries definiert und programmiert werden. Der eigentliche Vorteil von Tags liegt jedoch in ihrer Wiederverwendbarkeit ohne Code-Duplizierung mit verbesserter Wiederverwendbarkeit nach dem D-R-Y Prinzip (Don’t Repeat Yourself), weshalb dieser Blog Eintrag von durch Erweiterung vorhandener Tags definierten Tags und von generierten Tags handeln soll und davon, wie solch selbstdefinierte Tags z.B. in JSPs verwendet werden (übrigens immer ein beliebtes Thema bei den SCWCD/OCWCD Prüfungen, wie aus eigener Erfahrung bekannt).

Seit der JSP 2.0 Version gibt es zwei Arten von in JSPs der Version 2.0 und höherer Versionen verwendbaren Tags: “Classic Tags“ (sog. “Tag Extensions“, “Custom Actions“, “Classic Actions“ oder “Classic Tag Extensions “) und “Simple Tags“ (sog. “Simple Tag Handlers“). Davor gab es nur “Classic Tags“, die direkt vom Tag Autor als Klassen programmiert wurden und per Compilerung als .class Dateien zur Verfügung zu stellen waren (z.B. im /WEB-INF/tlds – Verzeichnis, wo auch die erforderliche .tld Datei als “TagLib-Descriptor“, zu finden ist). Hier ein Beispiel einer .tld-Datei. Und hier zwei JAVA Klassen als Tag Handler Implementierungen: eine, welche direkt von TagSupport ableitet und dazu die doTag() – Methode implementiert und ein Classic Tag zur formatierten Datumsausgabe in einer JSP, dessen Java Klasse von org.apache.struts.taglib.bean.WriteTag (der Struts 1.3 Tag Library) ableitet und ebenfalls die doTag() – Methode implementiert. Beide Tags sind somit Ausprägungen der seit JSP 1.1 bzw. 1.2 Spezifikation im Package javax.servlet.jsp.tagext.TagSupport implementierten TagSupport Klasse.

Die neuen JSPX basierten Tags, welche in JSP Dokumenten der Endung .jspx verwendet werden, bestehen hingegen nur aus einer Tag Datei der Endung .tagx und beinhalten selbst wieder Tags existierender Tag Bibliotheken, wie z.B. der JSTL, die bereits in implementierter bzw. compilierter Form vorliegen. Die Tag Implementierungs-Klasse zu den .tagx Dateien wird vom J2EE Container mit seiner JSP/Servlet Engine (z.B. Tomcat) während der .tagx File-Compilierung generiert, also im Rahmen des JSP Lifecycles bei der JSP-Compilierung erzeugt, weshalb hierbei keine Tag Handler Klasse zu sehen oder erforderlich ist.

Diese .tagx Dateien werden z.B. auch von SpringRoo generiert und verwenden intern fast ausschließlich Logikelemente der JSTL. Hierfür bietet Spring in den Versionen 2.0, 2.5.x und 3.x mit Spring Roo eine ausgereifte Lösung an, weshalb in diesem Blog-Eintrag anhand eines kleinen Beispiels und einiger @Roo… annotierter Beispiel-Klassen auch kurz darauf eingegangen wird. Zielgruppe des Blog Eintrags sind also Java Entwickler mit Spring Roo und J2EE-Kenntnissen (SCWCD/OCWCD), die bereits Erfahrungen mit selbstdefinierten Tags oder Spring Roo haben, oder diese und ähnliche Erfahrung ergänzen möchten. Hier als Beispiel eine index.jspx, die eine ziemlich kompakte .jspx View zeigt, zumindest, wenn man sie mit einer traditionellen .jsp vergleicht. Dieses JSP Document hat dabei nicht eine Standard HTML Document Struktur, sondern ähnelt eher einer XML Datei. Betrachtet man die Verwendung des <spring:message /> Tags, wird klar, dass es Properties aus einer der beiden Spring typischen .properties Dateien lädt, also der application.properties und der messages.properties, die sich in einer mit Spring Roo generierten Web Applikation im webapp Verzeichnis unter WEB-INF/i18n befinden. Das message Tag kann hierbei verwendet werden um Texte bzw. Messages aus den lokalen Properties Dateien zu lesen und in Page Variablen zu speichern, (wie z.B. in dem folgenden Fragment, welche die Property application_name in der lokalen Page Variable app_namespeichert: <spring:message code=“application_name“ var=“app_name“/>).

Oder es kann verwendet werden, um den Output wie im folgenden Fragment zu rendern, wobei der Textinhalt der Property welcome_titlepaneunter Verwendung der bereits gespeicherten Variable app_name“ zur Substitution in der Message Property “welcome_titlepane“ als „Welcome to Spring Roo WebApp“ vom Tag bereitgestellt wird.

<spring:message code=“application_name“ var=“app_name“/>
<spring:message arguments=“${app_name}“ code=“welcome_titlepane“/>

application.properties:
#app name
application_name=Spring Roo WebApp

messages.properties:
#welcome page
welcome_titlepane=Welcome to {0}

In der Anwendung finden sich heutzutage in den meisten Projekten auch immer seltener die traditionellen Classic Tags, die als Java-Klassen programmiert wurden und das javax.servlet.jsp.tagext.Tag – Interface implementieren, sondern eher die moderneren Simple Tags, welche das javax.servlet.jsp.tagext.SimpleTag – Interface implementieren bzw. von der javax.servlet.jsp.tagext.SimpleTagSupport – Klasse ableiten, oder Tags, die von existierenden Struts oder JSF Tag Bibliotheken abgeleitete Tags sind, die wiederum von der javax.servlet.jsp.tagext.TagSupport – Klasse ableiten. In Spring Projekten, die auf Spring Versionen ab Spring 2.5 basieren bzw. auf diese oder höhere Spring Versionen aufgebaut und migriert wurden, kommen auch immer häufiger die sehr vorteilhaften SpringRoo basierten, generierten Tags zum Einsatz.

Classic Tags wurden vor allem eingesetzt, wenn das Tag eine einzelne isolierbare Aktion durchführen sollte, oder um eine neue Scripting Variable oder ein Scoping Attribut in der aufrufenden JSP im nachfolgenden Code verfügbar zu machen (z.B. per Aufruf von <c:set …/> ), oder um Content abhängig von einer bestimmten Logik in den Response Stream zu schreiben. Die Lifecycle Methoden eines Classic Tags ermöglichen zwar nicht, ein Tag zu schreiben, werden jedoch vom JSP/Servlet Container aufgerufen und lauten: setParent(Tag), setPageContext(PageContext), Tag getParent() und release(). Die Service Methoden eines Classic Tag Handlers ermöglichen, das Tag zu schreiben und lauten: int doStartTag(), int doEndTag(). Mit Hilfe der Schalter EVAL_BODY_INCLUDE, SKIP_BODY wird der Body der Tags geparst und ausgegeben, oder eben nicht; die Schalter EVAL_PAGE, SKIP_PAGE bestimmen, ob der Rest der Jsp nach dem Tag gerendert wird oder nicht. Ein Classic Tag kann auch das javax.servlet.jsp.tagext. Tag – Interface erweiternde javax.servlet.jsp.tagext.IterationTag – Interface mit der Methode int doAfterBody() implementieren, wodurch der zusätzliche Schalter EVAL_BODY_AGAIN zusätzlich eingesetzt werden kann. Üblicherweise wird ein Classic Tag aber von der javax.servlet.jsp.tagext. TagSupport Klasse ableiten oder, wenn die Frage der (nicht) gebufferten Ausgabe des Tag Bodys eine Rolle spielt, von der javax.servlet.jsp.tagext.BodyTagSupport – Klasse, die wiederum das javax.servlet.jsp.tagext. BodyTag – Interface implementiert und den Einsatz des EVAL_BODY_BUFFERED Schalters ermöglicht.

Aber genug von der zunehmenden Komplexität der Classic Tags, die durch den Einsatz von Simple Tags erfreulich vereinfacht wurde (seit JSP 2.0), welche üblicherweise von der javax.servlet.jsp.tagext.SimpleTagSupport – Klasse ableiten, oder das javax.servlet.jsp.tagext.SimpleTag – Interface mit der Methode doTag() implementieren. Als Lifecycle Methoden hat ein Simple Tag die folgenden Methoden: setJspContext(JspContext), setParent(JspTag parent), JspTag getParent(), setJspBody(JspFragment fragment), wobei die letzte Methode den Typ JspFragment verwendet und es möglich ist (genau wie beim BodyContent für ein Classic BodyTag), dass dieses gespeicherte JspFragment null ist, weshalb vor Methodenaufrufen auf der Reference eines JspFragment immer auf JspFragment != null geprüft werden sollte, um eine NullPointerException zu vermeiden. Für die ausführlichen Tag Lifecycles eines Simple Tags oder Classic Tags darf an dieser Stelle auf die Fachliteratur (siehe Zertifizierungsbuch) verwiesen werden. Hier noch ein UML-Diagramm vom Tag Handler API der Simple Tags und Classic Tags.

Zum Thema JSTL hier noch eine meiner Meinung nach sehr gelungene Quick Reference von verfügbaren JSTL Tags.

Wie beschrieben, verwendet Spring Roo die .jspx – XML-konformen JSP Dateien und, um deren Code möglichst übersichtlich zu gestalten, wiederverwendbare, selbstgenerierte .tagx Dateien als Tags. Hier als Beispiel die mit Spring Roo generierten .tagx Dateien im WEB-INF Verzeichnis und deren aufrufende .jspx Document Dateien, welche im Document Header die richtigen Namespaces includieren. Spring Roo wird allerdings in einem eigenen Blog Eintrag besprochen.

Weitere empfehlenswerte Bücher sind “Spring 2.5″ aus dem ADDISON-WESLEY Verlag, das Buch von Eberhard Wolff mit dem Titel “Spring 3″aus dem dpunkt Verlag, das Buch “SPRING im Einsatz” von Craig Walls aus dem HANSER Verlag, sowie das Buch “springframework 2″ aus dem WROX Verlag, um nur einige zu nennen.

Dieser Artikel verwendet als Quelle Beispielcodes aus verschiedenen Open Source Quellen und den offiziell, frei verfügbaren Spring Dokumentationen und Informationen aus den genannten Büchern als auch eigene Erfahrungen mit dem Spring Roo Framework und mit JSPs und Tags.

Kommentare

10 Kommentare zu “Web Frameworks – Selbstdefinierte Tags mit Spring Roo”

  1. Von Services – mit REST, JPA 2, EJB 3.2, JSF 2.2, Angular JS, Bootstrap, JBoss Forge : Softwareentwicklung, Projektmanagement & Schulung | binaris informatik GmbH am Donnerstag, 1. Oktober 2015 08:27

    […] von Tags und TagLibs, z.B. im Zusammenhang mit dem Struts 1.3 Framework und mit Spring Roo, gibt es hier einen weiteren Blog-Eintrag in diesem […]

  2. Von WebApps – mit JSF 2.2, Primefaces 5, REST, JPA 2, JEE7, JBoss WildFly 10 : Softwareentwicklung, Projektmanagement & Schulung | binaris informatik GmbH am Sonntag, 28. Februar 2016 19:29

    […] bestehender und die Definition eigener Tags gibt es bereits einen Blog-Eintrag in diesem Blog hier und durch die soeben gezeigten Beispiele ist erkennbar, wie simpel es ist, eigene Tags für die […]

  3. Von WebApps – Migration JSF 2.2 MyFaces, RichFaces zu Primefaces, REST, JPA 2, JEE7 auf JBoss WildFly 10 : Softwareentwicklung, Projektmanagement & Schulung | binaris informatik GmbH am Sonntag, 27. März 2016 19:09

    […] bestehender und die Definition eigener Tags gibt es bereits einen Blog-Eintrag in diesem Blog hier und durch die soeben gezeigten Beispiele ist erkennbar, wie simpel es ist, eigene Tags für die […]

  4. Von WebApps – Migration mit JSF 2.2 Primefaces, REST, JPA 2, JEE7 auf JBoss WildFly 10 : Softwareentwicklung, Projektmanagement & Schulung | binaris informatik GmbH am Samstag, 30. April 2016 22:44

    […] bestehender und die Definition eigener Tags gibt es bereits einen Blog-Eintrag in diesem Blog hier und durch die soeben gezeigten Beispiele ist erkennbar, wie simpel es ist, eigene Tags für die […]

  5. Von WebApps – vom Modell zur App, mit JSF 2.2, Angular JS, REST, JPA 2, JBoss WildFly 10 : Softwareentwicklung, Projektmanagement & Schulung | binaris informatik GmbH am Sonntag, 29. Mai 2016 15:51

    […] bestehender und die Definition eigener Tags gibt es bereits einen Blog-Eintrag in diesem Blog hier und durch die soeben gezeigten Beispiele ist erkennbar, wie simpel es ist, eigene Tags für die […]

  6. Von WebApps – mit JPA 2, JSF 2.2, Primefaces 6, REST, JEE7, Java 8 auf JBoss WildFly 9 und WildFly 10 : Softwareentwicklung, Projektmanagement & Schulung | binaris informatik GmbH am Sonntag, 25. September 2016 23:41

    […] bestehender und die Definition eigener Tags gibt es bereits einen Blog-Eintrag in diesem Blog hier und durch die soeben gezeigten Beispiele ist erkennbar, wie simpel es ist, eigene Tags für die […]

  7. Von WebApps – mit JSF 2, Primefaces 6, REST, JPA 2, EJB 3, JEE7, Java 8 auf JBoss WildFly : Softwareentwicklung, Projektmanagement & Schulung | binaris informatik GmbH am Sonntag, 27. November 2016 18:31

    […] bestehender und die Definition eigener Tags gibt es bereits einen Blog-Eintrag in diesem Blog hier und durch die soeben gezeigten Beispiele ist erkennbar, wie simpel es ist, eigene Tags für die […]

  8. Von WebApps – mit JSF 2, RichFaces 4, Primefaces 6, REST, JPA 2, EJB 3, JEE7, JBoss WildFly : Softwareentwicklung, Projektmanagement & Schulung | binaris informatik GmbH am Samstag, 28. Januar 2017 12:18

    […] bestehender und die Definition eigener Tags gibt es bereits einen Blog-Eintrag in diesem Blog hier und durch die soeben gezeigten Beispiele ist erkennbar, wie simpel es ist, eigene Tags für die […]

  9. Von WebApps – Primefaces 6, FileUploads, JSF 2, JPA 2, EJB 3, JEE7, REST, AngularJS, WildFly : Karriere als Software Entwickler | binaris informatik GmbH am Mittwoch, 22. Februar 2017 16:03

    […] bestehender und die Definition eigener Tags gibt es bereits einen Blog-Eintrag in diesem Blog hier und durch die soeben gezeigten Beispiele ist erkennbar, wie simpel es ist, eigene Tags für die […]

  10. Von WebApps – JSF 2, Primefaces, FileDownloads, JPA 2, EJB 3, JEE7, REST, MySQL, WildFly : Karriere als Software Entwickler | binaris informatik GmbH am Sonntag, 26. März 2017 19:52

    […] bestehender und die Definition eigener Tags gibt es bereits einen Blog-Eintrag in diesem Blog hier und durch die soeben gezeigten Beispiele ist erkennbar, wie simpel es ist, eigene Tags für die […]

Einen Kommentar hinzufügen...

Sie müssen registriert und angemeldet sein um einen Kommentar zu schreiben.