Über mich

Mein Bild
Seevetal-Horst in der Nähe von Hamburg, Niedersachsen, Germany

2007-08-19

Cache mich

Test-Driven-Development ist eine feine Sache: man schreibt einen Test, welcher einen Anwendungsfall simuliert und implementiert und testet das Interface, bis alles so sauber funktioniert, wie es das Interface verspricht.

Meine Tests laufen als Remote-Client und testen Remote-Interfaces von stateless Session Beans. Das ist zwar etwas umständlich, entspricht aber dem für die Anwendung geplanten Szenario. Es sind also keine Unit- sondern eher Integration-Tests. Mit Glassfish und Netbeans ist das einfach aufgesetzt - man muss nur appserver-rt.jar im Classpath der Tests haben und kann dann einfach InitialContext JNDI lookup() ausführen.

Implementieren von Methoden, Deployen der stateless Beans und Ausführen der Tests geht selbst auf meinem 2GB Thinkpad T60 recht zügig (natürlich läuft da auch die Informix DB noch drauf).

Etwas macht mir aber Kummer: Irgendwie passiert es immer wieder, dass der Persistence Context definitiv behauptet, es gäbe von einer Entity garantiert gar kein Exemplar mehr und dann beim persist() eine ExceptionEntityExists auslöst, weil er dann meint, den Primary Key doch schon zu kennen. Und das, obwohl unmittelbar vor dem persist() ein Query "delete from Entity" ausgeführt wurde und ein em.find() mit dem Key der neu einzufügenden Entity nichts findet.

Ich habe den Eindruck, dass durch das Deployen der zu testenden EJBs die Synchronisation der Persistence Contexts, die für jede Methode der stateless Beans (pro Transaction) erzeugt werden, mit dem 2nd Level Cache der Toplink Essentials beschädigt wird.

Ich habe in Wonseok Kim's Blog einiges zum Thema Toplink Cache gefunden.

Das Problem lässt sich nur durch Stoppen und Starten des Glassfisch beheben.

Allerdings macht mich die Idee nervös, mit solchen Effekten rechnen zu müssen, wenn in einem in Produktion laufenden Glassfish neue Versionen deployed werden. Kommt Zeit, kommt Rat!?

2007-08-14

Lohn der Ordnung

Da hatte ich mir eine handvoll prima funktionierender, generischer Methoden zur Persistierung der Entities in eine stateless Bean geschraubt, um mit JUnit meine Mappings zu testen. Das sah dann zum Beispiel so aus:
public  T getEntity(Class t, K k ) {
log.info("getEntity(" + t + ", "  + k );
Object o = em.find(t, k);
@SuppressWarnings("unchecked")
T r = (T) o;
if ( r != null) {
em.refresh(r); // unbedingt nötig, damit OneToMany aktualisiert wird
}
return r;
}
Für den Einsatz in einer richtigen Anwendung war das aber zu unpraktisch und ließ keinen Raum für Geschäftslokik. Also wurde eine Facade gebaut:
public Xyz getXyz(final Integer xyzKey){
Xyz xyz = this.getEntity(Xyz.class,cargowrid);
... xyz geschäftlich bearbeiten ...
return xyz;
}
Prima! Es ging um ein Package mit ungefähr 50 Entities. Für jedes Entity Methoden fürs
  • Einfügen
  • Finden
  • Ändern
  • Löschen
macht zusammen 4 x 50 = 200 Methoden im Remote Interface. Einige Stunden Arbeit später fiel der Startschuss für die Wiederholung der inzwischen auch angepassten JUnit Tests.

Ich sollte hier erwähnen, dass meine JUnit Tests gegen das Remote Interface ausgeführt werden und bis vor dieser Neu-Ordnung prima funktionierten. Meine Überraschung war nicht gering, als ich das erste Ergebnis sah:
Testcase: testCargowWithCarseqInsert(ejb.TestPartnerServiceRemoteCargow): Caused an ERROR
-98
java.lang.ArrayIndexOutOfBoundsException: -98
at com.sun.corba.ee.impl.presentation.rmi.bcel.BCELStubBase.invoke(BCELStubBase.java:193)
at ejb.__PartnerServiceRemote_Remote_DynamicStub.finishSession(ejb/__PartnerServiceRemote_Remote_DynamicStub.java)
at ejb._PartnerServiceRemote_Wrapper.finishSession(ejb/_PartnerServiceRemote_Wrapper.java)
at ejb.TestPartnerServiceRemoteCargow.tearDown(TestPartnerServiceRemoteCargow.java:38)

Das ist doch ganz klar, um was es hier geht ... oder? Na - ich habe jedenfalls ungefähr eine Stunde gebraucht, um von der Fehlersuche in und am Glassfish Application Server abzulassen.

Um es kurz zu machen: Die Testanwendung, welche im Glassfish installiert ist und das Local Interface verwendet, hatte gar keine Probleme mit der neuen Facade. Also war mein JUnit Testaufbau kaputt? Hatte ich plötzlich falsche JARs am Wickel?

Eine Tasse Kaffee später ging mir ein Kronleuchter auf. Ich kommentierte 90% der Methoden im Remote Interface aus und suchte mir einen JUnit Tests, der mit dem Rest agierte aus: VOILA!

Die durch meinen Hang zur Ordnung hervorgerufene Inflation an Methoden im Remote Interface hatte eine Schallmauer durchbrochen, von deren Existenz ich nichts wusste. Meine anschliessende Suche nach der unsichtbaren Grenze blieb ohne Ergebnis. Wer weiß, wo man sowas nachlesen kann? Und, um es mit Torfrock zu sagen "Gibt es Leben auf anderen Planeten?" - also noch andere Limits, vor deren Überschreitung ich mich gern schützen würde?

Ich bin - um ehrlich zu sein - einfach nicht ehrgeizig genug, die nächsten Tage damit zu verbringen, nach diesen Grenzen zu suchen. Mein derzeitiger Auftraggeber ist auch nicht wirklich daran interessiert, Geld für diese Suche auszugeben.

.... aber irgendwie wurmt es mich doch, dass ich das alles noch nicht weiß!

Natürlich muss ich jetzt noch weiter aufräumen - neue Packages - neue Remote Interfaces - neue Lookups - neue Arbeit.

Schade - es war zu schön einfach.

Leider vermeldet die SUN Bug WebSite "Maintenance" ... also werde ich demnächst erfahren, ob es sich wirklich um einen Bug handelt oder lediglich die Exception mit besserer Diagnose Information ausgestattet wird.

Inzwischen heißt SUN jetzt ORACLE und die haben sich von diesem Bug völlig getrennt. Es lohnt sich also nicht mehr, auf den obigen Link zu klicken.

2007-08-11

Womit ich momentan viel Zeit verbringe

Java Enterprise Edition 5 (Java EE 5)

Endlich! Wieder ein neuer Weg, der grundlegenden Idee einen neuen Namen zu geben. Ich kann mich entsinnen, auch schon "Java 2 Enterprise Edition 5" gelesen zu haben. Seit mehr als 10 Jahren treibt SUN es mit der Vergabe von Bezeichnungen auf die Spitze.

Gibt es schon eine Zertifizierung für das fehlerfreie Aufsagen von Releases und zugehörigem marktwirksamen Namen? Ich sollte mal intensiv auf der SUN Website forschen, ob es da so etwas wie eine "Wenn Sie sich verloren vorkommen - schauen Sie doch einfach auf diese Tabelle aller Bezeichner und Relases, die uns innerhalb von 10 Jahren eingefallen sind .... ohne Gewähr für die Richtigkeit der Inhalte"

Man kann nur hoffen, dass die für die Entwicklung der Technologie zuständigen Mitarbeiter bei SUN nicht ähnliche Konfusionsaktivitäten im Quellcode veranstalten.

Da habe ich nun NetBeans 5.5.1 und Glassfish 2.0 Beta Build 53 auf der Platte und bin schwer damit beschäftigt, eine knapp 20 Jahre alte Informix 4GL Anwendung auf diese brandneue Plattform zu migrieren. Mehr als 280 Tabellen und einige komplexe Views möchten auf EJB3 Entities gemappt werden.

Nicht zu vergessen 323 Informix 4GL Module, die zu 214 Dialogprogrammen und 50 Reports gebunden sind, sowie deutlich über 300 Shellscripts, die das alles in Bewegung versetzen. Das alles ohne Dokumentation und mit sehr sehr wenigen Kommentaren im Quellcode, deren Aktualität in der Regel sehr sehr fragwürdig ist.

Eigentlich war ich durch IBM's RAD 6 und RSA 6 schon sehr gut mit Eclipse vertraut und hätte gern weiter damit gearbeitet. Aber leider haben alle Eclipse Distributionen, die ich mir näher angeschaut habe, keine auch nur annähernd vergleichbar nahtlose Integration mit Java EE 5, EJB3 und Glassfish geboten.

Nach einigen Wochen mit NetBeans 5.5 und ein paar Tagen mit NetBeans 6.0 Preview bin ich nicht wirklich unglücklich mit dieser Arbeitsumgebung. Wenn ich das mit IBM's RAD6 vergleiche, bin ich sogar sehr sehr sehr glücklich damit.

Dieses - mein erstes - Blog soll die Höhepunkte meines Zusammenlebens mit dem oben angerissenen Projekt festhalten. Bin schon sehr gespannt darauf, ob ich es schaffe, das Tagebuch regelmässig zu füttern. Und es sollen nicht nur Nörgeleien aufgezeichnet werden.