Subcategories: Java, Android, Sicherheit
maven-release-plugin and git fix
After hours of trying and wondering why my release scripts suddenly stopped working, I found out that maven-release-plugin seems to have an issue with git on recent systems. If you invoke mvn release:prepare and find out that the release process just runs against the current SNAPSHOT instead of the release version, you likely stumbled upon bug MRELEASE-812.
The reason for this issue seems to be that mvn release:prepare parses the output of git status. However the status is localized in recent versions of git, and maven-release-plugin fails to parse the localized output.
The coming fix will probably use git status --porcelain, which returns a machine-readable output. However, for the time being
LANG='en_US.UTF-8' mvn release:prepare
is a valid workaround.
TomTom für Android: ein erster Eindruck
Relativ spät betritt nun auch TomTom die Bühne der Car Navigation für Android. Bei Google Play stehen verschiedene Versionen zur Verfügung, derzeit zum Einführungspreis. Für uns interessant ist TomTom D-A-CH für 35 Euro, TomTom Western Europe für 45 Euro und TomTom Europe für 60 Euro. Wie hoch die regulären Preise sein werden, konnte ich nicht herausfinden.
Im Preis nicht inbegriffen ist der Verkehrsservice HD Traffic und eine Radarfallen-Datenbank, diese können in der App auf Monats- oder Jahresbasis nachgekauft werden. Im Preis inbegriffen sind allerdings kostenfreie Kartenupdates für die gesamte Lebensdauer der App, so die Beschreibung bei Google Play:
FREE Lifetime Maps. Always drive with the latest map and get to your destination faster. Download 4 or more full updates every year for the life of your app.
Problematisch ist derzeit allerdings, dass die Anforderungen an die Display-Auflösung sehr restriktiv sind und sich daher nur wenige Geräte überhaupt für die Installation eignen. Später sollen aber weitere Auflösungen unterstützt werden.
Was lange währt, wird also endlich gut? Ich habe mir TomTom Western Europe für mein HTC Desire HD gekauft und mit meinem alten TomTom XL IQ Routes-Navigationsgerät aus dem Jahr 2009 verglichen. Hier ein erster Eindruck.
hibernate3-maven-plugin fails with Java 1.7
If you’re using Maven’s hibernate3-maven-plugin for creating a DDL file from your entities, you might encounter the following error when using Java 1.7:
Execution default of goal org.codehaus.mojo:hibernate3-maven-plugin:2.2:hbm2ddl failed: An AnnotationConfiguration instance is required
The reason seems to be a broken JRE detection in the Mojo code, which mistakenly assumes that Java 1.7 does not support annotations. However, I haven’t checked that in depth.
The fix is pretty easy. In the plugin configuration of the hibernate3-maven-plugin, add an implementation property to the componentProperties like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>hibernate3-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<componentProperties>
<implementation>annotationconfiguration</implementation>
</componentProperties>
</configuration>
</plugin>
This enforces the use of an AnnotationConfiguration instance.
Designlektüre
Als Web-Entwickler mit technischem Hintergrund weiß man mit HTML und CSS umzugehen. Man beherrscht die Werkzeuge, um eine Website zusammenzubauen, im Schlaf. Und trotzdem kann das Ergebnis unbefriedigend sein. Die Farben harmonieren irgendwie nicht so recht, das Layout wirkt wie zusammengewürfelt, die Schriftart hat man schon tausendmal gesehen, und die Seite ist überhaupt zu textlastig. Kurzum: Der ganze Auftritt wirkt strunzlangweilig, vollgefrachtet, kunterbunt oder einfach unprofessionell. Was dann fehlt, ist ein gutes Webdesign. Und das kann man lernen!
The Principles of Beautiful Web Design schließt genau diese Lücke. Jason Beaird geht in einem leicht verständlichen und angenehm zu lesenden Englisch auf die Themen Layout, Farbgestaltung, Textur, Typografie und Bebilderung ein. Dabei richtet er sich auch an Menschen ohne Designausbildung, die von Farbmodellen, Texturen oder Typografie noch nie etwas gehört haben.
Als Praxisbeispiel dient das Redesign einer Coupon-Website. Man erlebt Schritt für Schritt, wie professionelle Designer in Zusammenarbeit mit dem Kunden einen neuen Webauftritt erstellen, und erhält so einen kleinen Einblick hinter die Kulissen einer Webagentur.
Alleine schon die etlichen Links, die das Buch mitbringt, sind das Geld wert. Neben vielen inspirierenden Beispielen sind dies auch alle möglichen Resourcen und Online-Werkzeuge, die beim Erstellen des eigenen Webdesigns helfen. Das Spektrum reicht dabei von kostenlosen Quellen bis hin zu professionellen Anbietern, die hochwertige Materialien für einen kommerziellen Webauftritt bereitstellen.
Nach dem Lesen des Buches wird man zwar nicht über Nacht zu einem begnadeten Webdesigner, aber man weiß dann, was ein gutes und ein schlechtes Design ausmacht, und hat das Wissen, um sein Auge zu schulen, schwächen am eigenen Design zu entdecken und neue Projekte von Anfang an strukturiert anzugehen.
Das Buch richtet sich hauptsächlich an Webentwickler, die den technischen Aspekt der Website-Erstellung bereits beherrschen und nun auch den künstlerischen Aspekt erlernen möchten. Auf die Themen HTML, CSS und JavaScript wird nur sehr knapp eingegangen. Glücklicherweise, möchte ich sagen, denn das technische Fachwissen wird in unzähligen anderen Büchern bereits ausreichend abgedeckt und veraltet früher oder später. Beim Design dagegen mögen Moden kommen und gehen, die vermittelten Grundprinzipien gelten aber bereits seit Jahrhunderten.
The Principles of Beautiful Web Design ist bei SitePoint erschienen. Auf deren Website kann es auch als PDF- und Ebook-Fassung gekauft werden. Eine deutsche Übersetzung bietet der Dpunkt Verlag unter dem Titel “Gelungenes Webdesign: Die Prinzipien der Webseitengestaltung” an.
Mir persönlich gab das Buch einige Hilfe und Inspiration, um Fehler im Design der shredzone zu erkennen und zu beheben. Das neue Layout, das auf dessen Basis entstand, ist viel aufgeräumter und übersichtlicher.
Bildquelle: SitePoint-Verlag (mit freundlicher Genehmigung)
Setting a renderer on JComboBox
When setting a custom renderer to a JComboBox, the usual way is to extend a DefaultListCellRenderer and override the getListCellRendererComponent() method. However, this may lead to ugly comboboxes on some Look and Feels. As you can see on the top combobox, it is rendered considerably smaller and with the letters sticked to the left border, just by using a DefaultListCellRenderer. The Look and Feel seems to use a special renderer class for proper rendering, as it is shown in the combobox below.
A solution is to use a proxy ListCellRenderer instead, which only converts the value and then delegates the rendering to the original renderer. For example:
public class ListCellRendererProxy implements ListCellRenderer {
private final ListCellRenderer delegate;
public ListCellRendererProxy(ListCellRenderer delegate) {
this.delegate = delegate;
}
@Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
// modify the value here...
return delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
}
The renderer proxy can be used like this:
JComboBox cbx = new JComboBox(); ListCellRenderer oldRenderer = cbx.getRenderer(); cbx.setRenderer(new ListCellRendererProxy(oldRenderer));
The combobox items are now converted to a string by a custom cell renderer, but are still rendered by the original renderer implementation of the current Look and Feel. However, while a single DefaultListCellRenderer instance can be shared with many JComboBox, a new renderer proxy needs to be instanciated per combobox.
Métro endlich für Android
Eigentlich bin ich ja glücklich auf Android umgestiegen. Es gibt nur eine App meines guten alten Palm TX, die ich wirklich vermisse: Métro. Mit dem Programm kann man sich in etlichen Städten der Welt eine Route mit öffentlichen Verkehrsmitteln berechnen lassen. Auch wenn keine richtigen Fahrpläne, sondern nur Streckenpläne verwendet werden, ist die Datenbank dank des Alters von Métro sehr umfangreich und wird gut gepflegt. Mir hat Métro auf etlichen Städtetouren und auch daheim viel Zeit und Umwege erspart. Es ist einfach unverzichtbar.
Schon lange versprechen die Entwickler, auch eine Android-Version herauszubringen. Und jetzt ist es endlich soweit!
Das Tool ist allerdings noch in einem recht frühen Stadium. Ein paar Features, die ich in der Palm-Version lieb gewonnen habe, fehlen. Außerdem ist die App nicht im Market und muss direkt installiert werden. Aber das ist alles sicherlich nur eine Frage der Zeit. Métro für Android erfüllt jedenfalls schon jetzt seine eigentliche Aufgabe.
Und jetzt kann ich meinen Palm TX endlich ganz einmotten. 
PHP 5.3.7, eine Analyse
Das PHP-Entwicklerteam veröffentlichte vor wenigen Tagen die Version 5.3.7, nur um schon wenige Tage später vor deren Verwendung zu warnen. Der Grund dafür war ein Fehler in der Funktion crypt(), welche bei bestimmten Hash-Verfahren lediglich das Salt zurückliefert. Das kann dazu führen, dass nach einem Update auf PHP 5.3.7 keine Benutzer sich mehr auf einem Webauftritt einloggen können oder sich bei einer Passwortänderung nach einem Update auf eine spätere PHP-Version nicht mehr einloggen können. In PHP 5.3.8 wurde der Fehler wieder behoben.
Dieser Artikel ist der Versuch einer Analyse, wie es zu dem Fehler kam und warum er erst nach der Release bemerkt wurde.
Die PHP-Funktion crypt() ist in der Datei php_crypt_r.c implementiert. Folgender Codeausschnitt baut dort den Passwort-Hash zusammen:
memcpy(passwd, MD5_MAGIC, MD5_MAGIC_LEN); strlcpy(passwd + MD5_MAGIC_LEN, sp, sl + 1); strcat(passwd, "$");
strcat() fügt eine Zeichenkette an das Ende eines Puffers. Die Funktion gilt als unsicher, da sie nicht prüft, ob der Zielpuffer genügend Speicherplatz zur Verfügung stellt. Wird die Zeichenkette zu lang, wird der nachfolgende Speicherbereich beschädigt – ein typisches Problem bei C-Sprachen.
Aus dem Grund wurde der Aufruf durch eine sicherere Funktion ersetzt. Leider ist aber gut gemeint das Gegenteil von gut gemacht.
memcpy(passwd, MD5_MAGIC, MD5_MAGIC_LEN); strlcpy(passwd + MD5_MAGIC_LEN, sp, sl + 1); strlcat(passwd, "$", 1);
strlcat() stellt sicher, dass der Puffer nicht über sein Ende hinaus beschrieben wird. Dazu wird dessen Größe übergeben. Und genau hier lag das Problem, denn statt der Größe von passwd wurde anscheinend die Größe des zu kopierenden Textes übergeben, nämlich 1. Da passwd zu dem Zeitpunkt bereits deutlich mehr als ein Zeichen enthält, tut strlcat() genau das, was es tun soll, nämlich gar nichts. Das “$”-Zeichen wird nicht angehängt, das tatsächliche Ergebnis weicht damit von dem gewünschten Ergebnis ab.
Solch ein Fehler ist eigentlich ein Lehrbuchbeispiel für Unit-Tests, und der Kommentar zum Bugfix (Revision 315218) deutet auch an, dass ein solcher existiert:
Unbreak crypt() (fix bug #55439)
# If you want to remove static analyser messages, be my guest,
# but please run unit tests after
Tatsächlich gibt es einen Test, der die crypt()-Funktion mit bestimmten Werten aufruft und das Ergebnis mit einem erwarteten Ergebnis vergleicht. Dieser Test schlägt Alarm, wenn er ausgeführt wird.
Dass PHP 5.3.7 dennoch veröffentlicht wurde, lässt eigentlich nur einen Schluss zu: Der Unit-Test wurde nicht ausgeführt oder der Alarm wurde schlichtweg ignoriert. Spätestens beim Bau der finalen Version unmitelbar vor der Veröffentlichung hätte dies aber stattfinden müssen. Alles andere wäre grob fahrlässig.
Zusammengefasst hatte der Fehler also folgende Ursachen:
- die für C-Sprachen üblichen Probleme bei der sicheren Verarbeitung von Zeichenketten
- eine missverständliche oder nicht verstandene Dokumentation der Funktion
strlcat() - keine verbindlich vorgeschriebene fehlerfreie Ausführung der Unit-Tests vor der Freigabe einer Release
Insbesondere der letzte Punkt wiegt schwer und wirft ein schlechtes Licht auf die verantwortlichen PHP-Entwickler.
Android-Debugging unter Fedora
Eine schöne Sache an der Android-Plattform ist, dass man auch unter Linux Apps entwickeln kann. Java und die Entwicklungsumgebung Eclipse steht als fertiges Paket zur Verfügung, und bei Google können die Entwicklertools kostenlos heruntergeladen werden.
Das Testen erfolgt entweder über einen Emulator, oder man geht gleich ans Eingemachte und testet seine Anwendung auf echter Hardware. Bevor das möglich ist, muss Fedora das Smartphone bekannt gemacht werden. Dazu wird mit Root-Rechten die Datei /etc/udev/rules.d/51-android.rules angelegt und mit folgendem Inhalt versehen:
SUBSYSTEM=="usb",SYSFS{idVendor}=="0bb4",SYMLINK+="android_adb",MODE="0666"
Unter idVendor wird die jeweilige Hersteller-ID des Smartphone-Herstellers eingetragen. Eine Tabelle der Vendor IDs gibt es ebenfalls bei Google. Wenn mehrere Smartphones verschiedener Hersteller zum Einsatz kommen, können entsprechend weitere Zeilen ergänzt werden.
Als nächstes muss auf dem Android-Phone das USB-Debugging aktiviert werden. Den Menüpunkt findet man unter Einstellungen → Anwendungen → Entwicklung → USB-Debugging aktivieren.
Wenn man nun seinen Androiden per USB anstöpselt und in dem Android-SDK das Kommando
platform-tools/adb devices
aufruft, sollte das Smartphone aufgelistet werden. Es steht dann als Zielplattform für die Entwicklung zur Verfügung.
String LOBs on PostgreSQL with Hibernate 3.6
For String properties that may contain more than 255 characters, it is advised to add a @Lob annotation to the appropriate property. For example, to keep a comment text in an entity, one would write:
@Lob
public String getComment() { return comment; }
public void setComment(String comment) { this.comment = comment; }
On PostgreSQL, a large string is usually kept in a TEXT column (instead of VARCHAR). However, after updating to Hibernate 3.6, an exception was suddenly thrown when accessing such a property (along with an SQLState: 22003 from PostgreSQL):
org.postgresql.util.PSQLException: Bad value for type long : This is some text...
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.toLong(AbstractJdbc2ResultSet.java:2796)
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getLong(AbstractJdbc2ResultSet.java:2019)
at org.postgresql.jdbc4.Jdbc4ResultSet.getClob(Jdbc4ResultSet.java:43)
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getClob(AbstractJdbc2ResultSet.java:384)
... and more
Obviously, the PostgreSQL connector tried to interprete the textual content as a long integer now, which – of course – results in a failure. PostgreSQL knows two ways of storing binary large objects, either as BYTEA within the table space, or as OID in a separate place and referenced by a numerical identifier. It seems that Hibernate 3.6 suddenly treats TEXT columns like OID columns as well.
In the internet, I have found similar problems related to @Lob annotated byte[] properties. A common solution was to add a @Type annotation to the property.
An attempt to add @Type(type = “org.hibernate.type.MaterializedClobType”) did not help at all. Instead, @Type(type = “org.hibernate.type.TextType”) did the trick:
@Lob
@Type(type = "org.hibernate.type.TextType")
public String getComment() { return comment; }
public void setComment(String comment) { this.comment = comment; }
For PostgreSQL, it now works fine again, even without needing to alter the table column type. However I couldn’t check the impact of the annotation on other DBMS (like Oracle). Your feedback is welcome.
JSF2.0, mod_proxy and CSS
I stumbled upon a strange issue when I recently deployed a JSF 2.0 web application. The application was developed using Jetty, and was working fine there. However when I deployed the application on a server, the page layout was utterly broken and Firefox complained that it would not load some CSS resources because of the wrong content type application/xml+xhtml.
On the server, a Tomcat is connected to an Apache web server via mod_proxy and mod_proxy_ajp. I found out that the Tomcat itself delivered the CSS resources without a Content-Type header, but the Apache web server returned a Content-Type: application/xml+xhtml. Actually, mod_proxy always adds a Content-Type header if it is missing, and tries to guess the right content type by the file suffix.
I searched the net for a proper solution of this issue, but found none. After some experiments, a working solution was to configure the Apache web server to force the content type of all .css.xhtml files to text/css:
<LocationMatch "\.css\.xhtml$">
ForceType text/css
</LocationMatch>
However I don’t know if this is the best practice. A likely better solution would be the Mojarra Faces servlet to return a proper content type for the CSS files.
