Startseite > Techblog > Artikel mit dem Tag: groovy
tfl

Unser Teamoffsite in Eschdorf am 13.11.09 war unter Anderem dem Thema gpars (http://gpars.codehaus.org/) gewidmet, ein Groovy-Framework, welches es erlaubt, parallele Software zu entwickeln, ohne dabei die Komplexität der dafür vorgesehenen Java-Mechanismen kennen zu müssen.
Folgende Konzepte werden von gpars unterstützt:

- Aktoren (auch verteilte)
- Datenflussoperatoren
- Sicherungen für veränderliche Objekte (Safe) sowie
- nebenläufige Operationen auf Collections und
- asynchrone Ausführungen

Gpars ist gut dokumentiert und bringt zahlreiche Beispiele mit, welche zum Teil bekannte Probleme sehr elegant und anschaulich lösen. Im Laufe des Tages haben wir verschiedene Konzepte ausprobiert und die Auswirkungen von paralleler Software auf die Bearbeitungszeit und Prozessorlast auf Mehrkern-Systemen unter verschiedenen Betriebssystemen (Windows, Linux) und unterschiedlichen Kerneln (Linux RT, Standard) untersucht. Allgemein konnte eine spürbare Verbesserung der Performance durch Parallelisierung beobachtet werden, eine reine Java-Implementierung mit Threads war zwar auch deutlich schneller, konnte aber mit der Gpars-Lösung bei weitem nicht mithalten.

Kommentar Feed Trackback URL
abu

Um in die Ausführung von Skripten zur Laufzeit einzugreifen gibt es das Feature der Scripting Events. Fast jedes Grails-Skript beinhaltet ein oder mehrere Einstiegspunkte (Hooks), welche man abgreifen und dann im Kontext des gerade laufenden Skriptes eigene Aktionen ausführen kann. Dazu wird einfach im Ordner /scripts die Datei _Events.groovy erstellt und von dort aus lässt sich nun auf einfache Weise überall “einhaken”.

Im letzten Projekt nutzten wir dieses Feature um zusätzliche Properties in der web.xml zu ersetzen und das funktionierte auch wunderbar in der lokalen Windows-Entwicklungsumgebung. Leider aber nicht auf der Build-Maschine, welche unter einem Unix-Betriebssystem lief. Der Fehler war nach langem Probieren ausgemacht – beim Anlegen des Skriptes wurde fälschlicherweise der Name _events.groovy anstatt _Events.groovy vergeben. Anscheinend ist Windows etwas weniger Restriktiv was den Aufruf der Datei anhand des Namens betrifft, ein Umbennen schaffte letztendlich abhilfe.

Kommentar Feed Trackback URL
abu

Bei Fehlern in Groovy Server Pages (kurz Gsp), erhält man erfreulicher Weise einen Stacktrace direkt auf der Seite in der jener Fehler aufgetreten ist. Weniger hilfreich ist allerdings, dass die angegebenen Zeilenummern in denen der Fehler auftrat nicht mit denen des geschriebenen Quellcodes zusammenpassen, wie dies z. B. bei Groovy-Klassen der Fall ist. Hier ein kleines Beispiel mit einer provozierten LazyInitializationException (../books/show/1):

GSP Exception

Zufällig bin ich durch einen Blog-Beitrag auf einen Parameter gestoßen, welcher den kompilierten Code einer Gsp direkt im Browser ausgibt (beschrieben ist dies auch in der Grails API im GroovyPagesServlet). Mit showSource=true erhält man den Quellcode samt Zeilennummern für die ausgewählte Url angezeigt. Für das obere Beispiel würde dies dann so aussehen (../books/show/1?showSource=true):

Gsp mit showSource=true

Das Ganze funktioniert natürlich nur im “Development-Mode”, eine Sicherheitslücke für den produktiven Einsatz muss daher nicht befürchet werden :-)

Kommentar Feed Trackback URL
abu

Die Validierung von Attributen direkt in Domain-Klassen durchzuführen ist nicht nur praktisch, sondern spart auch an mancher Stelle aufwändiges Exception-Handling. Mit einfachen Mitteln ist man in der Lage die Korrektheit der übergebenen Variablen zu überprüfen, bei Bedarf auch gleich mit einer lokalisierten Fehlermeldung.

Die klassische Variante

Zur Einführung wird zunächst eine simple Klasse mit entsprechenden Constraints erzeugt:

class User {
  String login
  String surname
  String lastname
  static constraints = {
    login(size:5..8,blank:false)
    surname(minSize:3, blank:false)
    lastname(minsize:3, blank:false)
  }
}

Beim Aufruf der Methoden save() bzw. validate() werden die gesetzten Werte über die Constraints überprüft und ein eventueller Fehler samt dem zugehörigen Klassen-Attribut im Objekt selbst hinterlegt. Beim standardmäßigen Aufruf einer .gsp können diese Fehler dann ausgegeben werden. Im folgenden Listing ist diese Funktion am Beispiel einer Service-Klasse dargestellt:

class UserService {
  ...
    User user = new User(login:"myLogin", surname:"hans", lastname:"m")
    if(!user.validate()) {
      user.errors.hasErrors.each {
        println "-> Error: " + it.getField()
      }
    }
    user.save()
  ...
}

Das Speichern des User-Objektes würde im oberen Fall fehlschlagen und auf der Konsole der Name des invaliden Feldes auftauchen. Da Domain-Klassen in der Regel aber etwas komplexer sind, zeigt das nächste Listing die Auslagerung des Nutzernamens in einer separaten Klasse:

class UserName {
  String surname
  String lastname
  static constraints = {
    surname(minSize:3, blank:false)
    lastname(minsize:3, blank:false)
  }
}
class User {
  String login
  UserName name
  static constraints = {
    login(size:5..8,blank:false)
    name(nullable:false)
  }
}

Artikel vollständig lesen »

Kommentar Feed Trackback URL
abu

Wer sich als Java-Entwickler bereits ein wenig mit der Sprache Groovy beschäftigt hat, wird während der Projektarbeit sicher schon einige Verwendungsmöglichkeiten für Groovy-Sprachkonstrukte gefunden haben. In den meisten Fällen betrifft dies eher relativ triviale Funktionen, wie Operationen im Dateisystem oder das Auswerten von Variablen eines Typs. Da aber gerade in der Erstellung von Prototypen die Evaluierung von Kernprozessen im Vordergrund steht, kann die ergänzende Verwendung von Skriptsprachen á la Groovy etwas mehr Geschwindigkeit und Flexibilität in die Entwicklung bringen.

Vorbereitungen

Um das eigene Projekt fit für den Groovy-Code zu machen, muss zunächst einmal die groovy-all-1.5.4.jar in den Build-Path aufgenommen werden. In der Regel findet sich diese Library im Verzeichnis der Groovy-Installation im Ordner \embeddable. Verwendet man Eclipse, so funktioniert das in etwa so ‘Project > Properties > Java Build Path > Libraries > Add External JARs…‘, wobei man es vorziehen sollte die Bibliothek in ein eigenes Projektverzeichnis zu kopieren (/lib) und von dort aus zu verlinken.

Theoretisch könnte es jetzt auch schon losgehen, aber ich denke die Wenigsten wollen beim Programmieren auf lieb gewonnene Features wie z.B Syntax Highlighting verzichten. Es gibt für die gängigsten IDE’s bereits Groovy-Plugins und ein paar Links dazu finden sich am Ende des Beitrages, wer mit Eclipse arbeitet kann mal einen Blick hierauf werfen. Die Plugins an sich sind zwar noch nicht 100% ausgereift und Autocompletion vermisst man stellenweise auch, aber hey – ich habe vor kurzem mit dem vi programmiert, auch das ging ;-)

Der erste Kontakt

Um einen schnellen Einstieg zu bekommen, soll ein kleines Beispielprojekt in Form eines Autohandels den Integrationsprozess veranschaulichen. Nachfolgend findet sich ein Listing zweier Interfaces die als Schnittstelle zur Groovy-Welt dienen.

package de.j2g.interfaces;

public interface ICar {
    public String getMake();
    public String getModel();
    public String getType();
    public double getPrice();
}

package de.j2g.interfaces;

import java.util.ArrayList;

public interface IGarage {
    public ArrayList<ICar> getCars();
}

Nachdem die Struktur steht, geht es an die Implementierung der Groovy-Klassen. In einem separaten Package wird die Klasse Car.groovy erzeugt, welche das Interface ICar implementiert:

package de.j2g.groovy

import de.j2g.interfaces.ICar;

class Car implements ICar {
    String make
    String model
    String type
    double price
}

Nein, hier wurde nicht vergessen die Methoden des Interfaces hinzuschreiben. Da Groovy die Getter- und Setter-Methoden zur bei Kompilierung selbst hinzufügt, müssen lediglich die Instanzvariablen definiert werden. Als Nächstes kommt die Implementierung der Garage.groovy:

package de.j2g.groovy

import de.j2g.interfaces.IGarage;
import de.j2g.interfaces.ICar;
import java.util.ArrayList;

class Garage implements IGarage {
    public ArrayList<ICar> getCars() {

    def cars = new ArrayList<ICar>()

    def car1 = new Car()
    car1.make = “Ford”
    car1.model = “SHELBY GT500″
    car1.type = “Sports Car”
    car1.price = 89000.00

    def car2 = new Car()
    car2.make = “Ford”
    car2.model = “Taurus”
    car2.type = “Full-Size”
    car2.price = 21000.00

    cars.add(car1)
    cars.add(car2)

    return cars
    }
}

Der Groovy-Teil steht, jetzt fehlt noch der Aufruf aus der Java-Welt. In der Main-Klasse werden als erstes die benötigten Groovy-Klassen über den mitgelieferten GroovyClassLoader geladen. Da nur die Methode getCars() der Garage.groovy angesprochen wird, muss auch nur diese Klasse explizit geladen werden. Alle abhängigen Klassen, in diesem Fall nur die Car.groovy, werden automatisch mitkompiliert und geladen. Ist die Klasse geladen, erzeugt man davon eine neue Instanz und castet diese auf das zuvor angelegte Interface IGarage.

package de.j2g.main;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;

import java.util.ArrayList;

import org.codehaus.groovy.control.CompilationFailedException;

import de.j2g.interfaces.ICar;
import de.j2g.interfaces.IGarage;

public class CarDealer {

    public static void main(String[] args) {
        System.out.print(“Loading groovy classes… “);
        ClassLoader parent = CarDealer.class.getClassLoader();
        GroovyClassLoader loader = new GroovyClassLoader(parent);

        Class gGarage = null;

        try {
            gGarage = loader.loadClass(“de.j2g.groovy.Garage”);
        } catch (CompilationFailedException e) {
            …
        } catch (ClassNotFoundException e) {
            …
        }

        GroovyObject goGarage = null;
        try {
            goGarage = (GroovyObject) gGarage.newInstance();
        } catch (Exception e) {
            …
        }

        System.out.println(” done!”);

        IGarage garage = (IGarage) goGarage;
        ArrayList<ICar> cars = garage.getCars();

        for (ICar car : cars) {
            System.out.print(“\n” + car.getMake() + ” “);
            System.out.println(car.getModel());
            System.out.println(car.getPrice() + ” €”);
            System.out.println(car.getType());
        }
    }
}

Das Ausführen der Main-Class sollte folgende Ausgabe auf die Konsole bringen:

    Loading groovy classes... done!     

    Ford SHELBY GT500
    89000.0 €
    Sports Car
    

    Ford Taurus
    21000.0 €
    Full-Size

The Power of Groovy

Die Funktionen im oberen Beispiel hätte man sicher auch ebenso schnell in Java umsetzen können. Etwas Programmieraufwand konnte aber schon bei der Car.groovy gespart werden – es war nicht nötig die Getter- und Setter zu definieren. Um nun die Effizienz der Skriptsprache noch etwas deutlicher zu machen, wird im Folgenden die Klasse Garage.groovy um einen FileReader erweitert:

cars.txt

    Toyota;Camry;34000;Full-Size
    VW;Golf;25000;Economy

Garage.groovy

public ArrayList<ICar> getCars() {
    def cars = new ArrayList<ICar>()
    def carFile = new File(‘D:/cars.txt’)

    carFile.eachLine {
        line ->
            def carArray = line.split(‘;’)
            def car = new Car()
            car.make = carArray[0]
            car.model = carArray[1]
            car.price = Integer.parseInt(carArray[2])
            car.type = carArray[3]
            cars.add(car)
    }
    return cars;
}

Fazit

Einfacher geht es kaum noch, wenig Code zur Funktionsimplementierung und optionales Exception-Handling machen Groovy zum idealen Begleiter für die Agile Entwicklung!

Groovy IDE Plugins: Eclipse IntelliJ JEdit Netbeans

Kommentar Feed Trackback URL
abu

Dieser Artikel soll einen Überblick über das Session Objekt in Grails geben und Lösungsmöglichkeiten bei Anwendungsfehlern aufzeigen.

Die allgegenwärtige Session

In allen Controllern ist die Session bereits standardmäßig im Application-Scope und wartet gebrauchsfertig mit dem Namen “session” auf Verwendung. Das Objekt implementiert im wesentlichen die Standardfunktionalität der javax.servlet.HttpSession und hält ergänzend die Zugriffsmöglichkeiten einer GroovyMap bereit.

session.username = ‘John Doe’

println session["username"] oder
println session.username

Das Objekt selbst wird im Hintergrund über request.getSession() initialisiert, daher hat man auch nach einem session.invalidate() bzw. einem Timeout beim nächsten Actionaufruf (Achtung: Nicht im selben Controller!) eine neue Session. Am Beispiel einer Nutzer-Authentifizierung soll der Zugriff verdeutlich werden:

//Im Interceptor ist die Authentifizierung definiert, die vor jeder Action ausgeführt werden soll
def beforeInterceptor = [action:this.&auth,except:'login']

//Falls kein Nutzer in der Session gefunden wird, erfolgt eine Weiterleitung zur Login-Action
def auth() {
  if(!session.user) {
    redirect(action:’login’)
    return false
  }
}
def login = {
    // zeige Login-Seite
}

Session Timeouts

Wie oben bereits angesprochen, muss man sich kein neues Session Objekt nach einem Timeout besorgen. Leider hat dieser Mechanismus aber den Nachteil, dass man dadurch nicht merkt ob eine neue Session durch den Timeout einer Vorhergehenden erzeugt wurde und Rückschlüsse darauf lassen nur eine neue ID und die fehlenden Session-Attribute zu.

Braucht ein Nutzer z.B. zu lange um eine Formular auszufüllen, bekommt er beim nächsten Klick den Zugriff verweigert oder der aktuelle Bearbeitungssatus wird zurückgesetzt. Sicher ist dies in den meisten Fällen eines Session-Timeouts der Fall, aber hier ist der unberechtigte Zugriff mit dem Timeout gleichgesetzt und der Nutzer kann schlecht explizit auf eine abgelaufene Session hingewiesen werden.

Eine Möglichkeit herauszufinden ob die aktuelle Session noch existiert und eine entsprechende Meldung auszugeben, wäre einen Parameter zu setzen und diesen vor einer Action abzufragen:

static beforeInterceptor = [action:this&checkSession, except:'login']

def checkSession = {
  if(!session.timeout)
  render(“Session Timeout!”)
}

AfterInterceptor Verwendung

Die Möglichkeiten eines Interceptors sind vielfältig, sollten aber gerade bei Ausführung nach Methodenaufrufen mit bedacht eingesetzt werden.

Beispiel: Man definiert in einer Basisklasse den Zugriff auf die Session per AfterInterceptor (z.B. für einen Logger) und leitet diese dann in einem Controller ab. In einer neuen Action wird nun die Session ungültig gemacht und als Ergebnis löst der Aufruf der Session-Variable im Interceptor automatisch eine IllegalStateException aus.

Dieser Aufruf kann auch schon die blosse Ausgabe der Session sein, da das Objekt im Controller nicht mehr exisiert. Im nachfolgenden Codeauszug wird der eben beschriebene Fall veranschaulicht:

class BasisController {
  def afterInterceptor = {       
    //wirft eine IllegalStateException
    println session
  }
  …
}

class UserInterface extends BasisController {
//Erzeugt nach dem render eine IllegalStateException
  def logout = {
     session.invalidate()
     render(view:’logout’)
  }
}

Ein Workaround wäre, im Interceptor nicht die Session-Variable des Controller zu nutzen. Stattdessen sollte man die Session direkt aus dem Request holen:

class BasisController {
  def afterInterceptor = {        
    //gibt die Session aus oder null, wenn diese ungültig wurde
    println request.getSession(false)
  }
  …
}

Zugriffe ohne Session

Ein großer Nachteil der automatischen Sessionvergabe war bislang auch die Tatsache, dass bei einzelnen Controlleraufrufen (z.B. durch einen externen Service), ebenfalls eine Session erzeugt wurde, obwohl diese gar nicht benötigt wurde. So hatte man bei einem Aufruf durch einen Webservice nach jedem Request immer eine Session, welche unbenutzt auf den Timeout wartete.

Seit Grails 1.0.1 wird nur nach der expliziten Nutzung des Session Objektes im Controller eine neue Session angelegt. Siehe dazu http://jira.codehaus.org/browse/GRAILS-1238.

Kommentar Feed Trackback URL
abu

Auf der offiziellen Grails Homepage gibt es bereits ein sehr gutes How-To für die Integration von Grails in Eclipse. Da die Konfiguration aber nicht immer reibungslos verläuft und vor allem das Einbinden bestehender Grails Projekte in die IDE nach wie vor Probleme bereiten kann, sollen nachfolgend noch einmal die wichtigsten Schritte und Stolpersteine erläutert werden.

Groovy Plugin

Basis für die Grails Entwicklung ist das (noch) nicht ganz ausgereifte Groovy-Plugin für Syntax Highlighting, Basic Code Completion und Kompilierung der Klassen. Die aktuelle Version gibt es zum Download unter

http://dist.codehaus.org/groovy/distributions/update/

Eclipse Konfiguration

Nach der Installation des Plugins muss eine Variable zum GRAILS_HOME gesetzt werden (Window -> Preferences -> Java -> Classpath Variables -> New…).

Anschließend sollte man noch bei Disable Groovy Compiler Generating Class Files (Window -> Preferences -> Groovy) einen Haken setzen.

Projekte bearbeiten

Bestehendes Projekt
Falls das zu importierende Projekt bereits einmal in Eclipse bearbeitet wurde, dann lässt es sich leicht über Import... -> Existing Projects Into Workspace hinzufügen.

Neues Projekt
Ist das Projekt eben erst angelegt oder noch nie mit Eclipse bearbeitet worden, erkennt die IDE nicht ohne Weiteres das es sich um ein Groovy Projekt handelt und welchen Builder es einsetzen muss. Folgende Schritte führen zum Erfolg:

  1. File -> New -> Java Project
  2. Create project from existing source auswählen und Projekt-Root angeben
  3. Project Name muss den selben Namen haben wie das Root-Verzeichnis des zu importierenden Projektes
  4. Finish!

Sollte man trotzdem noch nicht in den Properties die Groovy Einstellungen sehen, hilft eventuell Add Groovy Nature im Kontextmenü anzuklicken. Sind in der Package Ansicht die entsprechenden Grails Source Folder nicht als Source Folder angezeigt, sondern lediglich als normale Ordner, muss man folgende Einträge in der Datei .classpath ergänzen:

...
<classpathentry kind="src" path="src/java"/>
<classpathentry kind="src" path="src/groovy"/>
<classpathentry kind="src" path="grails-app/conf"/>
<classpathentry kind="src" path="grails-app/controllers"/>
<classpathentry kind="src" path="grails-app/domain"/>
<classpathentry kind="src" path="grails-app/services"/>
<classpathentry kind="src" path="grails-app/taglib"/>
<classpathentry kind="src" path="test/integration"/>
<classpathentry kind="src" path="test/unit"/>

Applikation starten

Bevor man den Server das erste Mal starten kann, muss folgender Befehl im Projekt-Root auf der Kommandozeile ausgeführt werden:    grails dev package

Um nun den Server zu starten, klickt man auf Run As -> Open Run Dialog... und im erscheinenden Fenster auf Java Application -> <Projektname>. Dort sind bereits alle Einstellungen gesetzt und ein Klick auf Run startet den Jetty Server. Beenden kann man die Applikation indem man einfach den Prozess terminiert.

Grails Targets aufrufen

Zwar ist es nun problemlos möglich während der Entwicklung den Jetty Server zu kontrollieren, jedoch stellt uns das System keine Möglichkeit zur Verfügung, auch andere Targets aufzurufen. Der Aufwand, beim Erstellen und Generieren von Domains, Controllern und initialen Views die Konsole zu bemühen, bleibt also bestehen. Um dem Problem zu begegnen, nutzen wir die Funktionen des External Tools Dialog. Im nachfolgenden Beispiel wird eine Domain-Class generiert:

  1. Öffnen der Konfiguration
    Run -> External Tools -> Open External Tools Dialog...
  2. Anlegen einer neuen Konfiguration
    Nach Anlegen einer neuen Konfiguration (Program -> New), müssen folgende Einträge gesetzt werden:
    Name
    Hier wird der Name der Konfiguration eingetragen, in diesem Fall soll er identisch mit dem Standard-Aufruf sein: grails create-domainclass
    Location
    Da die grails.bat für die Ausführung der Targets zuständig ist, wird der absolute Pfad in dieses Feld eingetragen. In diesem Fall ist das C:\Development\Application\grails-1.0-RC4\bin\grails.bat
    Working Directory
    Da alle grails Kommandos im Wurzelverzeichnis eines Projektes abgesetzt werden, muss hier der absolute Pfad zum aktuellen Project-Root gesetzt werden. Um die Konfiguration etwas generischer zu gestalten, lassen wir Eclipse den Pfad des aktuell selektierten Projekts eintragen. Dazu genügt die folgende Variable: ${project_loc}
    Arguments
    Im Beispiel der create-domain-class müssen folgende Argumente übergeben werden: create-domainclass ${string_prompt:the new domain class} Das erste Argument (create-domainclass) ist der Aufruf des Targets, das zweite Argument erzeugt ein Popup indem man die Domain-Klasse angibt. Ein zusätzliches Argument in der Variable ${string_prompt} manipuliert den Abfragedialog, sodass der Nutzer weiss was er angeben muss.

    External Tools Configuration

  3. Speichern der Konfiguration
    Nach dem Selektieren eines Grails-Projektes kann man über das Icon “External Tools Dialog” die Konfiguration abrufen. Es erscheint die Aufforderung zur Eingabe einer neuen Domain und anschließend wird in der Eclipse-Console der entsprechende Aufruf angezeigt. Mithilfe dieses Verfahrens lassen sich nun leicht auch andere Targets konfigurieren und von der Eclipse IDE aus starten.
Fehlermeldungen

Falls beim Ausführen eines Targets der Fehler Error starting Sun’s native2ascii ausgegeben wird, so kann dies zwei Ursachen haben:

  1. Die JAVA_HOME Variable verweist nicht auf das JDK sondern die JRE, eine Änderung des Pfadverweises sollte hier Abhilfe schaffen
  2. In manchen Fällen kommt diese Meldung auch bevor man initial grails dev package auf der Konsole ausgeführt hat

Kommentar Feed Trackback URL

Tag Cloud

Unsere Themen

Kommentare

  • SharePoint_Team: Rückblick zum Treffen der .NET Usergroup Dresden am 24.02.2010: im #Communardo #Techblog...
  • TorstenHu: Rückblick zum Treffen der .NET Usergroup Dresden am 24.02.2010: im #Communardo #Techblog...
  • SharePoint_Team: Neuer Blogpost zur #BastaCon im #Communardo #TechBlog: http://tinyurl.com/yjqyqpb This comment was...
  • SharePoint_Team: Nur noch etwa 1 Stunde, dann beginnt die .NET Usergroup… http://bit.ly/dxDoKg This comment was...
  • SharePoint_Team: RT @TorstenHu: ViS is waiting for an operation oder Warum Copy & Paste schlecht ist: #Communardo...

Twitter