I hate hibernate!

Every day another hibernate fuckup! And it is not (only) my poor understanding of it! It’s the unsufficient documentation. It’s the bad written book. It’s the arrogance of the hibernate team members in their forum. It’s the way they handle bugs. It’s their inconsistence with these two totally separated query-languages. It’s their proxy-fuckup. And i’m not alone with that perception…

How to use Apache POI HSSF – some hints

Apache POI is a java library which allows to build Office-Documents. POI stands for “Poor obsfuscation interface” and is a good description. Nonetheless it’s the only lib I know which allows you to produce what most customers still don’t want to miss: MS Excel sheets and Docs. In the following post, I want to list some hints I found in the last weeks when working on excel sheets:

– Cellstyles don’t work like normal objects: if you use a cellstyle for a cell and AFTERWARDS changes the style to use it for some other cell, you will find only the latter style in the resulting document

– Don’t mix up font definition and borders: Use the HSSFRegionUtil.setBorderXXX() for borders. This methods puts a border around the given region preserving the style (font) defined before. Keep in mind, that you have to use the method AFTER you defined the cell with a certain style.

– if you use Springs AbstractExcelView, do not just implement the excel-building code in a subclass of it. Build an abstraction layer between the Spring view and the building code to avoid dependencies to HttpRequest and HttpResponse. Otherwise testing will be painful. I defined an AbstractDocumentBuildView extending the AbstractExcelView that defines an abstract method which passes only the Workbook and the data to the implementing subclasses.

– Make a big list of constants defining the column/row-structure and labels!

– It is not possible to make “autofilters” so far! Just don’t try it.

– To put a dataFormat of your choice in a cell, use  cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat(xxx));

– HSSF is short for “Horrible SpreadSheet Format” (not kiddin’!). So just try to take it easy …

Http-Get and encoding – the technical stone age

Every day another fuckup. Today it was encoding. Somehow our excel exports did not work for cities with umlauts. MUST be an encoding thing. Interesting: It did work pretty well on Jetty, but good ol’ Tomcat throwed me broken characters in my servletrequest.

I tried javascript escape and the result was that it didn’t even work in Jetty anymore. So after proper reading (http://jira.codehaus.org/browse/JETTY-113, http://jetty.mortbay.org/jetty5/faq/faq_s_900-Content_t_International.html), I accepted that you just CANNOT put umlauts in a get-request. You are able to escape it, but there is apparently no standard how the server retranslates it. But how to do it? First idea was to post it. Post uses the given encoding and all is fine. And why not doin’ it ajaxian? Well, because it just doesn’t work. The server is building the document and returns the binary data, but what do I do then? Tried putting it in a new document, but it just doesn’t work. After a few hours and some thousand curses, I ended up writing a hidden html-form, which looks really ugly, being the ONLY handwritten form in the whole javascript-driven application.

In short:

Never try to use special characters in Http-Get!

Forget using ajax to retrieve a file!

How to live with hibernate proxies

Stumbled over the fucking hibernate-CGlib-Proxies again. So here is what I found out and what helped me a lot:

If you load an object via the load()-method hibernate returns a proxy by default. As long as you don’t access any primitive property this thing won’t materialize. No prob, you might think and in most circumstances it isn’t. But consider this example:

class Plan {

// Cascade-type all, fetch lazy
private Plan lastVersion;
private boolean active

public Plan(Plan lastVersion){
if (lastVersion != null){
lastVersion.active = false;
}
this.active = true;
}
}

I don’t want to expose a public setter here to ensure the integrity of my versioning. Now the fuck-up:

Let’s say I get the current Plan from my Client and want to save it, the following code seems pretty straight forward:

// transactionmanaged service-method

Plan lastVersion = getHibernateTemplate().load(Plan.class, 4)

Plan currentPlan = new Plan(lastVersion);

getHibernateTemplate().saveOrUpdate(currentPlan);

BUT (as you might have guessed) this doesn’t work. At the end I do have two entries in my db both marked as active. Why that? lastVersion is a cglib-Proxy and hibernate does not recognize any changes that are not done by the setter. A possible workaround would be a private setter in the plan class, but somehow not even this is recognized by hibernate. So what are our options? One is to change the fetchmode of the lastversion. But doing so means sucking all previous versions from db when loading. Same happens when you mark the class @Proxy(lazy=false) as its a recursive structure. Played around with access types a while but that doesn’t have any influence. Finally I found out, that if you work with the “real” object instead of the proxy, it all works fine. To do so, you have to use the method get() instead of load(). Get() makes the db call instantly and returns a materialized object. In difference to the eager-fetchmode, all containing subtypes remain proxies.

That all leads to the questions, how we can make a clean separation between the ORM-Layer and our business-objects with hibernate. It’s just not transparent, when we got hibernate-specific-behaving objects flyin’ around in our domain-layer. And well, I don’t really have an answer on that…

Alle Jahre wieder – Datumsprobleme beim Programmieren

Es hätte so schön sein können. Da kommt man im neuen Jahr in das noch spärlich besetzte Büro und will in Frieden arbeiten. Und dann das: Ein Test crasht, weil das Osterdatum nicht richtig berechnet werden kann. Super…

Hier das Snippet nach der Korrektur:


int g = year % 19; // Golden number -1
int c = year / 100; // Century -1
int h = (c - c / 4 - (8 * c + 13) / 25 + 19 * g + 15) % 30;
int i = h - (h / 28) * (1 - (29 / (h + 1)) * ((21 - g) / 11)); // Anzahl Tage von 21.3. bis Vollmond vor Ostern
int j = (year + year / 4 + i + 2 - c + c / 4) % 7; // Wochentag des Vollmondes vor Ostern
int l = i - j; // Anzahl Tage vom 21. bis Sonntag vor/an Ostern

int month = 3 + (l + 40) / 44;
int day = l + 28 - 31 * ( month / 4 ) ;

return new DateTime(year, month, day, 0, 0, 0, 0, GregorianChronology.getInstance());

Die Formel stammt hierher:

http://www.tondering.dk/claus/cal/node3.html#SECTION003130000000000000000

Aber bloss keine Klammer verändern!

Schöner coden – einige Grundregeln

Im Rahmen meiner Arbeit bin ich immer wieder mit Code konfrontiert, der zwar super funktioniert, aber schöner und einfacher gestaltet werden könnte. Ich will an dieser Stelle mal einige Dinge sammeln, die hier weiterhelfen können.

Vergleiche von Strings mit Konstanten

schlecht:

if (!string.equals(KONSTANTE){..

Problem: Nullpointer-Exception bei Null-String

medium:

if (string != null && !string.equals(KONSTANTE){ ...

schöner:

if (!KONSTANTE.equals(string){ ...

In dieser Schreibweise wird die Nullprüfung unnötig. "".equals(null) gibt false zurück und verursacht keine Nullpointer-Exception.

Vergleiche mit Leerstring

schlecht:

eingabe.equals("")

Problem: siehe oben

medium:

"".equals(eingabe)

Problem: Es wird nicht beachtet, dass eingabe auch ” ” sein kann.

medium/schlecht:

"".equals(eingabe.trim())

Problem: Hier rennt man wieder in eine Nullpointer, wenn eingabe null ist.

schön:

StringUtils.isEmpty(eingabe)

StringUtils ist eine Klasse aus den apache.commons und deckt alle Anforderungen in diesem Zusammenhang ab:

isEmpty (null) == true

isEmpty("") == true

isEmpty(" ") == true

isEmpty ("something") == false

Analog ist mit Booleans zu verfahren. Hier gibt einem BooleanUtils entsprechende Hilfestellung. Aber Achtung: BooleanUtils.isFalse(null) == false und BooleanUtils.isTrue(null) == false!

PDFs konkateniert als HttpResponse zurückgeben

Um irgendwas mit PDF zu machen, bietet sich die Bibliothek iText an. Die API finde ich persönlich nicht sonderlich schön, aber man hat ja keine Wahl…

Hier ein Snippet, wie man ganze PDF-Dokumente konkateniert und dann als ein PDF ausgibt. Es gibt sicherlich schönere Lösungen. Comments sind immer willkommen. Nachteilig ist hier vor allem die Benutzung von byte[]. Je nach konkretem Anwendungsfall sollte man besser auf Streams umsteigen.

public doGet(HttpServleRequest request, HttpServletResponse response){

byte[][] files = ...;

String fileName = "myfile.pdf";

response.setHeader("Pragma", "public");
response.setHeader("Cache-control", "must-revalidate");
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "filename=" + fileName);

Document document = new Document();

PdfCopy copy = new PdfCopy(document, response.getOutputStream());
document.open();
for (int i = 0; i < files.length; i++) {
PdfReader reader = new PdfReader(files[i]);
int pageNum = reader.getNumberOfPages();
for (int j = 1; j <= pageNum; j++) {
copy.addPage(copy.getImportedPage(reader, j));
}
}
document.close();

}

Checkliste Java-Projekte

1. …

12. JRE-Kompatibilität

Kommen beim Kompilieren Warnings? Ist dies der Fall, ist zu überprüfen, ob als “deprecated” gesetzte Klassen oder Methoden verwendet wurden. Es gibt einen ganzen Haufen Anwendungen, die mit JDK 1.5 einfach nicht mehr funktionieren, da verwendete Klassen oder Methoden nicht mehr von java.lang (oder anderen APIs) unterstützt werden. Fallen in einer Version Elemente weg, so sind diese in älteren Versionen schon als deprecated gekennzeichnet.

1.6 Projektplanung

In jedem Projektplan ist Zeit zum Refactoren und zur Verbesserung der Performance einzuplanen. Nichts ist schlimmer, als in einem – natürlich auch wieder enorm zeitkritischen – Projekt in den erodierten Sourcen rumwühlen zu müssen und nach und nach immer unwartbareren Code zu pflegen.

14. Testing
14.56 Zufallsgeneratoren überprüfen
Zu testen:
verschiedene Seeds in hintereinander generierten Random-Objekten? Initialisiert man mehrere Random-Objekte hintereinander, z.B in einer Schleife, tut es ein einfaches new Randon(System.currentTimeMillis()) nicht mehr. Auf schnellen Rechnern führt das zu einem gleichen Verhalten der Randoms. Eine Lösung ist die Verwendung eines zusätzlichen Randoms zur Initialisierung.

23. Systemintegration

23.5 Speicherbedarf untersuchen

..

23.6 Garbage-Collection untersuchen

Bei der Systemintegration im Produktiv-, wie auch im Testsystem ist das Verhalten des Garbage-Collectors zu untersuchen.

Die JVM kann dazu mit den Parametern -gc:verbose und -XX:+PrintGCDetails gestartet werden.

Eine weitere interessante Perspektive gibt die Auswertung von jstat:

jps zeigt alle vm-Ids der laufenden Virtual Machines. Befehl ist Teil vom SDK. vm-Id ist typischerweise die pid.

jstat - [-t] [-h <lines>] <vmid> [<interval> [<count>]]
Beispiel: jstat -gcutil -h3 99999 250 200

Ein Tool, dass die Informationen zum Verhalten des Garbage Collector visualisiert, ist visualgc. Hier läßt sich auch der Grund für die Garbage Collection sehen: War es ein System.gc() oder gab es bessere Gründe? Das Tool ist nicht in der JDK 1.5 enthalten, kann aber bei Sun heruntergeladen werden.

Es sollte auch ein Auge auf die Auslastung des Perm-Spaces geworfen werden. Dieser ist unabhängig vom Gesamtheap. Die Größe läßt sich mit -XX:PermSize=..MB und -XX:MaxPermSize=..MB steuern. Im Default sollte die JVM 64MB reservieren, der aber unter mysteriösen Umständen auch schrumpfen kann. Ich bin mir nicht ganz sicher, ob es sich dabei um ein normales Vergrößern des Virtual Spaces ( nicht allozierter, aber reservierter Speicher) handelt. Setzt man die Größe mit -XX:PermSize scheint die Größe sich aber nicht zu verändern.

Bei Serveranwendungen ist es wichtig, das Verhältnis von Young zu Tenured Space zu untersuchen. Finden zuviele Young collections statt? In einer größeren Serveranwendung kann man u.U. eine Ratio von 1:2 festlegen ( -XX:NewRatio=2) (Young 1 : 2 Tenured) .

Im Client-Teil einer Anwendung reichen die default-Einstellungen meist aus.

Velocity condensed

Velocity ist keine Fahrradstadt, sondern ein Java-basiertes Templatesystem, dass eine Trennung zwischen Java-Code und Oberflächenbeschreibung erlaubt. Die Velocity Template Language (VTL) erlaubt den Aufruf von an anderer Stelle in Java implementierten Objekten und Methoden. Velocity geht über den reinen Einsatz auf Webpages hinaus. Auch SQL (u.v.m.) läßt sich damit zusammenbauen.

Nach vergleichsweise langer Suche habe ich eine gute How-to-Seite gefunden, aus der ich im Folgenden das Wesentliche wiedergebe.

Sprachsyntax:

– jede Anweisung beginnt mit #, Referenzen mit $

-Variablen werden mit $ gekennzeichnet, sie können im HTML-Code oder im Java-Code definiert und initialisiert werden: #set ( $a = “bla”), Variablen beginnen mit Buchstaben, so dass die Angabe $2.40 nicht als Variable interpretiert wird.

– Escaping mit \

-Strings: ” “, wenn sowohl statischer Text, als auch zu interpretierende Variablen, ‘ ‘ wenn as-is.

– Comment: ## (single line), #* *# (multiline), #** *# (documentation)

-drei Typen von Referenzen: variables ($var), properties($object.Property ruft, wenn vorhanden die Methode getProperty() auf – nicht verwechseln mit Instanzvariable! Auf diese kann nicht ohne Getter zugegriffen werden), methods ($object.eatThis( “banana”) ), wobei die Übergabe zwischen Java und Velocity immer über Strings läuft

– werden Properties verwendet, gibt bestimmte Lookup-Rules um auf die richtige Methode zu kommen

– ist eine Referenz zum Zeitpunkt der Ausführung nicht definiert, wird die Referenz als Klartext ausgegeben. Um stattdessen blank auszugeben, ist ein ! zu notieren: $!justDontPrintMeIfNull

– die zu den Referenzen angegebene Schreibweise ist die shorthand-Schreibweise. Wenn nötig, kann der Ausdruck mit geschweiften Klammern versehen werden: $!{object.doFormal()}

– Escapen mit \

-Anweisungen: beginnen immer mit #, lassen sich auch über {} schreiben: #{if}

-#set: zum Wertzuweisen: #set ( $var = XXX) mit XXX als Property, Methodenrückgabe, Variable, Array ( [ “b”, “c”]), Map ({“a” : “appel”, “b” : “banane”}), arithmetischer Ausdruck

– Standardmäßig kann KEIN null zugewiesen werden! Die Referenz bleibt erhalten!

-Konditionen: #if #ifelse #else #end(!)

-Evaluierung im #if: $var ist true, wenn boolean und true ODER $var ist nicht boolean und nicht null

– == kann zum Vergleich von Strings, Numbers oder Objects verwendet werden

– logische Operatoren &&, || und ! äquivalent zu Java

-#foreach( $thingie in $things) #end

– interne Variable für die Nummer des Schleifendurchlaufs: $velocityCount startet bei 1

– #include (“bla.txt”) : ungerendertes Einbauen, #parse (“vtlText.txt”) : rendern und einbauen; Dateien müssen unter TEMPLATE_ROOT liegen

-#stop. Stoppt die Velocity-Interpretation, zu Debugging-Zwecken sinnvoll.

Soviel zu Velocity condensed. Es gibt auch die Möglichkeit Macros zu schreiben (Velocimacros). Darauf möchte ich an dieser Stelle nicht weiter eingehen. In oben verlinktem How-to wird darauf näher eingegangen.