... gegen Computerkopfschmerzen

Grails: Tutorial 3 – Weitere Tipps

In diesem Tutorial findet man weiterführende Hinweise zu Grails, die nicht in und enthalten sind.

Ich habe zu diesem Zweck ein neues, sehr übersichtliches Projekt angelegt. Es handelt sich um eine Liste von Obstbäumen mit den Feldern „Name“, „Art“, „Typ“, „Kaufdatum“ und „Bemerkung“. Da in diesem Tutorial das Datenmodell zwischendurch öfter geändert wird, steht dbCreate in der Datei grails-app/conf/application.yml auf update. Das funktioniert meistens, um die Änderungen auch der Datenbank bekannt zu machen. Falls Grails trotzdem abstürzt, findet man am Ende dieses Beitrages zwei Möglichkeiten, das Problem zu beheben.

Beispielanwendung erstellen

Die Anwendung wird mit
% grails create-app Garten

% mv Garten Garten-DB

% cd Garten-DB

Garten-DB % grails create-domain-class Baum

erzeugt. Das Basisverzeichnis ist Garten-DB, die Datenbank heißt garten.

Datenmodell

Die Domain sieht so aus:
Garten-DB % vi grails-app/domain/garten/Baum.groovy

package garten

class Baum {

String name
String art
String typ
Date gekauft
String bemerkung
static constraints = {
name (unique:true)
art inList: ['Süßkirsche','Sauerkirsche','Apfel','Birne','Zwetschge','Mirabelle','Quitte','Blaubeere','Himbeere','Brombeere','Heidelbeere']
typ inList: ['Halbstamm','Buschbaum','Säule','Strauch']
typ (nullable:true)
gekauft (nullable:true)
bemerkung (nullable:true)
}
}

Das Listenansicht sieht so aus:
Listenansicht Baum-Datenbank mit Grails

„Name“ und „Art“ sind Pflichtfelder, die anderen nicht, da für diese Felder in der Domain nullable:true hinterlegt ist. Für die Felder „Art“ und „Typ“ ist eine Liste mit vorgegebenen Werten definiert, die man beim Anlegen des Baumes in einem Dropdown-Menu angezeigt bekommt:
Dropdown-Menu

Datumsformat und individuelle Texte

Das Datum enthält auch die Uhrzeit, diese löscht man hier:
Garten-DB % vi grails-app/i18n/messages_de.properties

löschen:

default.date.format=dd.MM.yyyy HH:mm:ss z

In dieser Datei kann man auch die Texte anpassen, die in der Weboberfläche (beispielsweise in den Dialogen) angezeigt werden. An einigen Stellen wird automatisch der Name der Domain verwendet (in diesem Fall „Baum“), z. B. in der Listenansicht in der Überschrift „Baum Liste“. Diesen Text kann man ebenfalls hier ändern. Außerdem wird der Name des Feldes „gekauft“ auf „Kaufdatum“ geändert:
Garten-DB % vi grails-app/i18n/messages_de.properties

ergänzen:

typeMismatch.java.math.BigInteger=Die Eigenschaft {0} muss eine gültige Zahl sein

baum.label=Obstbaum
baum.gekauft.label=Kaufdatum

Nachdem noch einige Bäume angelegt wurden, sieht die Liste so aus:
Listendarstellung mit 10 Einträgen

Bei mehr als zehn Einträgen wird eine Seitennummerierung angelegt. Die Anzahl der Einträge pro Seite kann man so ändern:
Garten-DB % vi grails-app/controllers/garten/BaumController.groovy

ändern:

def index(Integer max) {
params.max = Math.min(max ?: 15, 100)
respond baumService.list(params), model:[baumCount: baumService.count()]
}

Jetzt ist die Liste länger und die Seitennummerierung erscheint erst wieder, wenn mehr als 15 Einträge in der Liste vorhanden sind.
Listendarstellung mti 15 Einträgen

Datensätze ohne Link?


Jetzt kommen noch ein paar Experimente mit der Domain (Grails ist gestoppt).

Bisher ist das Feld „Name“ unique, d.h. ein Wert darf nur einmal vorkommen und das Feld darf nicht leer sein. Das wird nun so verändert, daß diese Einschränkungen nicht mehr gelten:
Garten-DB % vi grails-app/domain/garten/Baum.groovy 

ändern:

static constraints = {
name (nullable:true)

Grails wird wieder gestartet, die Datenbanktabelle wird automatisch angepaßt. Die Liste sieht jetzt so aus:

Listendarstellung, Feld Name kann keer sein

Jetzt gibt es ein Problem: die Datensätze, in denen das Feld „Name“ leer ist, können nicht angezeigt oder verändert werden, da ein Link auf sie fehlt. Im Grails-Tutorial: 1 – Anwendung inkl. Bild-Upload haben wir gesehen, daß das Ausschließen eines Feldes aus der Listenansicht das Feld „Id“ sichtbar macht. Das probieren wir aus und schließen das Feld „Bemerkung“ aus:
Garten-DB % vi grails-app/views/baum/index.gsp 

ergänzen:

</g:if>
<f:table collection="${baumList}" except="bemerkung"/>

<div class="pagination">

Jetzt wird in der Liste das Feld „Id“ angezeigt, welches der Primärschlüssel der Tabelle „Baum“ ist:
Listendarstellung mit Feld Id

Da das Feld „Bemerkung“ in der Listenansicht natürlich angezeigt werden soll, wird ein zusätzliches Dummy-Feld im Datenmodell definiert und dann in den verschiedenen Views (index.gsp, edit.gsp, show.gsp, create.gsp) wieder ausgeschlossen:
Garten-DB % vi  grails-app/domain/garten/Baum.groovy

ergänzen:

</g:if>
String bemerkung
String dummy
static constraints = {

bemerkung (nullable:true)
dummy (nullable:true)
}


Garten-DB % vi grails-app/views/baum/index.gsp

ergänzen:

</g:if>
<f:table collection="${baumList}" except="dummy"/>

<div class="pagination">

Jetzt hat man auch die Möglichkeit, Datensätze mit leerem Feld „Name“ aufzurufen:

Listendarstellung mit Bemerkung

Grails stürzt ab?

Wenn Grails nach Änderungen am Datenmodell abstürzt, kann man folgendes tun:

Datenbanktabelle löschen:
Garten-DB % mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 913
Server version: 8.0.23 MySQL Community Server - GPL

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use garten
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> drop table baum;
Query OK, 0 rows affected (0.00 sec)

mysql> quit

Controller und Views neu generieren
Garten-DB % grails generate-all Baum -force



macOS Catalina
Grails Version: 4.0.8
JVM Version: 11.0.10
MySQL Community Server 8.0.23