Inhalt

Einleitung

Motivation

Applikation in 12 Schritten Erstellen

Fazit

Einleitung

Spring Roo ist ein Open Source Rapid Application Development (RAD) Framework für Java.
Laut der Roo-Internetseite kann man mit dem Framework sehr schnell Java-Applikationen bauen. Es ist leicht zu bedienen und es gibt eine aktive und hilfreiche Community.

http://projects.spring.io/spring-roo/

Motivation

Im Rahmen eines Projektes sollte eine neue Web-Applikation innerhalb einer kurzen Zeit entwickelt werden, welche Daten in einer Datenbank (mit ca. 18 Tabellen) verwaltet.
Da es um eine klassische CRUD-Web-Applikation handelt, stellt sich natürlich die Frage, ob man wirklich alle Entities, DAOs, Controller, JSP-Seiten und zahlreiche Konfigurationen manuell anlegen soll oder ob ein paar Schritte automatisiert werden können.
Dazu darf man nicht vergessen, dass das Projektsetup mit der Einbindung von allen notwendigen Bibliotheken auch Zeit kostet (auch wenn Maven dabei schon viel Arbeit abnimmt). Viele (un)nötige Diskussionen mit Kollegen über Projekt- und Package-Strukturen machen die Aufgabe auch nicht leichter.
Aus eigener Erfahrung kenne ich Cake-PHP, ein RAD-Framework für PHP. Das Framework wurde damals in einem Projekt eingesetzt und hat uns viel Entwicklungszeit gespart. Als Java-Entwickler aus Leidenschaft wollte ich aber unbedingt Java treu bleiben.
Ich konnte mich an einen alten Artikel im Java-Magazin erinnern, in dem über Spring Roo kurz berichtet wurde. Da Spring mir nicht fremd ist und ich bereits viele Projekte mit Spring Core,  MVC und Security umgesetzt habe, lag es nahe, sich damit mal zu beschäftigen.

Applikation in 12 Schritten Erstellen

Als Beispiel wird eine kleine Web-Applikation für die Zuordnung von Studenten zu Vorlesungen entwickelt. Die Daten werden in einer MySQL-Datenbank persistiert. Die Beziehung zwischen Studenten und Vorlesungen ist eine m:n-Beziehung.

Vor dem Start sollen aktuelle Version von Spring Roo heruntergeladen und ein neuer Projekt-Ordner angelegt werden.

Projekt anlegen

Über Kommandozeile zu dem Projektpfad navigieren und Roo starten:

spring-roo-1.2.5.RELEASE\bin\roo.bat

1.   Über die Roo-Konsole den ersten Befehl ausführen, um eine Projektstruktur mit eingegebenen Namen und Package anzulegen:

project --topLevelPackage de.lustin.rooexample –projectName uni

2.   Projektkonfigurationen für Eclipse anlegen und das Projekt bauen:

perform eclipse

Das generierte pom.xml wird mit jedem Roo-Befehl um notwendige dependencies automatisch erweitert.

Persistenz-Schicht

3.   Erster Schritt ist das Anlegen von Datenbank- und JPA-Konfigurationen. Dabei werden zahlreiche SQL-Datenbanken unterstützt. Von NoSQL-Datenbanken wird aktuell sicher nur MongoDB unterstützt. Dafür wird aber kein JPA genutzt, sondern Spring-Data, deswegen werden auch andere Spring-Roo-Befehle  verwendet (mongo setup, entity mongo, usw.)
Ich verwende wie oben angekündigt MySQL.

jpa setup --provider HIBERNATE --database MYSQL

Die  generierte Datei db.properties soll mit Datenbankkonfigurationen befüllt werden!

4.   Eine Student-Entity mit CRUD-Methoden erstellen. Spring-Roo verzichtet auf DAO-Pattern und alle Datenbank-Zugriffsmethoden werden als statische Methoden direkt in die Entities generiert.  Die testAutomatically-Option ermöglicht die JUnit-Tests-Generierung. Testdaten werden in der StudentDataOnDemand-Klasse bereitgestellt.

entity jpa --class ~.entity.Student –testAutomatically

Die generierten Klassen enthalten zuerst weder Variablen noch Methoden, sondern nur Roo-Annotations. Die Variablen und Methoden befinden sich temporär in AspectJ-Dateien, die über die Roo-Annotations gesteuert werden. Wenn man Roo-Konfigurationen aus dem Projekt entfernt, werden alle AspectJ-Inhalte in die entsprechenden Klassen geschrieben.

5.   Student-Entity mit 2 Felder erweitern:

field string --fieldName name --notNull --sizeMin 2 --sizeMax 50
field number --fieldName matrNumber --notNull --type java.lang.Long

Im Hintergrund wird nicht nur die Entity erweitert, sondern auch die StudentDataOnDemand-Klasse.

6.   Die zweite Entity zum Persistieren von Vorlesungen, inklusiv JUnit-Tests und Generierung von Testdaten anlegen:

entity jpa --class ~.entity.Course –testAutomatically

7.   Course-Entity auch mit 2 Felder erweitern:

field string --fieldName title --notNull --sizeMin 2 --sizeMax 50
field date --fieldName courseDate --notNull --type java.util.Date

8.   Ein Set von Studenten, die die Vorlesung besuchen, anlegen:

field set --fieldName students --type ~.entity.Student

9.   Jetzt sollen wir auch die Student-Entity um eine Collection von Vorlesungen erweitern. Mit dem Befehl focus springen wir in die Student-Klasse zurück

focus --class ~.entity.Student

10.   und legen genauso ein Set an:

field set --fieldName courses --type ~.entity.Course

Wenn die Property „hibernate.hbm2ddl.auto“  in der persistence.xml auf „create“ oder „create-drop“ gesetzt ist, werden beim Starten der Applikation oder bei Ausführung von JUnit-Tests Datenbanktabellen für alle Entity-Klassen erstellt.

Hier stoßen wir auf ein Problem, das bei Spring-Roo einen manuellen Eingriff in die generierten Klassen erfordert: es werden 2 Assoziationstabellen generiert, um eine m:n-Beziehung zwischen Student und Course dazustellen. Deswegen soll die Assoziationstabelle in Entitiy-Klassen vorkonfiguriert werden:  die ManyToMany-Annotation wird mit einer weiteren Annotation JoinTable ergänzt.

Student-Klasse:

@JoinTable(
          name="student_course",
          joinColumns={@JoinColumn(name="student_id", referencedColumnName="id")},
          inverseJoinColumns={@JoinColumn(name="course_id", referencedColumnName="id")})

und die Course-Klasse:

@JoinTable(
          name="course_ student",
          joinColumns={@JoinColumn(name="course_id", referencedColumnName="id")},
          inverseJoinColumns={@JoinColumn(name="student_id", referencedColumnName="id")})

Web-Schicht

11.   Mit diesem Schritt wird die Spring MVC-Struktur angelegt. Es gibt auch eine Möglichkeit, die Web-Schicht für GWT oder JSF zu erstellen. Spring MVC wird aber am besten unterstützt.

web mvc setup

12.   Die Controller-KLassen, JSPs, Apache Tiles Konfigurationen für alle definierten Entities erstellen. Die Controller-Methoden greifen direkt auf entsprechende CRUD-Methoden in Entity-Klassen zu, um unnötige Schichten-Komplexität zu vermeiden.

web mvc all --package ~.controller

 

Das Projekt soll mit Maven-Install-Target gebaut werden und schon haben wir eine lauffähige Web-Applikation.

Optionale Erweiterungen

1.    Folgender Befehl wird ausgeführt, wenn die gleichen CRUD-Methoden auch für JSON-Objekte verfügbar sein sollen:

json all

2.    Die Controller-Klassen um Request-Methoden für JSON-Objekte erweitern

web mvc json all

3.    Unterschiedliche Finder-Methoden. Der Name der Finder-Methode spielt eine wichtige Rolle – find<Entity>By<IntityVariable>

finder add --finderName  findCoursesByTitle --class ~.entity.Course
finder add --finderName  findStudentsByName --class ~.entity.Student

4.    Die Suchfelder für die Finder auf der JSP sichtbar machen und entsprechende  Methoden in Controller-Klassen erstellen

web mvc finder add --formBackingType ~.entity.Course --class ~.web.CourseController
web mvc finder add --formBackingType ~.entity.Stuident --class ~.web.StudentController

5.    Es ist möglich, eine Logik-Schicht zwischen Controller und Datenbankzugriffsmethoden einzuführen:

service all --interfacePackage ~.service.CourseService
service all --interfacePackage ~.service.StudentService

6.    Eine zusätzliche Sprache einfügen. Eine zusätzliche Datei I18n.properties wird angelegt.

web mvc install language --code de

7.    Die Spring Security konfigurieren

security setup

8.    Einfache Selenium-Tests generieren

selenium test --controller ~.web.CourseController
selenium test --controller ~.web.StudentController

9.    Ein Backup von den generierten Sources erstellen

backup

10.    Spring-Roo entfernen über Eclipse

Eclipse: Project -> Refactor -> Push In

Um ein sauberes Projekt zu haben, sollte man noch manuell die Roo-Annotations aus generierten Klassen entfernen, da sie keinen Zweck mehr erfüllen und nur für eine Roo-Wiederverwendung relevant sind. Ja, es gibt Möglichkeit Roo wieder ins Projekt zu integrieren, ist aber von mir nicht empfolen, weil es doch nicht sauber funktioniert hat.

Fazit

Mit dem Framework kann man innerhalb einer kurzen Zeit eine einfache Java-Web-Applikation erstellen. Der generierte Quellcode ist von guter Qualität. Dank den generierten JUnit-Tests für Datenbankzugriffe wird eine hohe Testabdeckung erreicht. Das Framework gibt eine Projektstruktur vor, so dass unnötige Diskussionen im Team vermieden werden können.

Das Framework hat mir sehr beim Starten eines Projektes geholfen. Wenn ich aber Roo länger genutzt habe und dabei die generierten Sourcen manuell angepasst habe, sind Fehler aufgetreten und der Quellcode wurde richtig generiert. Die Fehlermeldungen von Roo sind oft insgesamt nicht aussagekräftig genug, so dass man nicht wirklich verstehen kann, ob eine Funktion fehlerhaft ist, noch nicht implementiert ist oder die Eingaben falsch sind.

Die beste Art, Spring Roo zu verwenden ist: Resourcen generieren, Roo entfernen, Resourcen manuell weiter bearbeiten.

Ich werde Spring Roo in weiteren passenden Projekten gern wieder einsetzen, um die Setup-Phase zu verkürzen und schneller sichtbare Ergebnisse zu erreichen, was in der agilen Softwareentwicklung eine wichtige Rolle spielt.