Samstag, 8. Dezember 2012

Tür zu zum Talentschuppen

Wer gute Ideen in's Web bringen will, muß erst einmal aussortieren, was gute und was schlechte Idee sind. D.h. man muß leider all die schlechten auch in's Web bringen und dann aussortieren, was funktioniert und was nicht.

Alle, die nur wirtschaftlich garantiert erfolgreiches in's Web bringen, leben von denen, die vorher einmal mit Idee gescheitert sind.

Ganz in diesem Sinne hatte Google für die Google App Engine und die Goople Apps kostenlose Angebote, mit denen man schnell, einfach und ohne Risiko Idee in's Web bringen konnte. - Ja, konnte. Denn zeitgleich mit der FTD hat Google heute die kostenlose Version der Google Apps eingestellt - und damit den Weg verbaut, in der gegenwärtigen Fassung Anwendungen aus der Google App Engine mit einer eigenen Domain zu versehen.

Das bedeutet deutlich mehr, als daß man eben keine kostenlosen Mail- und Office-Anwendungen etc. für seine Domains mehr bekommt! Eigene Domains für die Google App Engine sind - und das auch jetzt noch - nur mit den Google Apps zu realisieren.

Auch der in diesem Blog beschriebene Weg, klein anzufangen, und dann im Erfolgsfall einfach wachsen zu können mit der Google Infrastruktur ist damit verbaut. Man kann keine Websites mehr erstellen, die mit - hoffentliche - innovativen, selbst programmierten Ideen - und damit ohne die fertigen Versatzstücke Blog, Sites etc. von Google - kostenlos starten und wenn es viele Teilnehmer gibt, technische wie wirtschaftlich - dann natürlich auch gerne für Google - anfangen zu fliegen.

Jetzt kann jeder für sich durchrechnen, ob die konsteplflichtigen Angebote von Google in diesem Zusammenhang einen Testbalon für die ein oder andere Sache trotzdem sinnvoll erscheinen lassen.

Hier beginnt nun erst einmal die Suche nach den alternativen, die das kostenlose Szenario - und damit auch für Projekte ohne Gewinnabsicht - wieder bedienen.

Bisher war die Rechnung wie folgt:

- Coole Idee mit Google App Engine umsetzen (kostenlos)
- Domain kaufen (Mindestpreis .de Domain 4,65€ pro Jahr)
- Google Apps für die Domain einrichten (kostenlos)

Ich geh dann mal suchen...

Update:
Mini Google-Apps gehen noch, sind aber sehr klein geworden und evtl. zeitlich nur noch begrenzt verfügbar.

Montag, 3. Dezember 2012

Singing the YUI Blues

Im Web gehört es ja zum guten Ton, spätetens seit Google die PageSpeed Tools herausgebracht hat, zusätzlich zur Kompression des HTTP-Inhaltes CSS und JavaScript zu "minifizieren" (ich sage mal lieber minimieren).

Es gehört sogar nicht nur zum guten Ton sondern bringt meßbar bessere Reaktionen in den Browsern und vermindert für Betreiber größerer Websites signifikant die Traffic-Menge. Das alte Argument, daß nachbearbeiten wäre zu CPU-belastend, gilt heute wirklich nicht mehr, wie ich an einer der größten deutschen (europäischen?) Website erfahren und messen konnte. Hier hat man eher Probleme, es nicht zu tun, da irgendwann auch GBit-Bündel von Netzanschlüssen am Kapazitätsende ist - nicht jedoch die CPUs.

Im Tangram sind natürlich alle statischen Dateien im Bereich CSS und JavaScript bereits beim Zusammenbau minifiziert und beim Ausliefern sollte der JSP/Servlet Container komprimieren - oder ein HTTP-Server davor. In der Google App Enginge erledigt das die Infrastruktur von Google auf irgendeiner Ebene für uns ebenfalls automatisch mit. (Und wenn auch die es im großen tun, ist es wohl wirklich kein Lastproblem mehr...) Für Inhalte aus dem Repository ist eine Lösung enthalten, die das CSS oder JavaScript zur Laufzeit minimiert.

Obwohl man das Minimieren dadurch mit dem Komprimieren des gesamten HTTP-Inhaltes verwechseln kann, wird es auch gerne "Kompression" genannt und ist so der Namensgeber des YUICompressors. Dieser ist - s.o. - lange im Tangram integriert, aber nie ohne Probleme, die wir hier endlich einmal nicht elegant aber funktionierend lösen müssen.

Der YUICompressor bietet sehr gute Ergebnisse, ist eigentlich einfach zu benutzen und sehr weit verbreitet. Damit wäre alle in Ordnung und erledigt, da er auch eine einfach zu benutzende Programmierschnittstelle hat, die im Tangram sowohl im Buildsystem als auch in der späteren Ausspielung zur Laufzeit genutzt wird.

Der erste unangenehme Punkt ist, daß aktuelle Versionen des YUICompressors (mindestens für mich) bisher nicht in öffentlichen Maven-Artefakt-Repositories zu finden sind und wir so mit einer nicht ganz neuen Version unterwegs sind.

Der zweite Punkt tut mehr weh: Im JAR-Archiv des YUICompressors befinden sich Klassen, die einige Klasse aus der eingesetzten JavaScript-Bibliothek - einer ebenfalls älteren Fassung von Rhino - überschreiben sollen. Das ist so natürlich eine recht dreckige Lösung, und sie funktioniert auch normalerweise nicht. Das liegt ganz einfach daran, daß im classpath ein JAR mit Namen yui... selten vor einem JAR mit Namen js... zu finden ist. Eine relativ saubere Behandlung der dreckigen Lösung wäre das umschreiben der Archive beim Zusammenbau des Tangram.

Da aber Tangram eher die möglichkeiten bestehender Software nutzen als zu viel Räder neu erfinden soll, Greifen wir lieber in den Werkzeugkasten und sehen, was unser Werkzeugbestand leisten kann.

In diesem Fall ist Gradle - endlich einmal wieder - unser Freund und bietet Möglichkeiten zur Umbenennung beim Zusammenbau. Da alle Zielsysteme den classpath alphabetisch sortiert zusammestellen, reicht es für uns aus, den YUICompressor einfach ein wenig nach vorne zu schieben. Damit sind dieselben Klassennamen immernoch zweimal im classpath vertreten, aber es wird - Erfahrung im Tangram und großen Systemen (s.o.) - nur die funktionierende Version genutzt.

Damit alle Abhängigkeiten im Buildsystem sauber formuliert bleiben, kleben wir unser Pflaster nur in den Anwendungen auf, die mit Tangram gebaut sind - nicht im System selbst.

Im Detail sieht das so aus:

Wir müssen nun den Anwendungen die genaue Version bekannt machen, die bisher nur im System einfach enthalten war:

ext.yui_version="2.4.6"

Das entsprechen JAR lösen wir aus dem automatisch zusammegestellten classpath heraus:

dependencies {
  .
  .
  .
  // To exclude original YUICompressor jar from output war
  providedCompile "com.yahoo.platform.yui:yuicompressor:$yui_version"
  .
  .
  .
}

Jetzt sind wir sowohl den YUICompressor als auch seine Dependencies los und müssen diese nun "von Hand" wieder einfügen. Da tun wir im war.doFirst Zusatz, der in Tangram-Anwendungen "traditionell" schon angepaßt ist:

war.doFirst {
  // Strange way of overwriting things - it must be the first webapp dependency
  if (configurations.webapp.dependencies.size() > 0) {
    String archiveFileName = configurations.webapp.asPath
    int idx = archiveFileName.indexOf(';')
    if (idx >= 0) {
      archiveFileName = archiveFileName.substring(0, idx)
    } // if
    println "unzipping $archiveFileName"
    ant.unzip(src: archiveFileName, dest: "$buildDir/target") 
  } // if
 
  // Missing: YUICompressor - see base system
  // It's not really that important since we don't have any
  // static Stylesheets or JavaScripts are in the examples.
  copy {
    from 'src/main/webapp'
    into "$buildDir/target"
    include '**/**'
  }
 
  // ...and to again include those YUICompressor's dependencies with a different name

  copy {
    from "$buildDir/target"
    into "$buildDir/target"
    include '**/yui*'
    rename 'yui', 'aaa-yui'
  }
  into ('') {
    from "$buildDir/target"
    include 'WEB-INF/lib/aaa-*'
    include 'WEB-INF/lib/js-*'
  }
 
  into ('') {
    from "$buildDir/target"
    exclude 'WEB-INF/lib/**'
  }
}

Hier wird die WAR-Depencency ausgepackt, ggf. statische Ressourcen minifiziert und dann alles außer den Abhängigkeiten sauber verpackt. Und das "alle außer den Abhängigkeiten" müssen wir nun wieder relativieren, da wir ja den YUICompressor aus den Abhängigkeiten entfernt hatte. Also kommt er explizit als "aaa-yuicompressor" wieder rein zusammen mit der Rhino-Bibliothek. Viola - das war's.

Was ist an der Lösung so toll? Nun, in Maven-Szenarien ist mir nichts besseren Eingefallen, als den YUICompressor unter dem albernen Namen in ein lokalen, eigenes Repository einzufügen. Würde ich das hier tun, wäre Tangram nicht mehr mit öffentlichen Maven-Artefakt-Repositories zu bauen. - Nicht gerade ein gute Idee und eigentlich auch keine für nicht öffentliche Projekte.

Sonntag, 2. Dezember 2012

OpenID - Closed Data on Google App Engine

Oder: Daten? Wer braucht schon Daten?

Relativ kürzlich hat ich in der Google App Engine mindestens für Java Anwendungen etwas recht störendes geändert.
Bisher war es immer einfach möglich, mit dem Python Werkzeug den kompletten Datenbestand aus dem Data Store der App Engine herunterzuladen oder einen kompletten Stand wieder hochzukopieren.
Solche Kopien sind für das Testen von Anwendungen lokal in meiner Welt essenziell. Es geht einfach meist nicht ohne einen wenigstens teilweisen Abzug von Produktionsdaten. Man kommt so einfach näher an Probleme heran, die man nicht entdeckt, wenn man nur auf einem zu kleinen, synthetischen lokalen Datensatz arbeitet. Außerdem zeichnet sich der Data Store in der Entwicklungsinstanz der Google App Engine als nicht gerade persistent heraus, wenn man bedenkt, daß das Verzeichnis bei jedem sauberen Build der Software eigentlich bei jedem Buildsystem gelöscht wird. Und umgekehrt kann man mit dem Werkzeug lokalen keinen Datenbestand erzeugen und als Basisdaten installieren. Dieser Weg war nie möglich, da man zwar lokal alle aus einer Datenbank einpielen konnte, sie aber nicht extrahieren konnte. - Seltsam aber dokumentiert.
Und selbst das geht nun nur noch, wenn die Anwendung nicht den OpenID Login benutzt. Dieser heißt zwar immernoch "Experimental", funktioniert aber seit geraumer Zeit sehr zufriedenstellend.
Was hat jetzt der Login mit den Datenkopien zutun? Eigentlich wenig, wäre da nicht die remote_api, die die Nutzung der Tools erlaubt hat. Diese braucht natürlich zu Sicherheit einen Login, und eben diesen Login erreicht sie nur über Google Accounts - nicht über OpenID.
Und seit kurzen kann man in der Google App Engine nicht mehr die Authentisierungsmethode umschalten.
Wege um dieses Problem herum ergeben sich aber realistisch nur für Python Anwendungen.
Schön, daß man die Daten zwischen Google Diensten hin- und herschieben kann, aber im Zweifel brauche ich vollen Zugriff auf meine eigenen Daten, nicht weil ich den Google Diensten zum Backup nicht traue oder so, sondern einfach um Anwendungen zu schreiben.
Bis das nicht wieder anders aussieht oder mir jemand einen Ausweg zeigt: Finger weg von der Google App Engine für Web-Anwendungen - also für allen, was wirklich einen Benutzerlogin braucht, es sei denn, man will ausgerechnet den selbst implementieren, was nun nicht mehr in den modernen "Mesh-Up" passen würde.

Freitag, 16. November 2012

Herbst Update

Ruhig hier gewesen in letzter Zeit. Aber es gab ja auch einige Probleme, die relativ nervig waren, und für die es keine Lösungen gab, die man mal eben aus dem Internet kopieren könnte.
JDO ist eine schöne, einfache Persistenz-Schnittstelle (Auch wenn man die Kritik an der Google Implementierung in der Google App Engine mal mit einrechnet.), aber der Enhancement Prozeß auf dem Kompilierten Code war für Tangram nicht nur eine Konzeptionelle Unschönheit.
Das wichtigste Problem damit war die mangelnde Update-Fähigkeit des Entwicklungssystems für Tangram auf neuere Java-Versionen, weil dort der JDO Enhancer nicht mehr als Compiler-Plugin funktionierte
Dafür gibt es nun eine neue Enhancement-Mimik in Tangram und allen Beispielanwendungen, die sicherstellt, daß man nicht mehr mit "aus Versehen" nicht enhancetem Code und damit ohne jede Möglichkeit die Anwendung zu benutzen auch nur einen Testlauf starten kann. Das gibt wesentlich mehr Vertrauen, daß das produzierte Ergebnis auch irgendwo sinnvoll laufen kann und nicht nur den Compiler, der ja von dem ganzen Prozeß ohnehin nichts mitbekommt, glücklich macht.
Der Compiler wurde mit den letzten Commits nach GitHub aber auch wieder ein wenig glücklicher, da ich die Warning-Levels weiter heraufgesetzt habe und in der Folge ein paar Zeilen für Sicherheit und Eleganz des Codes investiert habe. Natürlich ist der CI Server im BuildHive der cloudbees dabei eine große Hilfe, das am Ende wieder alles zusammenpaßt.
Das Aufsetzen der eigenen Umgebung für Tangram mit Eclipse wurde um ein paar lästige Schritte bereinigt, sodaß es nun endlich wieder auf zu neuen Ufern in den Anwendungen von Tangram gehen kann.

Samstag, 19. Mai 2012

BuildHive

Wer sich heute noch selbst Computer in ein Rechenzentrum stellt, kann irgendwie nicht rechnen - oder es ist sein Kerngeschäft.
Ein Stelle, wo es bisher immer sehr bequem oder notwendig war, noch detailliert auf die Server zugreifen zu können, ist der Softwaretest und -bau. Aber mit dem neuen BuildHive Dienst für Projekte auf github ist auch hier ein weitere Schritt getan, dieses auch in die Wolke zu schieben.
Natürlich ist eine Voraussetzung dafür, daß man sich standardisierter oder verbreiteter Techniken bedient. Mit Gradle, Java, Maven-Repositories etc. ist das z.B. gegeben. Erfreulich: Auch meine persönlichen Extravarganzen in Sachen Ordnerstruktur sind mit dem Build-System beschrieben und damt kein Problem. Zeitaufwand, hier einen CI-Server zu bekommen? Keine 5 Minuten!
Andere Projekte sind da viel komplizierter und überhaupt, muß man da sehr individuell vorgehen? Ich habe viel Verständnis für Individualisten und persönliche Bedürfnisse, aber nach all den Jahren in diesem Gewerbe ist es für mich ein Indikator, daß man evtl. nicht seinen Grips in diese Stelle der Software setzen sollte sondern genau hier die ausgetretenen Pfade nehmen sollte, die einem Sicherheit beim Bauen, Testen und Betriebsübergang geben. Fünf Minuten werden es vermutlich nicht sein, aber in diesem Bereich sehr schematisch vorzugehen ist eher eine Hilfe als ein Zeichen fehlender Ideen, es besser zu machen.
Der erfreuliche Nebeneffekt - und genau dafür ist so etwas ja da: Diese Umgebung deckte wieder einmal ein paar kleinere Schwächen im Code auf und regte mich dazu an, noch einmal ein Versions-Update von Gradle durchzuführen.
Schon wieder? Ja, Gradle bewegt sich mit großen Schritten auf eine ehrliche Version 1.0 zu und ließ es sich - zum Glück - nicht nehmen, noch ein paar inkompatible aber notwendig Änderungen durchzuziehen.

Dienstag, 14. Februar 2012

Noch mehr funky Groovy - und gradle blues

Rendering war ja nun schon lange nicht mehr mein Problem mit den bequemen Velocity Templates im Repository. Einiges Sites laufes ja schon damit (z.B. themen-geburtstag.de). Die URL-Formate lassen ebenfalls dort definieren, wenn man möchte, was sicherlich ein wenig schwieriger im Coding ist.
Neben dem eigentlichen Datenmodell fehlt nun noch die Action im ganzen, die ich auch gerne in's Repository verlegen würde - zumindest wieder einmal als Option, da das Verhalten doch etwas ist, was man ähnlich oft tunen will, wie das Layout.
Bisher habe ich das mit einem eigenen Satz Controller sauber lösen können, aber eben nicht so agil oder dynamisch wie die Styles und Templates.
Zumindest ist es nicht mehr meine Sicht auf moderne Web-Entwicklung, daß man einen Satz an Funktionalität fest eingebaut hat und nur noch Views darüber legt.
Und da sich am Horizont weitere Projekte abzeichen, die eher Communities als reine Websites werden sollen, bestand wieder einmal Handlungsbedarf.
Also habe ich nun den lange vorhandenen Action-Parameter bei der Link-Generierung einmal zu konsistenterem Leben erweckt (und nicht nur in der simplen Editing-Komponente verwendet) und mit zwei Annotations lassen sich nun in den LinkScheme Instanzen Methoden als Actionen markieren, die direkt über URLs angesprochen werden. Parameter-Übergabe und Resultatseiten Ansteuerung inklusive. Kommentare nach Lektüren der aktuellen Codes bitte gerne an mich.
Leider war eine Entscheidung nicht gerade förderlich (evtl. hatte ich sie deshalb beim letzte Lesen auf gradle.org auch nicht getroffen): Das update auf gradles 1.0 Milestone 7 bremst hier gerade extrem. Gut war es nur, als ich offline im Zug saß :-) Da war diese Version schneller. Ansonsten quält mich diese Version mit ewiglangen Suchaktionen nach den Dependencies. Zum glück kommt gerade Milestone 8 um die Ecke: Downloaden benutzen! Damit fühlt sich gradle wieder so gut an wie vorher :-)

Samstag, 14. Januar 2012

Neues auf der App Engine

Nachdem die letzten Monate vom Spielen mit Gradle, dem direkten Arbeiten mit einem eigenen RDBMS und dem CoreMedia CMS Adapter für tangram geprägt waren, habe ich mir nun mal wieder angesehen, was die App Engine so an Weiterentwicklungen gebracht hat.
  1. Ich vermisse immernoch das Tool zum Datastore dump und restore in der Java Version. Als lästige Konsequenz muß ich als "Nicht-Python-Entwickler" (aka Java-Entwickler, aber ich bin eigentlich nicht so festgelegt) auf noch die Python-Version installieren.
  2. Ich habe in den Release-Notes noch nichts entdeckt, das mir ein Update auf aktuellen Java-Versionen erlaubt.
  3. Es gibt anscheinend nun Google Cloud SQL - und das auch mit Google App Engine angenehme integriert. Leider konnte ich anhand der Texte noch nicht erkennen, wie das ganze mit JDO (oder JPA) zusammenspielen könnte. Die Beispiele von Webanwendungen nutzen direkt JDBC - und das in einer grusligen weise direkt in Servlets/JSP. Das ist also eher ein kleiner Scherz, der die Syntax für JDBC aufzeigt, aber nicht, was man auch nur ansatzweise in einem Hobby-Programm nutzen möchte.
  4. Es gibt keine konsistente Liste von OpenID Providern, wo man mal nachschlagen könnte, ob die Liste sich erweitert hat. Das ist recht schade, denn dieser Weg ist für mich immernoch der bevorzugte.
  5. Das neue Eclipse Plugin, das mich in seiner alten Fassung für den schneller Start doch sehr begeisterte und die Arbeit enorm beschleunigte, ist nun, nach dem Bau eines "richtigen" Build-Systems, mit dem es nicht integrierbar ist (mit Maven oder ANT wäre die Lage nicht besser), so eine Plugin eher im Bereich Spielzeug zu finden als eine Entwicklunshilfe. Professionell könnte ich es jedenfalls überhaupt nicht einsetzen.
Warum in dieser Zeit die Google App Engine den Preview Status verlassen hat, ist mir also bei dem dünnen Weiterentwicklungsstand schleierhaft. Das Thema Persistenz wird auch mit dem neuen Blob Store eher komplizierter als für die Anwendungsentwicklung besser.