Dynamik

Autor: Alexander Treptow [minf2622]
Stand: 26.11.2006
 

... [ Seminar "Betriebssysteme, Werkzeuge für das Web und Programmiersprachen" ] ... [ Inhaltsübersicht ] ... Konsistenz & Tests ...

Übersicht: Dynamik


Dynamic Tag Libraries

Grails stellt einige Tag-Bibliotheken zur Verfügung. Diese bieten auch die Möglichkeit der dynamischen Erweiterbarkeit. Es ist daher in Grails möglich eigene Tags hinzuzufügen, ohne zusätzliche Konfigurationen vorzunehmen oder die TLD zu aktualisieren. TLD steht für Tag Library Definitions. Da dort keine Einträge hinzugefügt werden müssen, ist es möglich neue Tags zur Laufzeit der Applikation hinzuzufügen. Allerdings integrieren die Dynamic Tag Libraries (DTL) sehr stark GSP, da GSP etwas dynamischer als JSP ist. Dies bedeutet aber auch, dass für die Erstellung von Tags für JSP etwas mehr Aufwand nötig ist.

Die Tags, die man selbst generiert unterteilen sich grob in drei Gruppen, die einfachen, logischen und iterativen Tags. Die Methoden bzw. Closures, die von den Tags aufgerufen werden, werden in den Tag-Libraries abgelegt. Diese sind unter "grails-app/taglib" zu finden und enden auf "TagLib.groovy". Hier nun drei Beispiele für die drei Arten von eigenen Tags und wie man sie aufrufen kann:

    def includeJs = { attrs ->
        out << "<script src='scripts/${ attrs[ 'script' ] }.js'>"
    }

    <g:includeJs script="myscript" />            -> ein einfacher Tag
    def isAdmin = { attrs, body ->
        def user = attrs[ 'user' ]
        if ( user != null && checkUserPrivs( user ) ) {
            body()
        }
    }

    <g:isAdmin user="${ myuser }">               -> ein logischer Tag
        // restricted Content
    </g:isAdmin>
    def repeat = { attrs, body ->
        def i = Integer.valueOf( attrs[ "times" ] )
        def current = 0
        i.times { body( ++current ) }
    }

    <g:repeat times="3">                         -> ein iterativer Tag
        <p>Repeat this 3 times! Current repeat = ${ it }</p>
    </g:repeat>

Um Grails Tag Libraries in JSP einzubinden gibt es zwei Möglichkeiten. Die eine ist mit dem JSP-"invokeTag"-Tag zu arbeiten, der auf eine Tag aus der Grails Tag Library zugreift.
Zu diesem Punkt ist die einzige Quelle
grails.org nicht eindeutig. Entweder in den Code-Beispielen wurden aus versehen GSP- anstatt JSP-Tags verwendet oder man kann GSP-Tags in JSP-Dateien verwenden und diese werden von Grails herausgefiltert und verarbeitet.

Mit dem "invokeTag"-Tag würden die Aufrufe laut der Grails-Seite wie folgt aussehen:

    <g:invokeTag name="includeJs" script="myscript" />
    <g:invokeTag name="isAdmin" user="${ myuser }">
        // restricted Content
    </g:invokeTag>
    <g:invokeTag name="repeat" times="3">
        <p>Repeat this 3 times! Current repeat = <c:out value="${ it }" /</p>
    </g:invokeTag>

Die zweite Möglichkeit benötigt für einen Tag zwei zusätzliche Dateien, bzw. eine Java Klasse und eine Erweiterung der TLD's. Dafür kann man dann einen eigenen Tag auch in JSP so benutzen wie in GSP.


Services

Ein Service ist eine Klasse, die mehrere Backend-Methoden einer Applikation enthält um die Controller nicht zu überladen. Und zudem ist es durch Services möglich logisch trennbare Bereche in verschiedene Services auszulagern. Um einen Service dann in einem Controller verwenden zu können muss dieser im Controller registriert werden. Da Services Programmorientiert arbeiten ist es nicht empfehlenswert in den Services auf Objektvariablen zu arbeiten, da die Änderungen in den Controllern dann auch bestehen und ggf. in die Datenbank übernommen werden. Services müssen im Verzeichnis "grails-app/services" angelegt werden und auf "Service.groovy" enden. Hier ein kleines Beispiel für die Verwendung eines Service.

class CountryService {
    String sayHello(String name) {
        return "hello ${ name }"
    }
}
class MailingListController {
    GreetingService greetingService
    def helloAction = {
        render( greetingService.sayHello( params.name ) )
    }
}

Scaffolding

Scaffolding generiert automatisch eine komplette Applikation aus einer Domain-Klasse, inklusive der Notwendigen View und Controller für die CRUD-Operationen. Die einfachste Möglichkeit Scaffolging zu aktivieren ist im zu einer Domain-Klasse zugehörigen Controller die Eigenschaft "scaffold" auf "true" zu setzen. Man kann diese Eigenschaft auch auf eine andere Domain-Klasse verweisen lassen. Mit Scaffolding ist es z.B. möglich innerhalb von 5 Minuten eine kleine Seite zu generieren, die ein Bücherdatenbank zur Verfügung stellt.

    Nun ein kleines Tutorial dafür (basierend auf Version 0.3)
  1. Grails muss installiert worde sein
  2. "grails create-app" auf der Console eingeben
  3. Als Name der Applikation "bookapp" angeben
  4. Grails erstellt nun die Projektstruktur
  5. "cd bookapp" eingeben um in den Projektordner zu wechseln
  6. "grails create-domain-class"-Befehl aufrufen und als Namen "book" angeben
  7. Die Datei "../bookapp/grails-app/domain/Book.groovy mit einem Editor öffnen und wie folgt verändern:
    class Book {
        String author
        String title
        Date releaseDate
    
        def constraints = {
            author( length : 5..50 , blank : false )
            title( length : 2..40 , blank : false )
            releaseDate()
        }
    }
    
  8. Änderungen speichern und in den Ordner "../bookapp/grails-app/controllers" wechseln
  9. Neue Datei mit dem Namen "BookController.groovy" anlegen
  10. Den "BookController" im Editor öffnen und wie folgt verändern:
    class BookController {
        def scaffold = true
        // def scaffold = Author.class      -> wäre auch Möglich für eine andere Domain-Klasse
    }
    
  11. In den Ordner "../bookapp/grails-app/conf" welchseln und die Datei "DevelopmentDataSource.groovy" öffnen
  12. Das Attribut "dbCreate" auf "update" setzen
  13. "grails run-app" in der Console eingeben und bestätigen
  14. Den Browser öffnen und die URL "http://localhost:8080/bookapp/book/" anwählen - Fertig

Die Constraints in der Domain-Klasse bestimmen im Fall von Scaffolding die Reihenfolge der Daten in den Views. Und die Applikation wird in diesem Beispiel sehr langsam laufen, da sie im Development-Modus läuft.


Job Scheduling

Eine weiter Funktionalität die Grails unterstützt ist das "Job Scheduling". Dieses wird unterteielt in normale Jobs und CronJobs. Jobs können beliebige Klassennamen haben, sie müssen nur im Verzeichnis "grails-app/jobs" liegen und eine "execute"-Methode besitzen, sowie bestimmte Eigenschaften, die von der Art des Jobs abhängen. Die in Grails verwendeten Jobs verwenden den Quartz Job Scheduler, der über Spring konfiguriert wird. Normale Jobs definieren ein Zeitinterval, wenn dieses verstrichen ist, wird die "execute"-Methode ausgeführt. Zudem besitzen sie ein Anfangsverzögerung. Der folgende Auftrag würde nach einmaligem Warten von 100 Millisekunden alle Sekunde eine Ausgabe machen.

class MyJob {
    def startDelay = "100"
    def timeout = "1000"

    def execute() {
        print "Job run!"
    }
}

CronJobs bestehen aus einer "cronExpression" und der "execute"-Methode, sie können auch in Intervallen ausgeführt werden. Welche möglichen Eingaben eine "cronExpression" bietet findet man hier.

class MyCronJob {
    def cronExpression = "0 0 8 11 12 2006"

    def execute() {
        print "Buy Grails in Action!"
    }
}

... [ Seminar "Betriebssysteme, Werkzeuge für das Web und Programmiersprachen" ] ... [ Inhaltsübersicht ] ... [ Top ] ... Konsistenz & Tests ...