Monthly Archives: November 2010

Mit Grails einen EAN-13 Code im PDF rendern

Kommt ja ab und an vor, dass ein PDF Dokument erstellt werden soll, das u.a. einen maschinenlesbaren Code enthält. Z.B. ein Barcode. Ich habe mich gestern in der Grails-Plugins Landschaft umgesehen. Auf anhieb fand ich das Rendering Plugin, mit dem es u.a. möglich ist PDF’s aus XHTML zu erzeugen. Nach anfänglichen Schwierigkeiten mit den Abhängigkeiten, habe ich eine Konstellation gefunden, die für mich funktioniert hat:

   ... 
  <dependency>
      <groupId>org.xhtmlrenderer</groupId>
      <artifactId>core-renderer</artifactId>
      <version>R8</version>
    </dependency>
    <dependency>
      <groupId>com.lowagie</groupId>
      <artifactId>itext</artifactId>
      <version>2.0.8</version>
    </dependency>
    <dependency>
      <groupId>net.sf.barcode4j</groupId>
      <artifactId>barcode4j</artifactId>
      <version>2.0</version>
      <exclusions>
        <exclusion>
          <groupId>xml-apis</groupId>
          <artifactId>xml-apis</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
   ...

Ich habe Abhängigkeiten zu XHTML Renderer, iText und Barcode4j definiert. Die Idee ist ganz einfach:

  1. Einen EAN-13 Barcode als Bild erzeugen und in dem Images Verzeichnis ablegen, das dem Webserver zugänglich ist.
  2. Ein GSP Template schreiben, aus dem später das PDF erzeugt wird
  3. In der GSP das Barcode Bild verlinken
  4. PDF rendern

Schritt 1

Das Rendering Plugin installieren: mvn grails:install-plugin -DpluginName=rendering und einen PdfController erstellen.

Schritt 2

Eine Methode schreiben, die mit Hilfe von Barcode4j einen Barcode erzeugt und in eine Datei unter web-app/images ablegt

class PdfController {
  static DPI = 600
  ...
 
  /**
   * Erstellt einen neuen Barcode und legt in die Datei ab
   *
   * @param code Der EAN Code
   * @param file Die Zieldatei
   */
  private void createBarCode(code, File file) {
    def bean = new EAN13Bean(fontSize: 3.0, barHeight: 6)
    bean.doQuietZone(false);
    bean.moduleWidth = UnitConv.in2mm(6.0f / DPI)
 
    file.withOutputStream { out ->
      def canvas = new BitmapCanvasProvider(out, "image/x-png", DPI, BufferedImage.TYPE_BYTE_BINARY, false, 0);
      bean.generateBarcode(canvas, code);
      canvas.finish();
    }
  }
}

Um mit Barcode4j einen bestimmten Barcode Typen zu erzeugen, instanziiere ich die entsprechende Bean. In diesem Fall EAN13Bean aber natürlich sind auch andere möglich – z.B. 2-dimensionalle. Mit dem BitmapCanvasProvider wird der Barcode erzeugt und in den OutputStream der Datei geschrieben.

Schritt 3

Eine Methode schreiben, die ein Barcode Bild erzeugt und lokal speichert, wenn es noch nicht existiert und anschließend eine URL liefert, die über dem Webserver zugänglich ist.

class PdfController {
  static LOCAL_PATH = "${new File("").absolutePath}/web-app/images/barcodes"
  ...
 
  /**
   * Liefert eine öffentlich zugängliche URL zu dem Bild,
   * das den übergebenen Code als Barcode darstellt.
   *
   * @param code Der EAN-13 code
   * @return Die URL zu dem erzeugten Barcode
   */
  private def asImageUrl(code) {
    if (!code || code.size() != 13) {
      throw new IllegalArgumentException("EAN 13 code not given or length is not 13: $code")
    }
 
    def filename = "${code}.png"
    def file = new File("${LOCAL_PATH}/${filename}")
    if (!file.exists()) {
      createBarCode(code, file)
    }
 
    resource(dir: 'images/barcodes', file: filename)
  }
 
  ...
}

Schritt 4

Eine GSP schreiben, die den Barcode als Bild einbindet.

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
  <head>
    <style type="text/css">
    @page {
      size: A4;
    }
    </style>
  </head>
  <body>
    <div>
      <img src="${barcode}" alt="Barcode" width="200px"/>
    </div>
  </body>
</html>

Letzter Schritt

Die PDF rendern und dem Client schicken

class PdfController {
  ...
  def index = {
    def ean = "9781590599952"
    def target = asImageUrl(ean)
    renderPdf(template: "/pdfs/barcode", model: [barcode: target], filename: "barcode.pdf")
  }
  ...
}

Webserver starten, im Browser die URL des Controllers eingeben (http://localhost:8080/CONTEXT/pdf/index) und es sollte ein PDF geladen werden, das ein Barcode als Bild enthält:bildschirmfoto-2010-11-16-um-100623

Die Verweiblichung unserer Gesellschaft

Heute morgen habe ich nano auf 3sat geschaut; einen Bericht mit dem Titel Spermien in Gefahr.
Demnach lässt die Qualität der Spermien zu wünschen übrig.

Bei einem Drittel der Männer ist sie so eingeschränkt, dass es länger dauerte, bis die Paare schwanger werden.

Und dafür gibt es einige Gründe auf die wir (in)direkt Einfluss haben. Das eine Frau während der Schwangerschaft das Rauchen sein lassen sollte, ist nichts Neues. Leider ist es bei vielen nicht angekommen und so schädigen sie bereits in der Schwangerschaft die Hoden ihrer Ungeborenen Jungen.

Dann spielt unsere Ernährung eine große Rolle. Unsere Lebensmittel kommen mit Verpackungen in Kontakt, in denen Weichmacher verarbeitet wurden. Manche Weichmacher wirken wie Östrogen und stören dabei die Testostäron-gesteuerten Abläufe im männlichen Körper. Ein Blick bei Google offenbart einige Presseberichte wie Plastikflaschen machen weiblich. Das Thema ist also nicht neu. Dabei sind Weichmacher allgegenwärtig. Sie sind in unserem Haushalt, in unserem Essen, Trinkwasser, und sogar in der Hausstaub-Luft.

Als dritter Grund wird Fettleibigkeit angeführt. Als heute Morgen mein Radiowecker anging, vernahm ich als erstes Franky’s Stimme von FFN, der meinte das 60% aller Männer in Niedersachsen Übergewicht haben. Das Bauchfett speichert und gibt Östrogen frei, das ebenfalls den Hormonhaushalt der Männer beeinflusst.

Die Folge davon ist, dass unsere Gesellschaft verweiblicht. In dem nano-Bericht wurde ein Forscher gezeigt, der Kaulquappen im Wasser züchtet, das Weichmacher enthält – so wie z.B. unser Trinkwasser. Dabei dominiert das weibliche Geschlecht auffallend. Und was im Tierreich funktioniert, kann auch bei uns ähnlich aussehen.

Android und Grails über JSON miteinander sprechen lassen

Ist eine Weile her seit meinem letzten Eintrag 🙂 Gestern habe ich mich mit einem Kollegen über die Kommunikation zwischen einer Android App und einem Grails-Backend unterhalten. Ich freue mich immer über eine Herausforderung, also habe ich ein kleines Projekt aufgesetzt, das dieses Problem löst.

Das Command-Pattern ist eines meiner liebliengs-Entwirfsmuster. Es eignet sich hervorragend zum Bau von Schnittstellen zwischen zwei unterschiedlichen Systemen. In diesem Fall zwischen Grails (serverseitig) und Android (clientseitig). Der Vorteil des Command-Patterns ist, dass es wunderbar mit dem Open/closed principle harmoniert. Denn die Schnittstelle umfasst, platt gesagt, einen Service mit einer execute Methode, die einen Request bekommt und einen Response liefert. Wie die konkreten Implementierungen der einzelnen Request/Response Paare aussehen, ist nicht wichtig, die Schnittstelle bleibt die Selbe.

Die Funktionsweise ist wie folgt:

  1. Auf der Android-Seite wird eine Anfrage in Form einer Action erzeugt und an einen asynchronen Service übergeben.
  2. Dieser Service serialisiert die Anfrage nach JSON und schickt die Nachricht per POST zum Server.
  3. Auf Server Seite wird die Nachricht deserialisiert und an einen synchronen Service übergeben, der damit was anzufangen weis.
  4. Die Antwort serialisiert der Server ebenfalls nach JSON und schickt sie zurück.
  5. Auf Android Seite wird die Antwort deserialisiert und das Callback des asynchronen Service aufgerufen.

Dies ist nichts Revolutionäres und funktioniert so oder so ähnlich in einigen Projekten. Ich möchte nun mit dem Code konkret werden. (Mir fehlte die Fantasie für einen tollen Namen, also habe ich das Projekt MDI – mobile data interface – genannt) Um das alles beisammen zu halten, habe ich ein neues Maven Projekt mit drei Modulen aufgesetzt:

...
  <groupId>de.fivews.mdi</groupId>
  <artifactId>mdi</artifactId>
  <packaging>pom</packaging>
  <version>0.1</version>
  <modules>
    <module>core</module>
    <module>server</module>
    <module>android</module>   
  </modules>
...

Wichtig ist in dem server– und android-Modul eine Abhängikeit zu dem core-Modul zu definieren.

...
  <dependency>
      <groupId>${pom.groupId}</groupId>
      <artifactId>core</artifactId>
      <version>0.1</version>
    </dependency>
...

Core – gemeinsame Code-Basis

Das erste Modul core ist das umfangreichste und bildet die Schnittstelle zwischen der Client-App und dem Server. (Ich habe die Bezeichner Action, Result und ActionHandler an das Dispatch Modul in GWT angelehnt.)
bildschirmfoto-2010-11-03-um-181627

In diesem Modul sind Interfaces und Klassen definiert, die sowohl auf der Client- als auch für die Serverseite genutzt werden. Das Result Interface wird von allen Beans implementiert, die ein Ergebnis enthalten, das für den Client bestimmt ist.

public interface Result extends Serializable {}

Analog zu dem Result gibt es das Action Interface. Dieses Interface sorgt für zweierlei.

  1. Die Bindung an einen bestimmten Result. Es wird von der konkreten Implementierung vorgegeben, von welchem Typ das Ergebnis sein muss.
  2. Die getResultClass-Methode liefert die Klasse des Results. Wir werden später sehen, dass ich den Typen benötige, da die Generics mir zur Laufzeit nicht weiter helfen.
public interface Action<T extends Result> extends Serializable {
  public Class<T> getResultClass();
}

Weiter geht es mit dem ActionHandler. So ein Handler ist jeweils für ein Action/Result Pärchen verantwortlich. Mit anderen Worten, nimmt ein Handler eine bestimmte Action entgegen, macht irgendwas damit und liefert ein bestimmtes Result-Objekt. Zu jedem Action/Result Paar gibt es genau einen ActionHandler. Es ist sinnvoll für jede Action gleich einen Mock-ActionHandler zu implementieren, der per Dependency Injection in eine Testumgebung eingebunden werden kann. Zudem liefert die getActionClass-Methode die konkrete Klasse der Action, für die der Handler verantwortlich ist. Auch dazu später…

public interface ActionHandler<A extends Action<R>, R extends Result> {
 
  /**
   * Handles an action and returns the appropriate result
   *
   * @param action The action to handle
   * @return The result of the action
   * @throws Exception If an action could not be executed
   */
  public R execute(A action) throws Exception;
 
  /**
   * @return The class of the action this handler is responsible for.
   */
  public Class<A> getActionClass();
}

Nun benötigen wir eine Instanz, die darüber entscheidet, welche Action, von welchem ActionHandler bearbeitet wird. Dafür habe ich mir den Dispatcher ausgedacht. Der Dispatcher führt eine interne Liste über die verfügbaren ActionHandler und delegiert jede Action zu dem entsprechenden Handler, sofern denn einer verfügbar ist.

public interface Dispatcher {
 
  /**
   * Executes an action and returns the result
   *
   * @param action The action to execute
   * @param <R> The result type
   * @param <A> The action type
   * @return The result
   * @throws DispatchException If an action raises an exception
   */
  public <R extends Result, A extends Action<R>> R execute(A action) throws DispatchException;
}

Passend dazu existiert auch eine asynchrone Variante für den Client. (Es ist nichts ärgerlicher als eine blockierende UI.) Der Unterschied liegt in der Rückgabe des Ergebnisses. In der Asynchronen Variante wird das Ergebnis(oder der Fehler) in einem Callback zurück gegeben.

public interface AsyncDispatcher {
  /**
   * Executes an action and returns the result
   *
   * @param action The action to execute
   * @param callback The callback with the result
   * @param <R> The result type
   * @param <A> The action type
   */
  public <R extends Result, A extends Action<R>> void execute(A action, AsyncCallback<R> callback);
}

Zu guter letzt habe ich auch noch einen konkreten Anwendungsfall modelliert und zwar die Abfrage nach der Schnittstellen-Version.

// GotVersion.java
public class GotVersion implements Result {
  private Version version;
  ...
}
 
// GetVersion.java
public class GetVersion implements Action<GotVersion> {
  public Class<GotVersion> getResultClass() {
    return GotVersion.class;
  }
}
 
// MockGetVersionHandler.java
public class MockGetVersionHandler implements ActionHandler<GetVersion, GotVersion> {
 
  public GotVersion execute(GetVersion action) throws Exception {
    return new GotVersion(new Version("1.0"));
  }
 
  public Class<GetVersion> getActionClass() {
    return GetVersion.class;
  }
}

Damit ist die Arbeit an der Schnittstelle fürs erste abgeschlossen. Die Erweiterung findet durch die Implementierung von jeweils Action + Result + ActionHandler statt. Danach zähle ich die Version in der pom.xml hoch, installiere das Modul in meinem Maven Repository und damit steht es dem Server und Client zur Verfügung.

Server – Grails

Der Server ist eine Grails Anwendung. Damit die Kommunikation mit dem Client funktioniert muss ich drei Dinge tun:

  1. Einen Dispatch Service implementieren
  2. Dem Dispatch Service alle Handler mitgeben
  3. Einen Controller implementieren, der die JSON Nachricht verarbeitet und an den Dispatch Service delegiert.

Die Implementierung der Dispatcher Schnittstelle ist denkbar einfach. Es wird eine Liste der verfügbaren ActionHandler im Konstruktor erwartet. Sie werden in einer Map auf die Klasse der Action abgebildet, für die der ActionHandler verantwortlich ist. Wird die execute-Methode aufgerufen, sucht sich der Service den passenden Handler raus und delegiert den Aufruf.

class DispatchService implements Dispatcher {
  def handlers = [:]
 
  def DispatchService(handlerList = []) {
    handlerList.each { handler ->
      handlers.put(handler.actionClass, handler)
    }
  }
 
  Result execute(Action action) {
    def handler = handlers.get(action.getClass())
    if (handler == null) {
      throw new DispatchException("Handler not found for action class " + action.getClass())
    }
 
    try {
      return handler.execute(action)
    }
    catch (Exception e) {
      throw new DispatchException(e)
    }
  }
}

Die zu verwendenden ActionHandler konfiguriere ich über die config/spring/resources.groovy

beans = {
 
  /**
   * The service that delegates the action requests to the responsible handler instances.
   * To extend the service, just instantiate a new handler bean and put it in the list 
   */
  dispatchService(DispatchService, [
          new MockGetVersionHandler()
  ])
}

Schließlich ist der Controller zu implementieren, der die JSON Nachricht verarbeitet. Da aus dem JSON String nicht erkennbar ist, welche Action gerade übertragen wird, schickt der Client den voll qualifizierten Klassen Namen als Parameter mit. Ich kenne keine Bibliothek, die so einfach wie GSON funktioniert, wenn es um die (De)serialisierung von JSON Daten geht. Um eine Action zu deserialisieren, benötigt GSON die konkrete Klasse der Action. Diese lädt der Controller über Class.forName()

package de.fivews.mdi.server.controller
 
import com.google.gson.Gson
 
class DispatchController {
  static packagePrefix = "de.fivews.mdi"
  def dispatchService
  def gson = new Gson()
 
  /**
   * Interface entry point for mobile data requests.
   * Expects the following parameters:
   * - a The full qualified action class name
   * - d The JSON data that will be transformed into an instance
   *     of the action class
   */
  def index = {
    /* Action package must start with de.fivews.mdi */
    if (params.a && !params.a.startsWith(packagePrefix)) {
      render(text: gson.toJson(new Error(error: 'action not supported')))
    }
    /* Is JSON data given? */
    else if (!params.d) {
      render(text: gson.toJson(new Error(error: 'data missing')))
    }
    /* Prerequisites are given. Continue processing... */
    else {
      try {
        def actionClass = params.a ? Class.forName(params.a) : null
        /* Is action name given? */
        if (!actionClass) {
          render(text: gson.toJson(new Error(error: 'action missing')))
        }
        /* Process request and returns the result as JSON text */
        else {
          render text: processRequest(params.d, actionClass)
        }
      }
      catch (Exception e) {
        /* Don't show too much information */
        render(text: gson.toJson(new Error(error: "unexpected error")))
      }
    }
  }
 
  /**
   * Handles the given JSON payload by decoding the action and executing
   * the action request. The result will be encoded as JSON and returned
   *
   * @param data The JSON payload
   * @param actionClass The action class of the JSON payload
   * @return The result as JSON
   */
  private def processRequest(d, actionClass) {
    def action = gson.fromJson(d, actionClass)
    def result = dispatchService.execute(action)
    gson.toJson(result)
  }
 
  /**
   * An instance of this class will be returned if an error is raised 
   */
  private static class Error {
    def String error;
  }
}

Sobald der Request im index-Closure angekommen ist, überprüft der Controller ob die Daten (params.d) und der Klassen-Name(params.a) der Action die Voraussetzungen erfüllen. Wenn nicht, erzeugt er eine Fehlermeldung. Soweit alles passt, lädt der Classloader mit Class.forName() die Klasse der Action und der Controller deserialisiert mit Hilfe von GSON die Nachricht in die entsprechende Action. Der Dispatcher delegiert die Action an den verantwortlichen ActionHandler und liefert das Ergebnis an den Controller, der das Ergebnis wieder nach JSON serialisiert und an den Client liefert. Puhh 🙂

Client – Android

An dieser Stelle ist die Arbeit schon fast erledigt. Auf der Clientseite ist es ratsam eine asynchrone Variante des Dispatcher's zu nutzen. So wird die Anwendung nicht blockiert. Meine Android-Activity sieht deshalb wie folgt aus:

...
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
 
    // URL = "http://localhost:8080/server/dispatch"
    final AsyncDispatcher dispatcher = new HttpAsyncDispatcher(URL, new DefaultHttpClient());
    dispatcher.execute(new GetVersion(), new AsyncCallback<GotVersion>() {
      public void onSuccess(GotVersion result) {
        Log.i(TAG, "result = " + result);
      }
 
      public void onError(Throwable throwable) {
        Log.e(TAG, "throwable = " + throwable, throwable);
      }
    });
  }
...

Nichts Spektakuläres… Eine neue Instanz der HttpAsyncDispatcher Klasse erzeugen und die GetVersion-Action abfeuern. Sobald der Server eine Antwort schickt, ruft der Dispatcher eine der beiden Methoden im AsyncCallback auf. Zu guter letzt die Implementierung des asynchronen Dispatchers:

public class HttpAsyncDispatcher implements AsyncDispatcher {
  private final BlockingQueue<Runnable> queue;
  private final ThreadPoolExecutor executor;
  private final HttpClient client;
  private final String url;
 
  public HttpAsyncDispatcher(String url, HttpParams params) {
    this(url, new DefaultHttpClient(params));
  }
 
  public HttpAsyncDispatcher(String url, HttpClient client) {
    /* The queue contains all tasks this dispatcher should handle */
    this.queue = new LinkedBlockingQueue<Runnable>();
    /* A thread pool for processing the tasks in the queue */
    this.executor = new ThreadPoolExecutor(2, 6, 10000, TimeUnit.MILLISECONDS, queue);
    /* Server target url */
    this.url = url;
    /* An instance of org.apache.http.client.HttpClient */
    this.client = client;
  }
 
  public <R extends Result, A extends Action<R>> void execute(final A action, final AsyncCallback<R> callback) {
    /* Creates a new Task and add it to the queue */
    executor.execute(new Runnable() {
      public void run() {
        try {
          /* The action and data parameters that will be processed by the server */
          final List<NameValuePair> params = new ArrayList<NameValuePair>();
          params.add(new BasicNameValuePair("a", action.getClass().getName()));
          params.add(new BasicNameValuePair("d", new Gson().toJson(action)));
          final UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "UTF-8");
 
          /* Create the post request an set the message payload */
          final HttpPost post = new HttpPost(url);
          post.setEntity(entity);
 
          /* Executes the request and wait for the response */
          final HttpResponse httpResponse = client.execute(post);
          final String content = EntityUtils.toString(httpResponse.getEntity());
          /* Decode the json request and execute the callback */
          final R result = new Gson().fromJson(content, action.getResultClass());
          callback.onSuccess(result);
        }
        /* In case something went wrong */
        catch (Exception e) {
          callback.onError(e);
        }
      }
    });
  }
}

Da der Aufruf auf dem HttpClient synchron abläuft, habe ich mir überlegt einen Thread Pool zu nutzen und die auszuführenden Aufgaben in eine Queue zu schreiben, die vom Thread Pool abgearbeitet wird. (Was genau in dem Service passiert, bitte ich den Kommentaren im Quelltext zu entnehmen.)

Fazit: Allgemein bin ich mit meiner Lösung zufrieden. Einmal geschrieben, kann sie schnell erweitert werden. Auch ist sie nicht besonders komplex. Was einwenig Disziplin erfordert ist das Design der Beans, die zwischen Client und Server ausgetauscht werden. Es gibt keine Saubere Möglichkeit zyklische Beziehung zwischen einzelnen Objekten in JSON abzubilden. Deshalb würde ich persönlich mit eher flachen Strukturen arbeiten und keinen komplexen Objektgraphen übertragen. Das ist natürlich von Fall zu Fall unterschiedlich, aber ich muss bedenken, dass ich mit JSON keine Referenzen auf Objekte übertragen kann und ein doppelt referenziertes Objekten u.U. zwei mal erzeugt wird. Damit kann das Objekt auf der Clientseite 2x existieren.