Monthly Archives: Februar 2010

Groovy String Array ( String[] )

Habe heute was Neues über Groovy Collections gelernt. Wenn ich in Java ein mit Werten initialisiertes Array benötige, dann mache ich das wie folgt:

1
final String[] array = new String[] { "1", "2", "3" };

In Groovy werden die Collection über literale Konstruktoren erzeugt. Listen mit [] und Maps mit [:]. Dies beißt sich einwenig mit Java. Um in Groovy ein Array zu konstruieren gibt zwei einfache Wege:

1
2
3
def array = ["1", "2", "3"] as String[]
/* oder durch einen Cast */
def array = (String[]) ["1", "2", "3"]

Grails + PostGIS

Puh, habe heute einwenig gebraucht, bis auch der letzte Integrationstest lief. Das letzte Mal, als ich mit Postgresql und PostGIS gearbeitet habe, liegt nun drei Jahre her und mein Wissen ist nicht mehr so frisch. In diesem Projekt ist es nicht Ruby on Rails, sondern Hibernate und Grails.

Ich habe heute eine Funktion benötigt, die mir ausgehend von einem bestimmten Punkt, die nächst-mögliche Entität liefert. Dafür habe ich Postgresql aufgesetzt und meine Datenbanken mit den PostGIS Funktionen erweitert.

In Grails ist es erstaunlich einfach eine Domain Klasse um ein Attribut zu erweitern, das georeferenzierte Informationen speichert:

1
2
3
4
5
6
7
8
9
10
11
12
import com.vividsolutions.jts.geom.Point
import org.hibernatespatial.GeometryUserType
 
class Station {
  Point location
 
  static mapping = {
    columns {
      location type: GeometryUserType
    }
  }
}

Damit die Imports aufgelöst werden können liegen im Classpath folgende Bibliotheken: (Versionen können abweichen)

* hibernate-spatial-1.0-M2.jar
* hibernate-spatial-postgis-1.0-M2.jar
* jts-1.8.jar
* postgis-2.0.0SVN.jar
* postgresql-8.4-701.jdbc4.jar

In der DataSource.groovy muss der Dialekt angepasst werden, wodurch eine menge cooler PostGIS Funktionen dazu kommen. Dazu später mehr.

1
2
3
4
5
6
7
8
environments {
  test {
    dataSource {
      driverClassName = "org.postgresql.Driver"
      dialect = org.hibernatespatial.postgis.PostgisDialect
    }
  }
}

Jetzt geht es um die eigentliche Funktion. In meinem ersten Entwurf habe ich den Code so geschrieben, wie ich es von Grails gewohnt bin.

1
2
3
4
5
6
7
class Station {
  Point location
 
  def static findNearest(Point point) {
    Station.executeQuery("from Station order by distance(location, :p)", [p: point], [max: 1])
  }
}

Das hat nicht ganz geklappt und ich habe eine SQLException mit der Begründung You must specify a valid OGC WKT geometry type such as POINT, LINESTRING or POLYGON bekommen. Ich habe einiges ausprobiert, aber wirklich weit bin ich nicht gekommen. Aber wie heißt es schön: RTFM

Das Tutorial auf der Hibernate Spatial Seite brachte mich weiter. Im Abschnitt Spatial Queries ist ganz kurz beschrieben wie das Problem in HQL gelöst wird. Der Trick ist Hibernate mitzuteilen, dass der Wert des Referenzpunktes vom Typ GeometryUserType ist, wodurch Hibernate die Query sauber zusammenbauen kann:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Station {
  Point location
 
  def static findNearest(Point point) {
    Station.withSession {Session session ->
      final String q = "from Station order by distance(location, :point) asc"
      final Query query = session.createQuery(q)
      final Type geometryType = new CustomType(GeometryUserType.class, null);
      query.setParameter("point", point, geometryType)
      query.setMaxResults(1)
      return query.uniqueResult()
    }
  }
}

distance ist übrigens eine der vielen HQL Funktionen, die der PostGIS Dialekt mit sich bringt. In einem Post habe ich eine Liste weiterer Funktionen gefunden: dimension, srid, envelope, astext, asbinary, isempty, issimple, boundary, overlaps, intersects, equals, contains, crosses, disjoint, touches, within, relate, distance, buffer, convexhull, difference, intersection, symdifference, geomunion, extent

iPhone Transitions unter GWT

Roulette Strategies sieht zwar aus wie ein iPhone App, fühlt sich aber nicht ganz so an, weil die Transitions fehlen (Das sind die animierten Übergänge von einer View zu einer anderen). Für meine neue GWT App auf dem iPhone habe ich mir überlegt, dass die Übergänge nicht fehlen dürfen. Meine Recherche ergab, dass es einige Bibliotheken gibt, die das Verhalten implementieren. z.B. jQTouch oder iPhone UI. Was mir persönlich nicht gefällt ist der erhebliche JavaScript Anteil, den die Bibliotheken mitbringen.

Zwar verträgt sich GWT mit anderen Libs, aber die Fehlersuche ist oft mühsam, wenn es mal nicht so sein sollte. Oftmals haben die Libs Initialisierungs-Routinen, mit denen sie über Elemente des DOMs iterieren und z.B. Click-Handler überschreiben. Wenn man aber die Handler zuvor unter GWT verdrahtet hat, ist die Verwunderung groß, wen sie nicht greifen oder sich anders als erwartet verhalten.

Mein Wunsch war es Transitions nur mit GWT und WebKit Mitteln zu realisieren und ich denke, dass ich ein ganz brauchbares Ergebnis erzielt habe. Hier erstmal eine Demo. Die nächste Tage veröffentliche ich bei Google Code das Projekt und werde im nächsten Artikel genauer auf die Realisierung eingehen.

(Die Demo funktioniert nur in WebKit Browsern.)

Roulette Strategies Free

Zugegeben, die Downloadzahlen der letzten beiden Tage sind ernüchternd. Zwar habe ich mir bei einer Nischenanwendung nicht die großen Downloads ausgemalt, aber die Hoffnung stirbt zuletzt. Jetzt heisst es Marketing zu betreiben. Meine erste Maßname ist es eine freie Version rauszubringen.

Da freie Apps charakteristisch öfters geladen werden als kostenpflichtige, habe ich auf die schnelle eine kleine Einschränkung eingebaut und das Icon der App getunt. Langsam macht mir das Submitten in den AppStore richtig Spass. Einmal überwunden, wird es zur Routine.

Die freie Version kann alles, allerdings ist die Größe der Permanenz eingeschränkt. Pro Tisch können 15 Treffer hinzugefügt werden, so dass zwar die Funktion ersichtlich, aber die App eigentlich nicht zu gebrauchen ist.

Parallel schreibt mein Bruder ein paar Artikel aus der Sicht eines Roulettespielers. Es ist auch ein kleiner Screencast geplant, der ein Online-Spiel zeigt. Mein persönliches Ziel ist es, bzw. war es noch bevor ich mit der Entwicklung angefangen habe, nach 6 Monaten die 5000 Downloads zu schaffen. Mal sehen 🙂

screenshot-20100208-191136

Roulette Strategies 1.1

Heute habe ich die App um zwei Bugs erleichtert und ein neues Feature implementiert. Zu jedem Spieltisch kann man sich nun die Verteilung in Form eines hübschen Balkendiagramms ausgeben lassen. So lässt sich auf anhieb erkennen, welche Felder wie oft gespielt werden. Neben den einzelnen Felder, zeigt das Diagram auch wie oft die Dutzende, die Farben, die Geraden/Ungeraden usw. gespielt wurden. Das Update mache ich morgen fertig und reiche es zur Durchsicht ein. Wenn Apple wieder genauso schnell arbeitet, wie beim ersten mal, dann ist es Ende nächster Woche online.screenshot-20100206-192450

Part 11 – Happy End

Gestern Abend bekam ich die Nachricht, dass meine App geprüft wurde und in den App-Store darf. Eine Erleichterung. Ich hatte Angst, dass eine Webanwendung möglicherweise abgelehnt wird. Heute morgen habe die ich Vertragsinformationen ausgefüllt und kurze Zeit später sah ich das hier auf meinem Bildschirm 🙂

bildschirmfoto-2010-02-04-um-083303

Mein Experiment ist an dieser Stelle abgeschlossen und das werde ich am Wochenende mit einem 500g Steak feiern. Die nächste App ist für Mai geplant und wird nicht so eine Mini-Anwendung sein, sondern einen gewissen Anspruch erfüllen. Grails 1.2.1 und GWT 2.0 liegen schon in meinem Download-Ordner und ich bin gespannt was ich mit dem GWT UIBinder anstellen kann.

Part 10 – Fazit

Laut meinem Issue-Tracker hatte ich bis gestern Zeit die App Roulette Strategies in der Vers. 1.0 in den App Store zu stellen. Und das habe ich gemacht. Irgendwann ist es immer das erste Mal und ich habe nicht geahnt wie viele Barrieren ich im Kopf ich zu überwinden habe bis die Sache durch ist. „Hast du denn den Demo Modus abgestellt?“, „Sind die Übersetzungen sauber?“, „Vielleicht doch noch irgendwo ein Bug, den Du übersehen hast?“, „Mit dem richtigen Schlüssel signiert?“ und so weiter, und so weiter. Die ganze Prozedur hat mich bestimmt zwei Stunden gekostet. Aber wenn ich es auf morgen verschieben würde, dachte ich mir, dann wird das nichts. Also Augen zu und durch.

Als ich mein Belohnungs-Kaffee trank, habe ich mich an das Gefühl erinnert als ich meine erste iPhone App kaufte. Das war so ähnlich. Dadurch das es neu für mich war und mir diese 0,00 auf 0,01 Cent Hürde ganz besonders schwer fiel, kaufte ich die erste App erst nach vier Monaten. Aber danach im Wochenrhythmus 🙂 Einmal den Prozess kennengelernt verliert er seinen Schrecken.

Wenn die App in den Store kommt betrachte ich mein Experiment als vollständig gelungen. Ich habe nun knapp drei Monate in meiner Freizeit damit zugebracht daran zu arbeiten. Habe dabei natürlich eine Menge gelernt und das meiste davon in den vorherigen Einträgen beschrieben. Gestern Abend konnte ich vor lauter Euphorie nicht einschlafen: Habe nämlich eine neue Idee für eine App 🙂 Aber, auch wenn die Idee weiter im Kopf reift setze ich sie noch nicht um – erst wenn diese App es in den Store schafft.

Aus heutiger Sicht glaube ich einen Fehler gemacht zu haben, was das iPhone Look & Feel angeht. Meine App sieht aus wie eine native Anwendung – verhält sich aber nicht 100%-tig so. Ich bin mir nicht sicher ob das nicht vielleicht mehr zum Negativen ausgelegt wird, als wenn ich einen ganz eigenen Style gemacht hätte. Zudem wollte ich die App auch im Android-Store veröffentlichen und muss dafür sowieso die Optik anpassen. Ich denke, dass ich bei der nächste App lieber ein plattformneutrales Look & Feel wählen werde, um mir die doppelte Arbeit zu ersparen. Aber für den Moment bin ich insgesamt zufrieden und der Rest ergibt sich mit der Zeit.