Mar 22

Ich habe ein paar Stunden dafür verwendet mein auf Google Code gehostetes Projekt grum auf den Stand der Dinge zu bringen (es wurde ja auch langsam Zeit). Grum ist eine kleine Grails Anwendung zur Benutzerverwaltung, die es mir ermöglicht mit dem Web Framework Grails “zu spielen”.

Ich habe bei der Umsetzung bewusst auf die vielen Grails Plugins verzichtet, um so wenig Seiteneffekte wie möglich zu haben und es auch für diejenigen einfach zu halten, die einen Einstieg in Grails suchen. So sind in Grum Lösungen enthalten, wie man z.B.:

  • den Zugriff auf eine Mysql Datenbank realisiert
  • 1:1, 1:n und n:m GORM Beziehungen modelliert
  • eigene Tag Libs schreibt
  • die JSP Tag Lib displaytag verwendet, um die Daten seitenweise anzuzeigen, zu gruppieren, zu sortieren und in alle möglichen Formate (excel, csv, xml, pdf) zu exportieren
  • den Upload von Dateien ermöglicht
  • funktionale Tests mit dem webtest Plugin verwendet
  • und die Auslieferung von XML aufgrund von besonderen URL’s (kurz Content Negotiation) umsetzt

Die neue Version 0.3 verwendet jetzt grails 1.2.1 und das Plugin webtest in der Version 2.0.3. Die Sourcen, die SQL Dateien zur Erstellung der Mysql Datenbank und ein Webarchiv mit allen notwendigen Bibliotheken stehen auf Google Code zum Download bereit.

Nutztungshinweise:
Der Code kann frei verwendet werden, kann aber Fehler enthalten, für die ich keine Haftung übernehme. Die Lizenzbedingungen der verwendeten Bibliotheken sind einzuhalten.

Ähnliche Artikel:

geschrieben von gklinkmann \\ tags: , , , ,

Mar 09

Dass meine Beiträge für die Kategorie weekly links eine Zeit lang pausiert haben, lag auch daran, dass mich das Kopieren der Links ziemlich genervt hat.

Was macht man also als Programmierer, wenn der Leidensdruck hoch genug ist – man liest eine API (in diesem Fall die von delicious.com), nimmt die Programmiersprache seiner Wahl (bei mir Groovy) und schafft Abhilfe.

Der Urvater der online Lesezeichenverwalter delicious.com stellt eine REST basierte API bereit. Groovy bietet mit dem Modul HTTPBuilder ein mächtiges Tool, dass einem die Arbeit mit HTTP basierten Resourcen extrem erleichtert.

Nach einer erfolgreichen Authentifizierung und einer gültigen Anfrage erhält man eine XML Antwort, die so aussehen könnte:

1
2
3
4
5
6
7
8
9
10
<posts tag="" user="user">
  <post href="http://www.weather.com/" description="weather.com"
  hash="6cfedbe75f413c56b6ce79e6fa102aba" tag="weather reference"
  time="2005-11-29T20:30:47Z" />
    ...
  <post href="http://www.nytimes.com/"
  description="The New York Times - Breaking News, World News & Multimedia"
  extended="requires login" hash="ca1e6357399774951eed4628d69eb84b"
  tag="news media" time="2005-11-29T20:30:05Z" />
</posts>

Testen kann man erst einmal auf der Kommandozeile mittels curl:

> curl https://user:passwd@api.del.icio.us/v1/posts/recent

Bestimmte URL’s wie z.B. posts/all sollte man nicht zu oft aufrufen, da sie limitiert sind. Macht man es doch (wie ich) erhält man den Fehler 999. Besser ist es da nur die letzten Einträge (per Default 15) über posts/recent anzufragen. Das ganze Programm sah dann bei mir so aus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import groovyx.net.http.* 
import groovy.util.slurpersupport.GPathResult 
 
class DeliciousBookmarkClient {
 
   static main(args) {
      def dc=new DeliciousBookmarkClient()
      dc.request()
   }
 
   public request () {
      try {
         // Authentifizierung
         def rc = new RESTClient( 'https://username:password@api.del.icio.us/v1/posts/recent' )
         rc.auth.basic "username", "password"
 
         // anfragen und überprüfen der Antwort   
         def resp=rc.get("count":"5")
         assert resp.status == 200
         assert ( resp.data instanceof GPathResult )
 
         def recentPosts=resp.data.post
         println "Anzahl posts "+recentPosts.size()
 
         // HTML Aufbereitung des Links und der Beschreibung
         println "<dl>"
         recentPosts.each{post->
            def desc=post.@description.text()
            def href=post.@href.text()
            println "   <dt><a href=\"$href\">$desc</a></dt>"
            println "      <dd>$desc</dd>"
         }
         println "</dl>"
      } catch (e) {
         println e.response.status
         println e.message
      }
   }   
}

Über die API lassen sich natürlich auch Lesezeichen hinzufügen und löschen. Das gilt auch für Tags und Tag Bundles. Damit bleiben keine Wünsche offen.

Ähnliche Artikel:

geschrieben von gklinkmann \\ tags: , ,

Mar 05

Wer sich nicht erst seit Grails mit Webanwendungen auf Java Basis beschäftigt, dem dürfte die JSP Taglib displaytag ein Begriff sein.

Displaytag ermöglicht es ohne große Klimmzüge Tabellen in Java Server Pages auf mehrere Seiten aufzuteilen (Paging), zu sortieren, zu gruppieren und nach Excel, Csv, Xml und Pdf zu exportieren.
Grails unterstützt “out of the box” nur das Paging und lange Zeit konnte man keine JSP Tag Libs in Grails verwenden, so dass man die restlichen Funktionalitäten entweder durch Plugins abbilden konnte oder selbst Hand anlegen musste.

Seit Grails 1.1 ist diese Beschränkung nun aufgehoben und der Test die beiden zu vereinen ist schon seit längerem erfolgreich abgeschlossen. Nur der Blog Eintrag darüber steht seit dem noch auf meiner ToDo Liste. Aber was lange währt wird gut (hoffe ich :-) ).

Folgende Schritte sind zur Integration von displaytag in Grails notwendig:

libs

Zuerst sollten die Displaytag Bibliotheken neben dem Datenbank Treiber ins lib Verzeichnis kopiert werden.

Displaytag Konfigurationsdatei

Die Konfigurationsdatei von displaytag displaytag.properties muss unter src/java erstellt werden. Der Aufbau dieser Datei ist in der Doku von displaytag beschrieben. Für mein grum Projekt sieht die Konfiguration so aus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
export.types=csv excel xml pdf
export.excel=true
export.csv=true
export.xml=true
export.pdf=true
export.excel.class=org.displaytag.export.excel.DefaultHssfExportView
export.pdf.class=org.displaytag.export.DefaultPdfExportView
export.rtf.class=org.displaytag.export.DefaultRtfExportView
export.banner=<div class="exportlinks">Export to: {0}</div>
export.amount=list
paging.banner.placement=bottom
basic.msg.empty_list=No data found.
basic.msg.empty_list_row=<tr class="empty"><td colspan="0">No data found.</td></tr></tr>
paging.banner.full=<span class="pagelinks"><a href="{1}"><strong>&lt;&lt;</strong></a>&nbsp;&nbsp;&nbsp;<a href="{2}"><strong>&lt;</strong></a>&nbsp; {0} &nbsp;<a href="{3}"><strong>&gt;</strong></a>&nbsp;&nbsp;&nbsp;<a href="{4}"><strong>&gt;&gt;</strong></a></span>
paging.banner.first=<span class="pagelinks"> {0} &nbsp;<a href="{3}"><strong>&gt;</strong></a>&nbsp;&nbsp;&nbsp;<a href="{4}"><strong>&gt;&gt;</strong></a></span>
paging.banner.last=<span class="pagelinks"><a href="{1}"><strong>&lt;&lt;</strong></a>&nbsp;&nbsp;&nbsp;<a href="{2}"><strong>&lt;</strong></a>&nbsp; {0} </span>
paging.banner.one_item_found=<span class="pagebanner">1 Record found. Seite: </span>
paging.banner.all_items_found=<span class="pagebanner"> {0} Records found. Seite: </span>
paging.banner.some_items_found=<span class="pagebanner"> {0} Records found, show {2} - {3}. </span><br /><br />

Displaytag Wrapper

Dynamische Links und Formatierungen werden in displaytag über das Decorator Pattern umgesetzt. Der Decorator wird in einer Wrapper Klasse implementiert, die in Grails natürlich in Groovy geschrieben ist. Meine Implementierung ist die Klasse DisplaytagWrapper, die im grum Projekt einen Link zu den Details der Benutzer erstellt und das Erstellungsdatum formatiert.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package de.koo.grum.groovy.util
 
import org.displaytag.decorator.TableDecorator;
 
public class DisplaytagWrapper extends TableDecorator{
   String getLinkToUser() {
      def user = getCurrentRowObject()
      return "<a href=\"/grum/user/show/${user.id}\">${user.username}</a>";
   }
   String getUserCreatedAt() {
      def user = getCurrentRowObject()
      return user.createdAt.format("dd.MM.yyyy HH:mm");
   }
}

Export Filter

Beim Export in ein nicht HTML Format muss der content type für die Antwort an den Browser neu gesetzt werden. Damit dies nicht zu Problemen führt, sollte ein Filter in der web.xml Datei definiert werden, der möglichen Fehlern entgegenwirkt. Displaytag bringt mit der Klasse ResponseOverrideFilter bereits eine Implementierung dafür mit.

Um in Grails Änderungen an der web.xml vornehmen zu können, müssen die Templates installiert werden:

grails install-templates

Danach befindet sich die web.xml im Verzeichnis src/templates/war. Für den Filter sind folgende Einträge notwendig.

1
2
3
4
5
6
7
8
<filter>
   <filter-name>ResponseOverrideFilter</filter-name>
   <filter-class>org.displaytag.filter.ResponseOverrideFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>ResponseOverrideFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

Einbindung in Groovy Server Page

Hat man diese ganzen vorbereitenden Schritte absolviert, kann man sich endlich an die Verwendung von displaytag in einer Groovy Server Page machen.
In meinem Beispiel user/list.gsp werden alle Benutzerdaten tabellarisch angezeigt. Die Tabelle ist durch das Attribut sortable nach Vor- und Nachnamen sortierbar (ohne erneuten Datenbankzugriff) und wird beim Erreichen der pagesize über das Attribut partialList auf mehrere Seiten verteilt.

1
2
3
4
5
6
7
8
9
10
11
12
13
<%@ taglib uri="http://displaytag.sf.net" prefix="display" %>  
<html>
..
<display:table name="userList" defaultsort="1" partialList="true" 
      decorator="de.koo.grum.groovy.util.DisplaytagWrapper"
      size="${resultSize}" pagesize="${pageSize}" requestURI="/grum/user/list"
      class="listing" cellpadding="0" cellspacing="0" sort="list">
   <display:column property="linkToUser" title="Userame" />						
   <display:column property="firstname" title="Firstame" sortable="true"/>						
   <display:column property="lastname" title="Lastname" sortable="true"/>						
   <display:column property="userCreatedAt" title="Created At" sortable="true"/>						
</display:table>
...

Über zusätzliche Attribute (export, group) kann wie im Beispiel contactData/list.gsp auch der Export in die verschiedenen Ausgabeformate und eine Gruppierung der Einträge erreicht werden.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<display:table name="contactDataList" export="true" defaultsort="1" partialList="true" 
      decorator="de.koo.grum.groovy.util.DisplaytagWrapper"
      size="${resultSize}" pagesize="${pageSize}" requestURI="/grum/contactData/list"
      class="listing" cellpadding="0" cellspacing="0" sort="list">
    <display:setProperty name="export.csv.filename" value="contactData.csv" />
    <display:setProperty name="export.excel.filename" value="contactData.xls" />
    <display:setProperty name="export.xml.filename" value="contactData.xml" />
    <display:setProperty name="export.pdf.filename" value="contactData.pdf" />
    <display:setProperty name="export.amount" value="list" />
 
    <display:column property="linkContactDataToUser" title="Name" sortable="true" group="1"/>						
    <display:column property="type" title="type" sortable="true" />
    <display:column property="data" sortable="true" />
</display:table>

Fazit:
Einmal konfiguriert ist displaytag eine der tollsten Lösungen für java basierte Webanwendungen um Daten tabellarisch aufzulisten. Der Funktionsumfang übertrifft dabei weit die Standard Funktionalität von Grails. Die Kombination von Grails und displaytag kann ich daher nur jedem empfehlen.

Links:
grum Quellcode

Ähnliche Artikel:

geschrieben von gklinkmann \\ tags: , , ,

Jan 14

Als Administrator sollte man beim Anlegen von Benutzern Passwörter wählen, die nicht gerade 123456 heißen. Da aber auch die Fantasy eines Administrators begrenzt ist, lässt man sich am besten eines generieren.
Eine Groovy Klasse für einen Passwort Generator könnte so aussehen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class PasswortGenerator{
   public static void main(def args){
      def availChars = []  
      ('A'..'Z').each { availChars << it.toString() }  
      3.times { (0..9).each { availChars << it.toString() } }  
 
      def generateRandomString = { length ->   
        def max = availChars.size      
        def rnd = new Random()  
        def sb = new StringBuilder()  
        length.times { sb.append(availChars[rnd.nextInt(max)]) }  
        sb.toString()  
      }   
 
      10.times { println generateRandomString(8) }   
   }
}

Quelle: www.chrisrauber.com

Noch einfacher geht es natürlich, wenn man den Inhalt der main Methode in der Groovy Shell ausführt.

Ähnliche Artikel:

geschrieben von gklinkmann \\ tags: , ,

Jan 08

Still und leise ist sie dahergekommen. Wie viele andere Groovy Projekte (Groovy 1.7, GPars 0.9, Gant 1.9) ist auch für Grails pünktlich zur Groovy&Grails Exchange eine neue Version erschienen. Die finale Version 1.2 hat lange auf sich warten lassen.

Eine stabile Version sollte es werden. Das war der Grund für die lange Beta und RC Phase. So basiert Groovy 1.2 auch noch auf der Groovy Version 1.6.7.

Zur neuen Version hat Dierk König (Author von Groovy in Action) einen ausführlichen Artikel geschrieben, so dass an dieser Stelle nur eine kurze Liste neuer Funktionen folgt:

  • Deklarative Abhängigkeiten für Bibliotheken innerhalb von Grails Anwendungen
  • Schnellere Sichten – Performancesteigerungen für Groovy Server Pages (GSP)
  • GORM defaults werden konfigurierbar
  • Named queries, die auch als Selektionsbasis für die dynamischen Finder Methoden dienen können
  • Ausbau, der eh schon sehr guten REST und JSON Unterstützung
  • die Grails documentation engine kann auch für andere (nicht auf Grails basierende) Anwendungen genutzt werden
  • Update auf Spring 3
  • fein granular konfigurierbare DataSources
  • erweiterte Unterstützung von annotierten Entities
  • Tomcat als Default Servlet Container. Andere Servlet Container wie z.B. Jetty werden ebenfalls unterstützt.

Die komplette Liste der Änderungen könnt Ihr im Change Log und den Release Notes nachlesen.

Grails 1.2 steht auf der Projektseite zum Download bereit. Für bestehende Grails Anwendungen reicht wie immer ein

grails upgrade

Der Sprung von Version 1.1 auf 1.2 ist nicht so groß, wie der von Version 1.0 auf 1.1. Von daher sind bis jetzt nur wenige Probleme bekannt.

Ähnliche Artikel:

geschrieben von gklinkmann \\ tags: , , ,