NIO.2 Umstellung. Mein Fazit (nach einem Tag)

Um zu testen, wie sich die neue NIO.2-Bibliothek so in der Praxis macht, habe ich unsere tutego-Software auf NIO.2 gebracht. Als erstes habe ich File durch Path/Paths/Files-Aufrufe ersetzt. Dabei sind mir schon ein paar Stellen aufgefallen, die ich gerne noch verbessert sehen würde für >= Java 8.

  1. Von den File-Konstrukturen gibt es: File(File parent, String child) und File(String parent, String child). Es ist praktisch, dass der erste Teil entweder File oder String sein kann. Ich habe bei mir eine Menge von Aufrufen der Art new File(path, filename). Mal ist path ein String, mal ein File (in der Regel File). Bei der Konvertierung zu Path wird es ungemütlich, denn es gibt nur get(String first, String… more) aber kein get(Path first, String… more). Also läuft es auf ein path.resove(child) raus, was ich aber nicht so schön finde wie ein get(path, child). Aber alles Geschmacksache.
  2. File wird öfter als Parametertyp akzeptiert als Path. So muss ich schreiben:
    PrintWriter out = new PrintWriter( testimonalsPath.toFile() );
    Schöner wäre ein Konstruktur PrintWriter(Path).
  3. Die Methode getFileName() liefert keinen String, sondern ein Path-Objekt nur mit dem Dateinamen. Daher führt folgendes nicht zum Ziel: path.getFileName().endsWith(".xml"). Und path.getFileName().toString()endsWith(".xml") ist etwas lang.
  4. Files.readAllBytes() ist zwar schön, aber Files.readAllChars(Path,CharSet) wäre auch nett.

Inselupdate: Ein Wort zu Microsoft, Java und zu J++, J#

In der Anfangszeit verursachte Microsoft einigen Wirbel um Java. Mit Visual J++ (gesprochen „Jay Plus Plus“) bot Microsoft schon früh einen eigenen Java-Compiler (Teil vom Microsoft Development Kit) und mit der Microsoft Java Virtual Machine (MSJVM) eine eigene schnelle Laufzeitumgebung. Das Problem war nur, dass Dinge wie RMI und JNI am absichtlich fehlten[1] – JNI wurde 1998 nachgereicht. Entgegen alle Standards führte der J++-Compiler neue Schlüsselwörter multicast und delegate ein. Weiterhin fügte Microsoft einige neue Methoden und Eigenschaften hinzu, zum Beispiel J/Direct, um der plattformunabhängigen Programmiersprache den Windows-Stempel zu verpassen. Mit J/Direct konnten Programmierer aus Java heraus direkt auf Funktionen aus dem Win32-API zugreifen und damit reine Windows-Programme in Java programmieren. Durch Integration von DirectX soll die Internet-Programmiersprache Java multimediafähig gemacht werden. Das führte natürlich zu dem Problem, dass Applikationen, die mit J++ erstellt wurden, nicht zwangsläufig auf anderen Plattformen lauffähig sind waren. Sun klagte gegen Microsoft.

Da es Sun in der Vergangenheit finanziell nicht besonders gut ging, pumpte Microsoft im April 2004 satte 1,6 Milliarden US$ in die Firma. Microsoft erkaufte sich damit das Ende der Kartellprobleme und Patentstreitigkeiten. Dass es bis zu dieser Einigung nicht einfach gewesen war, zeigen Aussagen von Microsoft-Projektleiter Ben Slivka über das JDK beziehungsweise die Java Foundation Classes, man müsse sie »bei jeder sich bietenden Gelegenheit anpissen« (»pissing on at every opportunity«).[2]

Im Januar 2004 beendete die Arbeit an Microsoft J++, denn die Energie floss in das .NET-Framework und der .NET-Sprachen. Am Anfang gab es mit J# eine Java-Version, die Java-Programme auf der Microsoft .NET-Laufzeitumgebungen CLR ausführt, doch Anfang 2007 wurde auch J# eingestellt. Das freie IKVM.NET (http://www.ikvm.net/) ist eine JVM für .NET und kommt mit einem Übersetzter von Java-Bytecode nach .NET-Bytecode, was es möglich macht, Java-Programme unter .NET zu nutzen. Das ist praktisch, denn für Java gibt es eine riesige Anzahl von Programmen, die somit auch für .NET-Entwickler zugänglich sind.

Microsoft hat sich aus der Java-Entwicklung nahezu vollständig zurückgezogen. Es gibt zum Beispiel noch den Microsoft JDBC Driver for SQL Server und Microsoft unterstützt eine API für Office-Dokumente. Das Verhältnis ist heute auch deutlich entspannter und vielleicht gratuliert Microsoft wie es auch Linux zum 20 Geburtstag gratuliert hat[3] irgendwann einmal Oracle.


[1] http://www.microsoft.com/presspass/legal/charles.mspx

[2] Würden wir nicht gerade im westlichen Kulturkreis leben, wäre diese Geste auch nicht zwangsläufig unappetitlich. Im alten Mesopotamien steht »pissing on« für »anbeten«. Da jedoch die E-Mail nicht aus dem Zweistromland kam, bleibt die wahre Bedeutung wohl unserer Fantasie überlassen.

[3] http://www.youtube.com/watch?v=ZA2kqAIOoZM

Performante Ereignisbearbeitung durch LMAX Architektur

Wer performante Systeme entwickelt, sucht immer nach neuen Ideen. Martin Fowler beschreibt in seinem Blog  http://martinfowler.com/articles/lmax.html die Architekturform LMAX einer Trading-Anwendung. Auch die PDF http://disruptor.googlecode.com/files/Disruptor-1.0.pdf beschreibt die Architektur und geht Fragen auf den Grund wie: Was kosten Locks, wo ist das Problem bei Queues, …? Mehr Infos gibt auch der Blog http://blogs.lmax.com/ und der Herz der Implementierung ist quelloffen: http://code.google.com/p/disruptor/.

JDK 7 ist da … und schon gleich die ersten Probleme

Am 7.7 wurde Java 7 ja schon weltweit gefeiert wir eine neue CD von Justin Biber. Heute ist der 28.07. und damit das offizielle Release-Datum. Eigentlich läuft das ganz rund, ABER mit HotSpot gibt es einen richtig harten Fehler: http://www.lucidimagination.com/search/document/1a0d3986e48a9348/warning_index_corruption_and_crashes_in_apache_lucene_core_apache_solr_with_java_7. Tja, dumm gelaufen.

Thema der Woche: CAL10N

Gastbeitrag: Bubbles in Swing

In vielen modernen Web-Anwendungen findet sich immer wieder eine Komponente, die bei einem Klick aktiviert wird und an Ort und Stelle auftaucht. Sie lässt sich im weitesten Sinne mit dem Wort "Popup", "Balloontip" oder "Bubble" beschreiben, wie zum Beispiel im Google Kalender:

Eine typische Popup Komponente aus dem google Kalender

Solche Komponenten stellen nicht nur Informationen dar, sondern bieten auch Funktionen zur Weiterverarbeitung an und können als Ersatz für viele Dialoge fungieren. Spätestens seit dem Code Bubbles Projekt ist der Nutzen auch für den Endanwender solcher Komponenten ersichtlich.

Weiterlesen

Aufrufstack von Ausnahmen verändern

Wenn wir in einer Ausnahmebehandlung eine Exception e auffangen und genau diese dann mit throw e weiterleiten, müssen wir uns bewusst sein, dass die Ausnahme e auch den Aufrufstack weitergibt. Aus dem vorangehenden Beispiel:

java.net.URISyntaxException: Malformed escape pair at index 7: http://%

at java.net.URI$Parser.fail(URI.java:2827)

at java.net.URI$Parser.scanEscape(URI.java:2957)

at java.net.URI.<init>(URI.java:595)

at Rethrow.createUriFromHost(Rethrow.java:9)

at Rethrow.main(Rethrow.java:24)

Die main()-Methode fängt den Fehler von createUriFromHost() ab, aber diese Methode steht nicht ganz oben im Aufrufstack. Die Ausnahme stammte ja gar nicht von createUriFromHost() selbst, sondern von fail(), sodass fail() oben steht. Ist das nicht gewünscht, kann es korrigiert werden, denn die Basisklasse für alle Ausnahmen Throwable bietet die Methode fillInStackTrace(), mit dem sich der Aufrufstack neu füllen lässt. Unsere bekannte Methode createUriFromHost() soll auf fillInStackTrace() zurückgreifen:

public static URI createUriFromHost( String host ) throws URISyntaxException

{

try

{

return new URI( "http://" + host );

}

catch ( URISyntaxException e )

{

System.err.println( "Hilfe! " + e.getMessage() );

e.fillInStackTrace();

throw e;

}

}

Kommt es in createUriFromHost() zur URISyntaxException, so fängt unsere Methode diese ab. Ursprünglich ist in e in der Aufrufstack mit der fail()-Methode ganz oben gespeichert, allerdings löscht fillInStackTrace() zunächst den ganzen Stracktrace und füllt ihn neu mit dem Pfad, den der aktuelle Thread zu der der Methode führt, die fillInStackTrace() aufruft – das ist createUriFromHost(). Daher beginnt die Konsolenausgabe auch mit unserer Methode:

Hilfe! Malformed escape pair at index 7: http://%

java.net.URISyntaxException: Malformed escape pair at index 7: http://%

at RethrowWithFillInStackTrace.createUriFromHost(RethrowWithFillInStackTrace.java:14)

at RethrowWithFillInStackTrace.main(RethrowWithFillInStackTrace.java:24)

Gastbeitrag: SQL als "interne DSL" in Java mit jOOQ

Vor einiger Zeit hat Christian auf seinem Blog das fluent API seiner jRTF-Library vorgestellt, welche dem Benutzer ermöglicht, RTF-Dokumente mit einfachen Sprach-Konstrukten direkt mit Java zu erstellen:

DSL (Domain Specific Languages) sind ein spannendes Thema in vielen Bereichen. Für die meisten Zwecke werden sogenannte "externe" DSL’s definiert, also für einen technischen oder fachlichen Bereich spezialisierte Sprachen, welche unabhängig von anderen Sprachen interpretiert oder kompiliert werden. Manchmal gelingt es aber auch, solche spezialisierten Sprachen in einer anderen Sprache zu "internalisieren", wie dies eben mit jRTF gelungen ist. Heute möchte ich eine ähnliche DSL präsentieren, welche ich in jOOQ (Java Object Oriented Querying) eingebaut habe. jOOQ bildet SQL als "interne DSL" in Java ab, so dass Datenbank-Abfragen direkt in Java formuliert werden können. Ein Beispiel:

// Suche alle Bücher, welche in 2011 publiziert wurden
create.select()
      .from(BOOK)
      .where(PUBLISHED_IN.equal(2011))
      .orderBy(TITLE)
      .fetch();

Dabei steht BOOK für eine Tabelle mit den Feldern PUBLISHED_IN und TITLE. Alle diese Objekte werden von jOOQ generiert.

Weiterlesen

Gastbeiträge sind willkommen

Wer Lust hat, etwas spannendes auf dem Java-Insel-Blog zu veröffentlichen (einmalig oder mehrmalig), kann sich gerne bei mir melden. Die Themen sollten sich natürlich um Java im weitesten Sinne drehen, also nicht, wie man den besten Mochito mixt, oder den Opa vom Schnarchen abhält. Für Leser sind Gastbeiträge etwas feines, denn so bekommt der Blog etwas andere Themen und neue Blickwinkel. Schreiber wiederum können ein relativ großes Publikum erreichen und so spannenden Projekte oder Lösungen vorstellen.

Mein Umstieg auf UiBinder (GWT)

Das komplette Frontend für die tutego-Kunden/Trainer/Serminarverwaltung ist in GWT implementiert. Die Codebase ist auf dem Level von GWT 1.1 und bis zur letzten Version hat sich viel geändert. Über Updates blogge ich regelmäßig. Es wurde Zeit neu zu betrachten, welche Teile meiner Software ich vielleicht umbauen kann. Viele Themen sind spannend, aber leider gibt im Netz kaum Dokus, und da meine Lösung läuft, war die Motivation nicht sonderlich hoch, Stunden zum Rumspielen zu investieren.

Eine der großen Neuerungen in GWT 2.0 ist die Möglichkeit, deklarativ Oberflächen aufzubauen. Im Mittelpunkt steht das UiBinder-Famework, was eine XML-Dateien zur Beschreibung eines Widget-Baum nutzt und in eine initialisierte GWT-Komponente überführt. Das Feature ist relativ gut dokumentiert und die Änderungen im Code sind klein. Daher habe ich mir ein paar Stunden für die Überführung einer View genommen.

Für jede View gibt es bei mir eine Klasse, die von einer GWT-Klasse wie Composite abgeleitet ist. Sie wird vom Presenter aufgebaut. Die View-Klasse deklariert eine Reihe von Objektvariablen. Die werden später initialisiert. Vorher sahen meine Programme etwas so aus:

// Contact person

HTML contactPersonLabel = new HTML( "<b>AnsprechpartnerIn</b> (Name, EMail, Telefon)" );
contactPersonLabel.getElement().getStyle().setMarginTop( 0.5, Unit.EM );
panel.add( contactPersonLabel );
panel.add( contactPersonTextBox = new FormTextBox() );   

// tutego rate per day

HTML ratePerDayLabel = new HTML( "<b>tutego Tagessatz</b> (netto)" );
ratePerDayLabel.getElement().getStyle().setMarginTop( 0.5, Unit.EM );
panel.add( ratePerDayLabel );
panel.add( new HorizontalFlowPanel( ratePerDayTextField = new FormIntegerTextBox(), new HTML( " Euro" ) ) );
ratePerDayTextField.setWidth( "5em" );

Mit Styles arbeite ich auch, wobei ich dies nicht für das Mikrolayout verwende. Lokale Abstände initialisierte ich immer direkt.

Der UiBinder externalisiert die Beschreibung des Objektgraphen in eine XML-Datei. Es ist wichtig zu verstehen, dass der UiBinder keinen Template-Engine ist, also die XML-Datei kein XHTML ist, wo man a) einfach HTML schreiben kann und b) so etwas wie Wiederholungen/Fallunterscheidungen schreiben kann. Es ist “nur” eine Beschreibung des Objektgraphen und ausschließlich GWT-Widgets werden dort referenziert. (Auch wenn das bei einem SpanElement mit <div></div> auf den ersten Blick nicht so aussieht.)

Das GWT-Plugin für Eclipse ermöglicht gleich das Anlegen der XML-Datei und der Klasse, was für neue Views praktisch ist. Ich habe von Hand eine XML-Datei EditCustomerView.ui.xml aufgebaut, die so aussieht:

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui=’urn:ui:com.google.gwt.uibinder‘
    xmlns:g=’urn:import:com.google.gwt.user.client.ui‘ xmlns:t=’urn:import:traida.client.web.util‘>
    <ui:with field=’res‘ type=’traida.client.resource.TraidaResources‘ />
    <ui:style>
       .bottomGap { margin-bottom: 1em; }
    </ui:style>
    <g:VerticalPanel>
        <g:Label styleName='{res.style.header1}‘ ui:field=’header‘ />

        <t:TitledPanel>
            <g:HTML>Adresse und Kontakt</g:HTML>
            <g:Anchor ui:field=’editContactAnchor‘>[Bearbeiten]</g:Anchor>
        </t:TitledPanel>
        <g:HTML styleName='{style.bottomGap}‘ ui:field=’businessCardHTML‘ />

        <t:TitledPanel>
            <g:HTML>Kurs(e)</g:HTML>
            <g:Anchor ui:field=’addNewTrainingAnchor‘>[+]</g:Anchor>
        </t:TitledPanel>
        <t:VerticalFlowPanel styleName='{style.bottomGap}‘ ui:field=’trainingsPanel‘ />

        <t:TitledPanel>
            <g:HTML>Vermerk und Logo</g:HTML>
        </t:TitledPanel>

    </g:VerticalPanel>

</ui:UiBinder>

Am Anfang werden zwei Namensräume g und t aufgebaut, einmal für die Google-Komponenten, einmal für eigene. Eigene Komponenten können einfach verwendet werden, auch die Tastaturvervollständigung klappt, ist allerdings (nur bei mir?) ziemlich träge.

Wichtig sind die ui:field-Elemente. Sie entsprechen Variablen, die in einer Java-Klasse deklariert werden. Parallel zu der XML-Datei EditCustomerView.ui.xml gibt es eine andere zugehörige Java-Klasse EditCustomerView. Sie beginnt so:

class EditCustomerView extends Composite
{
  interface EditCustomerViewUiBinder extends UiBinder<Widget, EditCustomerView> {}  // 2
  private static EditCustomerViewUiBinder uiBinder = GWT.create(EditCustomerViewUiBinder.class);

  @UiField Label header;    // 1

  …

  EditCustomerView()
  {
    initWidget( uiBinder.createAndBindUi( this ) );  // 3
    setWidth( "800" ); 
     …

  }

}

Im Rumpf ist etwas Magie, und drei Details sind wichtig:

  1. Die Klasse hat für alle in der XML-Datei deklarierten ui:field-Dinge eine Objektvariable mit der entsprechenden Annotation @UiField. Die Typen müssen zusammenpassen, also Label zu <g:Label> usw. Der UiBinder instanziiert selbständig die Typen durch den Standardkonstruktor. Ist keiner vorhanden, muss man tricksen und eine Factory einführen.
  2. Zu den Generics beim UiBinder: das erste Typargument (hier Widget) ist das, was später als Ergebnis “rauskommt”. In der XML-Datei nutze ich ein VerticalPanel, sodass der Typ hätte eigentlich auch spezieller sein können, doch den spezielleren Typ brauche ich nicht. Das zweite Typargument ist die Klasse, die die @UiField-Variablen deklariert, also die eigene Klasse selbst.
  3. Der Aufruf createAndBindUi() baut den Objektbaum auf. Das Ergebnis der Methode ist vom Typ, der im ersten Generics zugewiesen wurde, also im Beispiel Widget.

Das zur Technik. Die Frage ist, ob sich die Umstellung gelohnt hat. Bisher habe ich eine View umgestellt, doch das Ergebnis sieht gut aus. Die hierarchische Gliederung ist übersichtlich, wobei mir die XML-Ansicht reicht und ich den Designer nicht brauche. Allerdings fände ich es besser, das Layout einfacher verändern zu können. Soll zum Beispiel der Abstand zur nächsten Zeile erholt werden, so kann man nicht einfach beim Element selbst ein CSS-Syle setzen, sondern muss ein <style> Element einführen, ihm einen Namen geben und dann zuweisen. Das ist mehr Schreibarbeit als nötig. Die anderen Views werde ich nun auch umstellen.

Ob ich die UiBinder für jede View einsetzen werde wird sich zeigen, da einige Views viel stäter aus HTML aufgebaut werden und die View im Prinzip nur einen Titel setzt und der Rest ist HTML.

Ein paar Links: