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.
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.
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.
Flattr4j: Java-Library für Flattr
Der Belohnungsdienst Flattr arbeitet derzeit an einer REST API für den Zugriff auf das Flattr-Konto. Ich habe dafür eine Java-Library namens flattr4j erstellt, die den Zugriff auf die API kapselt und erleichtert.
Die Library unterstützt außerdem die Open API und die JavaScript API über eine JSP-Taglib, sowie auf Java-Seite Maven und Spring. Solange die Flattr REST API nicht öffentlich ist, ist allerdings noch eine Bewerbung bei Flattr notwendig, um die REST-Schnittstelle nutzen zu können.
Viel Spaß beim Ausprobieren! Euer Feedback ist willkommen.
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 DMBS, rand() could be used in a HSQL 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. HSQL 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.
Sun Certified Java Developer
Sun bietet verschiedene Zertifizierungen an, die die eigenen Fähigkeiten als Java-Entwickler in einem internationalen Maßstab bewerten sollen. Das “Sun Certified Java Developer”-Zertifikat bescheinigt, dass der Entwickler in der Lage ist, ein gegebenes Problem zu analysieren und unter Java-Standardtechniken daraus ein Programm zu entwickeln.
Voraussetzung für den Test ist das Bestehen des Sun Certified Java Programmers.
Dieser Test besteht nun aus zwei Teilen. Der erste Teil ist eine Aufgabe, die umgesetzt werden muss. Der zweite Teil besteht aus Fragen zu der eigenen Umsetzung.
Die gesamte Prüfung findet in englischer Sprache statt, wobei hier deutlich mehr verlangt wird, als nur einen englischen Text zu verstehen. Wer Probleme damit hat, längere Texte in Englisch zu verfassen, sollte sich das Geld besser gleich sparen. Das ist auch mein persönlicher Hauptkritikpunkt an der Prüfung. An sich sollte sie alleine die Fähigkeiten des Prüflings als Java-Softwareentwickler bewerten, aber zwangsläufig spielen so auch die Englischkenntnisse eine große Rolle in der Endnote. Englische Muttersprachler sind hier einfach im Vorteil.
Vorbereitung
Auch hier half mir die Complete Java 2 Certification Study Guide von Philip Heller (Sybex) weiter. Das Buch gibt wertvolle Tipps mit absoluter Prüfungsrelevanz. Ich empfehle außerdem die OOP-Pflichtlektüre schlechthin, die Entwurfsmuster von der berühmten Gang of Four.
Das schönste am ersten Teil der Prüfung ist aber, dass man ihn zu Hause und in aller Ruhe lösen kann!
Die Aufgabe
Nachdem man sich das Voucher für den ersten Teil gekauft hat, wird man in wenigen Tagen auf einer Test-Webseite freigeschaltet und kann sich sein Aufgabenpaket herunterladen. Es liefert die genaue Aufgabenstellung und vielleicht noch die eine oder andere dazu gehörende Datei.
Die Aufgabe ist klar und deutlich gestellt. Manche Bedingungen sind ausdrücklich ein must. Wer die nicht erfüllt, hat den ganzen Test nicht bestanden, und wenn der Rest der Lösung noch so gut ist. Es empfiehlt sich also, die Aufgabenstellung mehrmals und sehr gründlich durchzulesen. Die konkrete Aufgabe darf ich hier natürlich nicht wiedergeben, aber so viel kann ich sicherlich verraten: Ich sollte eine Swing-Applikation schreiben, die über das Netzwerk auf eine ebenfalls zu programmierende Datenbank zugreift.
Aus technischer Sicht ist diese Aufgabe für einen halbwegs routinierten Java-Entwickler problemlos zu meistern. Die Aufgabe stellte ein paar Einschränkungen, die zum Teil recht knifflig zu umgehen waren. Das ist durchaus Absicht, denn man soll auch seine Fähigkeit unter Beweis stellen, aus einer bereits bestehenden (und verkorksten) Teillösung noch das Beste herauszuholen.
Am Ende ein laufendes Programm zu haben, ist aber nur die halbe Miete. Es wird nämlich eine umfangreiche Dokumentation verlangt. Das fängt beim Quelltext an, der natürlich vernünftig formatiert, kommentiert und mit JavaDoc-Kommentaren versehen sein muss. Ebenso gehört eine kurze Benutzeranleitung dazu. Und schließlich soll man in einem Freitext schreiben, welche Probleme man bei der Umsetzung sah, wie man die Probleme löste und was für Alternativen es gab. Was ich abgab, bestand nur zu einem kleinen Teil aus Programmcode, die Dokumentation drumherum war weitaus umfangreicher.
Wenn man fertig ist, meldet man sich bei Sun, um Schreibrechte auf der Prüfungswebsite zu erhalten. Danach kann man dann sein Antwortpaket auf den Server hochladen. Man hat dabei nur einen Versuch! Wenn man auch nur eine Datei vergessen hat, muss man die (dann zum Glück ermäßigte) Prüfungsgebühr erneut bezahlen, bevor man das Paket ein zweites Mal hochladen darf.
Die Prüfung
Auf den ersten Teil folgt ein zweiter Teil, der ebenfalls absolviert werden muss. Im Gegensatz zu manchen Beschreibungen muss man nicht zuvor den ersten Teil bestanden haben. Die gesamte Prüfung wird erst dann bewertet, wenn der Prüfling beide Teile abgegeben hat. Deshalb sollte man so früh wie möglich nach Abgabe des ersten Teils einen Termin für den zweiten Teil machen, damit die eigene Lösung noch im Kopf präsent ist.
Auch für diese Prüfung muss man sich ein Voucher von Sun besorgen und mit einem Testcenter von Thomson Prometric einen Termin vereinbaren. Die Prüfung selbst dient eigentlich nur der Absicherung, dass man den ersten Teil auch selbst gelöst hat und nicht etwa nur abgeschrieben hat.
Man sitzt dafür an einem Computer und bekommt von ihm vier allgemeine Fragen zu der Umsetzung gestellt, die in einem Freitext beantwortet werden müssen. Dafür hat man insgesammt zwei Stunden Zeit.
Auch dieser Teil des Tests findet nur in Englisch und unter erschwerten Bedingungen statt. Ich tippe schon recht schnell englischen Text herunter und fand die zwei Stunden dennoch ein wenig knapp bemessen. Neben dem Zeitdruck kommt außerdem hinzu, dass keinerlei Hilfsmittel erlaubt sind, nicht einmal ein Englisch-Wörterbuch! Wer hier nicht halbwegs fit in Englisch ist, hat wohl kaum eine Chance.
Die Fragen selbst waren recht einfach und bargen wenig Überraschungen. Die Antworten hatte ich mehr oder weniger schon in der Dokumentation des ersten Teils gegeben, so dass ich sie einfach nur noch zu wiederholen brauchte. Wer sich auf den ersten Teil gründlich vorbereitet hat, braucht hier eigentlich nichts mehr zu befürchten. Wenigstens das...
Das Ergebnis
Beide Teile werden zusammen bewertet. Das heißt, der Prüfer bewertet einen erst, wenn beide Teile der Prüfung vorliegen. Das kann dann gute vier bis sechs Wochen dauern.
Die Fehlerquote ist recht gering bemessen: Von 400 möglichen Punkten muss man mindestens 320 erreicht haben, um zu bestehen. Vorausgesetzt natürlich, man patzt nicht gleich schon bei einer der must-Bedingungen.
Was es jetzt allerdings bedeutet, wenn man eine der Prüfungen nicht besteht, weiß ich nicht. Wenn man den ersten Teil nicht besteht, bekommt man die Chance, ihn gegen eine geringere Gebühr erneut einzureichen. Aber ob man dann auch den zweiten Teil wiederholen muss?
Sun Certified Java Programmer
Sun bietet verschiedene Zertifizierungen an, die die eigenen Fähigkeiten als Java-Entwickler in einem internationalen Maßstab bewerten sollen. Die grundlegendste Prüfung und zugleich die Voraussetzung für die weiteren Prüfungen ist das “Sun Certified Java Programmer”-Zertifikat.
Der Test besteht aus mehreren Multiple Choice-Fragen, die in einem Test-Center beantwortet werden müssen.
Soweit ich weiß, gibt es diesen Test mittlerweile auch in Deutsch. Trotzdem ist die Überlegung, den Test in Englisch zu machen, nicht verkehrt. Wer seine Fachliteratur in Englisch kauft, kommt dann nämlich sicher besser weg, weil ihm die Fachwörter in Englisch eher bekannt sind als in Deutsch. Ich habe mich aus dem Grund für die englische Fassung entschieden.
Vorbereitung
Man kann Seminare besuchen, die einen auf den Test vorbereiten. Man kann es aber auch lassen. Ich habe mir stattdessen das Buch Complete Java 2 Certification Study Guide von Philip Heller (Sybex) gekauft.
Das Buch besteht aus zwei Teilen. Der erste Teil ist für diese Prüfung interessant, der zweite für die Folgeprüfung, dem Sun Certified Java Developer. Der Autor gehört zum Team, das bei Sun für die Prüfungen verantwortlich ist. Dementsprechend gut ist der Inhalt. Die Kapitel gehen ganz gezielt auf die Sachen ein, die in der Prüfung drankommen. Außerdem gibt es reichlich Fragen, die Prüfungsähnlich sind und einen schon gut auf die Prüfung vorbereiten.
Von den Buch abgesehen gibt es im Internet etliche kostenlose und kostenpflichtige Webseiten mit Mockup-Tests, die man sich ebenfalls vornehmen kann. Wenn man sich nun durch den ersten Teil gearbeitet hat und die Prüfungsaufgaben aus Buch und Internet im Schlaf beantworten kann, ist man Reif für die Prüfung.
Für alle Programmiercowboys die gut gemeinte Warnung: Die Prüfung ist kein Spaziergang, selbst für Leute mit jahrelanger Praxiserfahrung nicht! Es geht wirklich um die absoluten Java-Grundlagen. Zum Teil sind die Fragen so theoretisch, wie sie sich in der Praxis nie stellen würden. Es lohnt sich also, zumindest die Mockups im Internet durchzugehen, um sich selbst zu beweisen, dass man wohl doch etwas mehr Vorbereitung brauchen wird.
Die Prüfung
Wenn du dich fit für die Prüfung hälst, kaufst du von Sun einen Voucher für die Prüfung. Das geht bequem online per Kreditkarte. Der Voucher verfällt nach einem Jahr. Man sollte also besser erst lernen und dann das Geld für die Prüfung ausgeben.
Mit der Voucher-Nummer rufst du bei Thomson Prometric an und lässt dir einen Termin in einem Prüfungscenter in deiner Nähe geben. Achte darauf, mindestens 15 Minuten vor dem Termin da zu sein und zwei Ausweispapiere mitzunehmen (z. B. Personalausweis und Führerschein).
Hilfsmittel sind für die Prüfung nicht erlaubt. Handy, Portemonnaie, aber auch das Englisch-Wörterbuch gibst du beim Empfang ab. Als einziges Hilfsmittel erhälst du eine Kunststofftafel und ein Filzstift. Und dann kann es auch schon losgehen.
Der Test findet am Computer statt. Vor dem Test kannst du ein Tutorial nehmen, das dir die Bedienung des Testprogramms erklärt. Es ist sehr empfehlenswert, das Tutorial beim ersten Mal zu nehmen. Es geht nicht von der Prüfungszeit ab, aber es erklärt, wie du Fragen beantwortest oder zur späteren Beantwortung zurückstellen kannst. An sich ist das Programm aber idiotensicher.
Der eigentliche Test besteht aus Fragen, die du in einer bestimmten Zeit entweder mit Multiple Choice oder mit einer eindeutigen Texteingabe beantworten musst. Es empfiehlt sich sehr, die Fragen in aller Ruhe und gründlich durchzulesen. Sie sind teilweise sehr theoretisch, und oft steckt der Teufel im Detail. Wenn du irgendwo festhängst, stell die Frage lieber zurück und gehe zur nächsten weiter. Die Zeit ist nicht gerade üppig bemessen, um sich zu lange an einer Frage zu verbeißen.
Wenn du alle Fragen beantwortet hast und auch die zurückgestellten durchgesehen hast, kannst du den Test beenden. Du erhälst dann direkt das Ergebnis, ob du bestanden hast oder nicht. Und ein paar Wochen später landet dann auch das offizielle Zertifikat von Sun im Briefkasten.
