Cold Water

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.

Lenovo ThinkPad X100e und Fedora 14

Nachdem die Installation von Fedora 13 auf dem Lenovo ThinkPad X100e nicht gerade besonders glatt lief, war ich sehr gespannt, wie sich Fedora 14 alias Laughlin auf dem System macht und welche Probleme zwischenzeitlich behoben wurden.

Schon beim ersten Start gab es eine positive Überraschung. Waren bei Fedora 13 noch Kernel-Optionen notwendig, um das System zu starten, fährt es nun bei Fedora 14 ohne Murren mit Plymouth hoch. Probleme gab es bei Fedora 13 außerdem mit der Steuerung der Hintergrundbeleuchtung und mit der Audioschnittstelle. Laughlin konnte auch hier punkten. Die Helligkeit lässt sich regeln, und endlich verstummen auch die eingebauten Lautsprecher, wenn man einen Kopfhörer anschließt. Das Suspend/Resume arbeitet nun ebenfalls einwandfrei, ohne dass ein Quirk notwendig ist. Das X100e geht problemlos schlafen und steht nach dem Aufwachen sofort wieder bereit.

Der für WLAN notwendige Treiber hat offenbar immer noch keinen Einzug in den Kernel erhalten, so dass es bei Fedora 14 weiterhin notwendig ist, den Treiberquelltext von Realtek herunterzuladen und selbst zu kompilieren. Hoffen wir, dass diese Schritte mit Fedora 15 der Vergangenheit angehören werden.

Eine Überraschung war, dass das Touchpad nun auch Multitouch unterstützt. Nach Installation des Pakets gpointing-device-settings konnten die entsprechenden Optionen ausgewählt werden, um zum Beispiel zum Scrollen mit zwei Fingern über das Touchpad zu wischen.

Vom fehlenden WLAN-Treiber abgesehen, zeigt sich Fedora 14 auf dem X100e von seiner besten Seite. Es macht richtig Spaß, mit dem Netbook zu arbeiten.

Flattr4j: A Java library for Flattr

The microdonation service Flattr is currently working on a REST API for accessing the flattr account. I have created a Java client called flattr4j, which makes accessing the API easier.

The client also supports the Open API and JavaScript API via a JSP taglib, as well as Maven and Spring. As long as the Flattr REST API is not public yet, you need to send a proposal to Flattr.

Have fun trying it out! Your feedback is welcome.

How to fetch a random entry with Hibernate

I recently found myself in the situation where I needed Hibernate to query a single, random entry from a table of Picture entities.

There is a simple way. Some DBMS allow to shuffle the result set by bringing the rows into a random order. For instance, in MySQL it is possible to use a query like this:

SELECT id FROM picture ORDER BY rand() LIMIT 1;

Since Hibernate delegates unknown function calls to the underlying DBMS, rand() could be used in a HQL query as well:

q.createQuery("FROM picture ORDER BY rand()").setMaxResults(1);

However this query would require MySQL, so we would sacrifice the benefit of Hibernate acting as an abstraction layer to the underlying database. HQL on the other hand does not offer a similar function.

A solution is to use the pagination technique. First we count the number of entries, and then select a random entry using setFirstResult(). With Hibernate Criteria, it would look something like this:

Criterion restriction = yourRestrictions;
Object result = null;  // will later contain a random entity
Criteria crit = session.createCriteria(Picture.class);
crit.add(restriction);
crit.setProjection(Projections.rowCount());
int count = ((Number) crit.uniqueResult()).intValue();
if (0 != count) {
  int index = new Random().nextInt(count);
  crit = session.createCriteria(Picture.class);
  crit.add(restriction);
  result = crit.setFirstResult(index).setMaxResults(1).uniqueResult();
}

restriction contains further restrictions to the result set (like only pictures that have been published). At the end, result contains a random single entry from the Picture entity, or null if the result set was empty.