Integrationtests with Groovy’s HTTP Builder

The HTTP Builder for Groovy simplyfies the creation and handling of HTTP requests. It is a wrapper around the Apache HttpClient adding a closure based API which increases readablitity and brevity.

I started to use the HTTP Builder in integration tests. Let’s take a look:

void test_myPage_shouldRedirectToLogin() {
  def baseURI = "http://servername"
  def httpBuilder = new HTTPBuilder(baseURI)
  // Make sure that HttpClient doesn't perform a redirect
  def dontHandleRedirectStrategy = [
    getRedirect : { request, response, context -> null},
    isRedirected : { request, response, context -> false}
  ]
  httpBuilder.client.setRedirectStrategy(dontHandleRedirectStrategy as RedirectStrategy)

  // Execute a GET request and expect a redirect
  httpBuilder.request(Method.GET, ContentType.TEXT) {
    req ->
      uri.path = '/webapp/de/de/myPage'
      response.success = { response, reader ->
        assertThat response.statusLine.statusCode, is(302)
        assertThat response.headers['Location'].value, startsWith("${baseURI}/webapp/login")
      }
      response.failure = { response, reader ->
        fail("Expected redirect but received ${response.statusLine} \n ${reader}")
      }
    }
  }

There are different overloaded versions of the request method. In the example I just use the variant which requires the HTTP Method and the expected content type. In the following configuration closure the request uri path is defined as well as the success and the failure closure. The failure closure will be executed when the status code is greater or equal than 400. Otherwise success will run. Each closure will be called with a HttpResponse object and a reader representing the response body.

Normally the Apache HttpClient will handle redirects transparently, but for this test I wanted to check if the redirect was correctly sent. So I created a new implementation of the RedirectStrategy interface using Groovy’s as operator.

HTTP Builder uses the Content Type to apply response parsing. When application/json is given, then the HTTP Builder will use the JsonSlurper to create a Map from the JSON content. For text/html the HTTP Builder provides a reader (as seen in our example).

In summary HTTP Builder is a convenient and easy to use HTTP framework. The resulting code is much more readable than when the Apache HttpClient is directly used.

Posted in Groovy | Comments Off

HTTP 2.0 and Domain-Sharding

HTTP 2.0 (which is based on SPDY) improves latency and throughput through multiplexing of requests and responses onto one single TCP connection. The header and the data of one request/response cycle is represented by a stream which will be divided into several frames. Streams can have different priorities so that critical resources for rendering (e.g CSS files) can be sent earlier than lower prioritized resources (e.g. images).

The following figure shows an example of a HTTP 2.0 connection flow which multiplexes 6 streams:


       | --> [6] --------[5]-[5]-> | 
Client |                           | Server
       | <-- [1] [4] [2] [4] [2]-- |

Advantages of multiplexing

The multiplexing reduces perceived latency and allows constructs like server push of resources. In addition the browser doesn't have to open up several TCP connections for one origin. With HTTP 2.0 only one TCP connection per origin is needed. As a result only one connection is affected by the TCP "slow start" algorithm. (TCP connections speed up if the network is capable enough, see TCP Congestion Control). The TCP connection will be long-lived and so it is likely that it will reach its full speed (more precisely: its maximum congestion window size).

Domain sharding still useful ?

The Domain sharding technique was used to maximize the amount of parallel TCP connections. Most browers open up six TCP connections per origin. With domain sharding this limit can be increased. But due to the multiplexing technique of HTTP 2.0 this performance optimization doesn't make sense for a HTTP 2.0 connection. It actually might decrease performance on a HTTP 2.0 connection, because the browser has to perform additional DNS requests and manage more TCP connections.

Further reading:

Posted in HTTP | Comments Off

Halbwertszeit von Wissen

Ein spannender Aspekt an der Software-Entwicklung ist die ungeheure Vielfalt an Konzepten, Technologien und Frameworks. Interessierte Software-Entwickler sind ständig dabei, Dinge neuzulernen, vorhandenes Wissen skeptisch zu validieren, und veraltetes Wissen (oder Ansichten) explizit “zu vergessen”.

IT-Wissen hat unterschiedliche Halbwertszeiten. Nehmen wir als Beispiel die Beherrschung der BlackBerry-API: Diese API ist an ein Produkt gebunden. Wenn das Produkt komplett auf eine neue Basis umgestellt wird oder gar stirbt, ist das vorhandene Wissen bzw. die Erfahrung mit der API auf einmal wertlos. Das gleiche gilt beispielsweise auch für Browser-“Optimierungen” (a.k.a Hacks) im Frontendbereich. Frontend-Entwickler, die sich bestens mit IE6 oder IE7-Hacks auskannten, können diese Informationen getrost vergessen, da das Produkt (der Internet Explorer 6,7) einfach nicht mehr relevant ist.

Das Einzige, was vom “Produkt”-Wissen bleibt, sind Konzepte, Strukturen und Ideen, die sich auf andere Gebiete übertragen lassen und die Fähigkeit, Probleme zu analysieren und schnell Lösungen zu finden.

Abseits von der Produktwelt ist das Wissen beständiger. Nehmen wir die HTTP-Spezifikation: HTTP 1.1 gibt es schon seit 1997, und wird wohl noch eine Weile bestehen (Auch wenn Google mit SPDY die Vorlage zu HTTP 2.0 geliefert hat). Von daher lohnt es, die Spezifikation wirklich komplett durchzuarbeiten, sofern man irgendwas mit Internet zu tun hat.

Andere Klassiker sind z.B. die 1989 veröffentliche Bash-Shell oder der wohl ewig nutzbare Vim-Editor. Wer sich da wirklich einarbeitet, kann Jahre davon profitieren.

Die Halbwertszeit von Wissen ist eine wichtige Variable bei der Zusammenstellung des eigenen “Knowledge-Portfolios“. Fundiertes Produkt-Wissen ist natürlich für die tägliche Arbeit unerlässlich, es darf aber nicht das Einzige sein, was man in das Portfolio übernimmt. Sehr wichtig ist es, Wissen mit langer Halbwertszeit zu identifizieren und so das eigene Portfolio langfristiger zu gestalten.

Posted in Business | Comments Off

Mein Artikel “Android goes Gradle” in der Java aktuell

In eigener Sache: Heute ist die Ausgabe 2-2013 des Java Aktuell-Magazins erschienen. Zu dieser Ausgabe durfte ich den Artikel “Android goes Gradle” beisteuern. Der Artikel stellt die frühe Betaversion des zukünftigen Android-Buildsystems auf Basis von Gradle vor.

Viel Spaß bei der Lektüre.

Titelblatt des Java aktuell Magazins

Posted in Mobile | Comments Off

Spass mit Websphere – Teil 2: DEBUG-Logs

Ich hatte heute morgen wieder Spass mit einer Besonderheit des Websphere Application Servers 7: In dem standardmässigen SystemOut.log werden nie DEBUG-Messages ausgebeben.

Der Websphere Application Server 7 leitet ALLE Log4j-Logmessages unterhalb von INFO in das trace.log (IBM/WebSphere/AppServer/profiles/AppSrv01/logs/server1/trace.log) um. Man kann in der eigenen log4j.xml konfigurieren, was man möchte (z.B. eigene File-Appender), es wird alles in das trace.log umgeleitet.

Das trace.log kann über die Admin-Konsole zumindestens konfiguriert werden:

Websphere Trace.log Konfiguration

Posted in Infrastruktur, Webapplikation Workout | 1 Comment

JSP-Tagfiles: Praktische Fragmente

JSP-Tagfiles ermöglichen die Wiederverwendung von Markup-Schnipseln. Sie können einfach mit Attributen parametrisiert werden. Bereits in früheren (JEE)-Projekten habe ich Tagfiles gerne eingesetzt. Was ich aber bis zum aktuellen Projekt noch nicht genutzt habe, waren die sog. Fragmente: Mit ihnen lassen sich mehrere JSP-Schnipsel gleichzeitig an ein Tagfile übergeben. Innerhalb des Tagfiles kann dann über <jsp:invoke> die interpretierte Ausgabe des Fragments eingebettet werden. Das nachfolgende Beispiel zeigt ein vereinfachtes Grid-Tag, das zwei Fragmente (main und sidebar) anbietet.

/WEB-INF/tags/grid.tag

<%@ tag description="The basic two column grid" pageEncoding="utf-8"
%><%@ attribute name="main" fragment="true"
%><%@ attribute name="sidebar" fragment="true"  
%>
<section>
   <div class="size3of4">
      <jsp:invoke fragment="main"/>
   </div>
   <div>
      <jsp:invoke fragment="sidebar"/>
   </div>
</section>

Aufruf des Tagfiles mit Übergabe von Fragmenten
Die zu übergebenden Fragmente werden durch <jsp:attribute/>-Blöcke definiert.

<%@ page contentType="text/html; utf-8"  pageEncoding="utf-8"
%><%@ taglib prefix="t" tagdir="/WEB-INF/tags"
%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"
%><%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt"
%>
<t:grid>
   <jsp:attribute name="main">
      <h2><fmt:message key="resultlists"/></h2>
      <%-- further content for main --%>				
   </jsp:attribute>
   <jsp:attribute name="sidebar">
      <h2><fmt:message key="addons"/></h2>
      <%-- further content for addons --%>
   </jsp:attribute>
</t:grid>

Standardmässig werden die übergebenen Fragmente beim Aufruf mit <jsp:invoke> direkt in die Response geschrieben. Alternativ kann der Output des Fragments in eine Variable gespeichert werden. Dazu wird muss das var-Attribut von <jsp:invoke> gesetzt werden.

Posted in Webapplikation Workout | Comments Off

Gradle direkt von Eclipse debuggen

Momentan stellen wir ein Maven-basiertes Java-Projekt auf das Buildsystem Gradle um. Wichtig dabei ist, dass von Maven bekannte Komfortfunktionen weiterhin genutzt werden können: Dazu gehört auch das schnelle Starten eines lokalen Tomcats ohne vorherige manuelle Installation. Analog zum maven-tomcat-plugin gibt es für Gradle das gradle-tomcat-plugin. Sollte man (trotz hoher Testabdeckung) in die Verlegenheit kommen, einen Debugger verwenden zu müssen, gibt es zwei Möglichkeiten:

  1. Den Debugger an die JVM anhängen, die über den Aufruf von “gradle” auf der Konsole gestartet wurde.
  2. Die JVM mit Gradle direkt aus Eclipse zu starten.

Lösung 2 ist definitiv vorzuziehen, da der Debugger wesentlich performanter agiert. Aber wie starte ich Gradle in einer eigenen JVM direkt aus Eclipse ? Ganz einfach: In dem Jar gradle-launcher-1.2.jar befindet sich die Main-Klasse org.gradle.launcher.GradleMain.

Diese Klasse können wir in Form einer eigenen Launch-Konfiguration verwenden:
Main-Klasse für Eclipse Launch-Konfiguration

Die gewünschten Gradle tasks übergeben wir in den Program arguments:
Liste mit gradle tasks

Bevor wir starten, müssen wir noch zwei JARs zum Classpath hinzufügen:

  • gradle-launcher-1.2.jar
  • gradle-core-1.2.jar

Classpath-Konfiguration

Nach Klicken auf Run können wir die Ausgabe von Gradle in einer Eclipse Console betrachten, und mit dem Debugging beginnen.
Ausgabe von Gradle

Nice.

Posted in IDE, Java, Webapplikation Workout | Comments Off

Apache Tomcat’s URIEncoding

Bei einem Refactoring einer Webapplikation hatte ich ein HTML-Formular von HTTP-POST auf GET umgestellt, da eine idempotente Suchanfrage ausgelöst wird. Allerdings traten bei Suchbegriffen mit Umlauten unschöne Encoding-Fehler auf:

Kaputte Umlaute durch fehlerhaftes Encoding

“Endlich mal wieder ein Encoding-Problem” denke ich, und beginne mit einem UTF-8-Schnellcheck:

UTF-8-Schnellcheck

  • Content-Type HTTP-Header korrekt gesetzt ? Ja.
    Content-Type: text/html; utf-8;charset=utf-8
    
  • Meta-Tag gesetzt ? Ja.
    <meta content="text/html; charset=utf-8" http-equiv="content-type">
    
  • Default-Encoding der JVM ?
    Ausgabe von Charset.defaultCharset() ? Ist UTF-8.

Alles schien in Ordnung zu sein, aber warum wurde der Suchbegriff falsch encodiert ? Bei der Analyse mit dem Debugger zeigte sich, dass bereits der CGI-Parameter vom Tomcat falsch encodiert wurde.

Die Ursache: URIEncoding-Attribut des Apache Tomcats
Wenn im Connector das URIEncoding-Attribut nicht gesetzt wird, dann verwendet der Tomcat eben das ISO-8859-1 Encoding. Normalerweise würde man jetzt die server.xml anpassen. Allerdings starten wir unsere Entwicklungsinstanzen mit dem maven-tomcat-plugin. In diesem Fall trägt man in der pom.xml einfach folgendes Attribut ein:

<maven.tomcat.uriEncoding>UTF-8</maven.tomcat.uriEncoding>

Fertig. Und schon wieder ein Encoding-Problem weniger.

Posted in Schei₸ Encoding | Comments Off

XCode – Nachträgliche Konfiguration von Application Tests

Beim Anlegen eines neuen Projektes kann XCode 4.3 auf Wunsch ein Unit-Test Bundle erzeugen. Die Option dazu heisst Include Unit Tests. Die so angelegten Unit-Tests werden in der Menüleiste unter Product > Test oder alternativ über den Shortcut cmd-U angestossen. XCode startet die zu testende App im Simulator und führt die Unit-Tests aus. Apple nennt diese Form der Tests Application Tests; ich würde sie eher Integration Tests nennen. Um eine ältere App nachträglich mit Application Tests zu versehen, müssen einige manuelle Schritte ausgeführt werden. Als Beispiel soll eine App namens AppWithoutTests dienen, die ich ohne die Include Unit Tests-Option angelegt habe.

1. Erzeugen eines Cocoa Touch Unit Testing Bundles

  • Klick auf File > New > Target ...
  • Auswahl des Cocoa Touch Unit Testing Bundle
  • Eingabe eines Product Names (z.B. Application Tests) und Klick auf Finish

2. Aufräumen der Schemes
XCode hat nun das Testing Bundle erzeugt, jedoch hat es ein weiteres Scheme angelegt. Für die Entwicklung ist das umständlich, da man für die Ausführung der Tests immer das Scheme wechseln muss. Von daher löschen wir das neu angelegte Scheme und erweitern das bisherige Standard-Scheme.

  • Klick auf Product > Manage Schemes ...
  • Löschen des automatisch angelegten Scheme ApplicationTests
  • Hinzufügen des ApplicationTests Bundles im Test-Target des Standard-Schemes (im Beispiel AppWithoutTests).

3. Testing Bundle: Bundle Loader und Testhost
Noch sind wir nicht fertig. Wir müssen die Wirts-Applikation in den Bundle Settings unseres Testing Bundles selbst konfigurieren.

  • Zunächst setzen wir den Pfad des Bundle Loader auf die unsere kompilierte App, also $(BUILT_PRODUCTS_DIR)/<app_name>.app/<app_name>. Für unsere Beispielapp müssen wir den Pfad auf $(BUILT_PRODUCTS_DIR)/AppWithoutTests.app/AppWithoutTests setzen.
  • Anschliessend setzen wir den Test Host auf den soeben konfigurierten Bundle Loaders. Dazu geben verwenden wir die Variable $(BUNDLE_LOADER).

4. Testing Bundle: Setzen der Target Depedencies
Die Abhängigkeit unsers Testing Bundles zu dem Application Target müssen wir selbst hinzufügen, so dass sichergestellt ist, dass immer zuerst die App, und dann die Tests kompiliert werden.

  • Klick auf die Build Phases unseres Testing Bundles
  • Klick auf Plus-Symbol in der Sektion Target Dependencies
  • Auswahl des Application Targets (Im Beispiel AppWithoutTests).

5. Application Target: Symbols hidden by default abschalten
Die zu testende Applikation darf die kompilierten Methoden und Klassen nicht verstecken. Ansonsten scheitert der Linker im Testing Bundle, weil er die importierten Klassen nicht findet.

  • Dazu müssen wir sicherstellen, dass die Option Symbols Hidden by Default in unserem Application Target AppWithoutTests” auf NO gesetzt ist.

Mit diesen (leider sehr umständlichen) Schritten können nun Application Tests für unsere AppWithoutTests ausgeführt werden. Im nächsten Blogeintrag geht es um die so genannten “Logic Tests”, also Tests, die keine Wirts-Applikation benötigen.

Posted in iOS, Test | 1 Comment

Good Webservice Design

Was zeichnet eigentlich einen guten Webservice aus ? Hier eine Liste von Anforderungen, die ein guter Webservice erfüllen muss.

1. Versioniert
Webservices ändern sich. Im Idealfall kommen nur neue, optionale Attribute hinzu, ohne dass ältere Clients kaputt gehen. Bei umfangreicheren Umstrukturierungen ist dies aber nicht der Fall: Die neue Version ist nicht mehr rückwertskompatibel. Hier muss sowohl die alte und die neue Version des Webservice eine Zeit lang parallel betrieben werden. Von daher muss die Version in die URL des Webservice mit aufgenommen werden (z.B. http://api.stackexchange.com/2.0/tags?order=desc&sort=popular&site=stackoverflow).

2. Zustandslos
Ein Webservice darf keine Session-Ids oder gar Cookies einsetzen. Lesende Requests sollten unabhängig von einander ausgeführt werden können; eine bestimmte Reihenfolge darf nicht vorgegeben sein.

3. Verständlich auch ohne Dokumentation
Methodennamen und Parameter sollten nicht kryptisch sein. Beispiel: Die Bedeutung von totalHits ist verständlicher als die von th. Zwar werden bei der kürzeren Variante ein paar Bytes eingespart, aber auf Kosten der Verständlichkeit. Wie Bytes besser eingespart werden, zeigt der nächste Punkt.

4. Kompakt
Der Webserver sollte die GZIP-Komprimierung anbieten. Des weiteren sollte der Webservice auch JSON zurückgeben, um das Parsen für die Clients zu erleichtern und die Datenmenge zusätzlich zu reduzieren.

5. Im Browser testbar
Jeder Webservice muss eine Testseite zur Verfügung stellen, auf der alle Requests und Parameter ausprobiert werden können. Beispiele dafür:

Testseiten erleichtern das Erlernen des Webservices und ermöglichen den schnellen Test unabhängig von irgendwelchen Tools. Gute Testseiten können sogar eine separate Dokumentation ersetzen.

6. Auskunftsfreudig bei Fehlern
Es ist ziemlich frustrierend, wenn der Webservice bei syntaktisch falschen oder fehlenden Parametern einfach nur eine Standardfehlermeldung zurückgibt. Wichtig ist, dass der Webservice mitteilt, was genau schief gelaufen ist. Beispiel:

{
  "error" : { 
    "name" : "missing_parameter",
    "description" : "parameter 'lang' is missing"
  }
}

Des Weiteren muss der Server bei einem Fehlerfall auch den HTTP-Code korrekt setzen. Bei clientseitigen Fehlern sollte der Server einen HTTP 400 (Bad Request) schicken, bei serverseitigen Fehlern dagegen einen HTTP 500 (Internal Server Error). Dies erleichtert das Cachingverhalten und die Fehlerbehandlung auf Seiten des Clients.

7. Konsistent
Parameternamen sollten über alle Methoden hinweg identisch benannt werden. Ansonsten muss der Client diese Inkonsistenzen abfangen, was die Client-Implementierung wieder aufwändiger macht.

Posted in Webapplikation Workout | 4 Comments