Donnerstag, 5. November 2009

Fluent Interface

Bin mal wieder über das Thema Fluent Interface Pattern gestolpert. Kurz ausgedrückt, werden mit dem Fluent Interface Pattern Methodenaufrufe in Fließtext gebracht. Beispiel:

Date date = CalendarUtils.add(5).days().and(10).hours().to(date);

Das fühlt sich beim Programmieren anfänglich etwas ungewohnt an, gefällt mir persönlich aber sehr gut. Auf den ersten Blick sieht es einfach aus, selbst solch ein Schnittstellenmodell zu bauen, was bei zunehmender Komplexität jedoch täuscht. Will man den Satzbau beeinflussen, also sicherstellen, dass alle geforderten Methoden aufgerufen werden, um die Objektinstanz fertig zu stellen, kann leider nicht immer nur ein und das gleiche Objekt zurückgegeben werden. Dann nämlich werden Mediatoren benötigt, die die nächsten Satzschnipsel anbieten. Das ist nicht schwierig, wird aber schnell unübersichtlich.

Eine sehr gelungen API, die in jedem Fall einen Blick wert ist, ist die API FEST Reflection Module. Die Beispiele auf der Projektseite veranschaulichen auch gleich, was man mit dem Fluent Interface Pattern so alles anstellen kann.

Ein Eclipse Plugin namens Fluent Interface Modeller, dass eventuell beim Aufbau eigener Fluent Interface Klassen helfen kann gibt es hier. Testen konnte ich dieses allerdings noch nicht.

Zum in das Thema hineinlesen eignet sich ansonsten noch ein Artikel vom Heise Verlag.

Mittwoch, 14. Oktober 2009

Datenverarbeitung

Man bekommt es ja häufiger mal mit Daten zu tun, die in irgendwelchen Formaten vorliegen und verarbeitet werden wollen. Üblicher Weise sind Eingaben vor deren Verarbeitung auf ihre Richtigkeit zu prüfen. Werden Daten in einem bestimmten Format erwartet, ist eben auch festzustellen, ob die hereingereichten Daten auch diesem Format entsprechen. Tun sie dies nicht, können nicht passende Daten unmittelbar abgelehnt und eine passende Fehlermeldung formuliert werden.

Kommen die zu verarbeitenden Daten aus dem Dateisystem, kann eine Prüfung auf die Dateierweiterung schon einen oberflächlichen Anhaltspunkt liefern. Windows begnügt sich übrigens mit der oberflächlichen Formaterkennung, was durchaus zur Folge haben kann, dass eine Bilddatei als Text deklariert wird, weil die Dateiendung gerade nicht zum Datenformat der Datei passt.

In der Unix Betriebssystemwelt geben sich Programme hingegen ehr selten mit Dateiendungen ab. Die Identifikation des vorliegenden Datenformats findet hier anhand der Magic Bytes - also den ersten vier Bytes der Datei statt. Die ersten vier Bytes eines Jpeg komprimierten Bildes lauten zum Beispiel 0xff 0xd8 0xff 0xe0.

Dateiformaterkennung anhand der Magic Bytes ist für Software immer die erste Wahl, da die Prüfung viel präziser ist, als die Dateiendung aus dem Filesystem. Spätestens, wenn beim Auslesen nur noch ein InputStream vorliegt, kommt man mit den Dateiendungen nicht weiter. So vermeidet man bereits präventiv, dass Daten auf einen Algorithmus losgelassen werden, für den diese gar nicht geeignet sind.

In der Praxis gibt es bereits fertige Bibliotheken, die sich um die Datenformaterkennung kümmern. So gibt es zum Beispiel das Mime Type Detection Utility, das bereits eine Vielzahl an gängigen Datenformaten erkennen kann.

Vor eine besondere Herausforderung wird man bei der Datenformaterkennung von Text gestellt. So wird bei UTF Kodierten Texten noch häufig die verwendete Byte-Reihenfolge (Big- oder Little-Endian) in die ersten zwei Bytes kodiert, spätestens bei ASCII ist aber Schluss. Die Erkennung von ASCII erfordert also echte Kreativität. Mein erster Ideenansatz ging in Richtung Textanalyse - also zum Beispiel zu prüfen, ob ein Text ein übliches Maß an Leerzeichen enthält, was aber nur eine ungenügende Annäherung ist. Ein Blick in den Source des Mime Type Detection Utility förderte noch einen anderen Ansatz zu Tage. Dieser dreht die These um und prüft, ob es sich bei den gegebenen Daten um Binärdaten handeln könnte. Auch dies ist wiederum nur eine Annäherung, aber durchaus praktikabel. So kann bei erwarteten Textdaten zumindest geprüft werden, ob es sich bei den gegebenen Daten eben NICHT um Text handelt.

Ohne lange Umschweife, hier der Source aus dem Mime Type Detection Utility dazu:


 /**
* This is a quick check for the byte array to see if it contains binary data.
* As no known text encoding can have a character containing more than maxNullValues consecutive negative bytes
* method does a quick and dirty elimination of what are probably binary files but should never eliminate possible text files.
*
* It is possible that some binary files will not have maxNullValues consecutive byte
* values especially if it's a small file and will slip through here. Later tests should eliminate these.
*/
public static boolean isBinary(byte[] data) {
// No text file should have 2 or more consecutive NULL values
final int maxNullValues = 2;
int negCount = 0;

for(int i = 0; i < data.length; i++) {
if(data[i] == 0) {
negCount++;
} else {
negCount = 0;
}

if(negCount == maxNullValues) {
return true;
}
}

return false;
}

Dateityp ermitteln

Man bekommt es ja häufiger mal mit Daten zu tun, die in irgendwelchen Formaten vorliegen und verarbeitet werden wollen. Überlicher Weise sind Eingaben vor deren Verarbeitung auf ihre Richtigkeit zu prüfen. Werden Daten in einem bestimmten Format erwartet, ist eben auch festzustellen, ob die hereingereichten Daten auch diesem Format entsprechen. Tun sie dies nicht, können nicht passende Daten unmittelbar abgelehnt und eine passende Fehlermeldung formuliert werden.

Kommen die zu verarbeitenden Daten aus dem Dateisystem, kann eine Prüfung auf die Dateierweiterung schon einen oberflächlichen Anhaltspunkt liefern. Windows begnügt sich übrigens mit der oberflächlichen Formaterkennung, was durchaus zur Folge haben kann, dass eine Bilddatei als Text deklariert wird, weil die Dateiendung gerade nicht zum Datenformat der Datei passt.

In der Unix Betriebssystemwelt geben sich Programme hingegen ehr selten mit Dateiendungen ab. Die Identifikation des vorliegenden Datenformats findet hier anhand der Magic Bytes - also den ersten vier Bytes der Datei statt. Die ersten vier Bytes eines Jpeg komprimierten Bildes lauten zum Beispiel 0xff 0xd8 0xff 0xe0.

Dateiformaterkennung anhand der Magic Bytes ist für Software immer die erste Wahl, da die Prüfung viel präszierer ist, als die Dateiendung aus dem Filesystem. Spätestens, wenn beim Auslesen nur noch ein InputStream vorliegt, kommt man mit den Dateiendungen nicht weiter. So vermeidet man bereits präventiv, dass Daten auf einen Algorithmus losgelassen werden, für den diese gar nicht geeignet sind.

In der Praxis gibt es bereits fertige Bibliotheken, die sich um die Datenformaterkennung kümmern. Eingesetzt habe ich bereits die Mime Type Detection Utility, die bereits eine vielzahl an gängigen Datenformaten erkennen können.

Vor eine besondere Herausforderung wird eine Datenformaterkennungssoftware bei der Erkennung von Text gestellt. So wird bei UTF Kodierten Texten noch häufig die verwendete Byte-Reihenfolge (Big- oder Little-Endian) in die ersten zwei Bytes kodiert, spätestens bei ASCII ist aber schluß. Die Erkennung von ASCII erfordert also echte Kreativität. Mein erster Ideenansatz ging in Richtung Textanalyse - also zum Beispiel zu prüfen, ob ein Text ein übliches Maß an Leerzeichen enthält, was aber nur eine ungenügende Annäherung ist. Ein Blick in den Source des Mime Type Detection Utility förderte noch einen anderen Ansatz zu Tage. Dieses dreht die These um und prüft, ob es sich bei den gegebenen Daten um Binärdaten handeln könnte. Auch dies ist wiederum nur eine Annäherung, aber durchaus praktikabel. So kann bei erwarteten Textdaten zumindestens geprüft werden, ob es sich bei den gegebenen Daten eben NICHT um Text handelt.

Ohne lange Umschweife, hier der Source aus dem Mime Type Detection Utility dazu:
/**
* This is a quick check for the byte array to see if it contains binary data.
*
* As no known text encoding can have a character containing more than maxNullValues consecutive negative bytes
* method does a quick and dirty elimination of what are probably binary files but should never eliminate possible text files.
*
* It is possible that some binary files will not have maxNullValues consecutive byte
* values especially if it's a small file and will slip through here. Later tests should eliminate these.
*/
public static boolean isBinary(byte[] data) {
// No text file should have 2 or more consecutive NULL values
final int maxNullValues = 2;
int negCount = 0;

for(int i = 0; i &lt; data.length; i++) {
if(data[i] == 0) {
negCount++;
} else {
negCount = 0;
}
if(negCount == maxNullValues) {
return true;
}
}
return false;
}

Dienstag, 6. Oktober 2009

Linktip Lesestoff

Angelika Langer stellt eine Vielzahl ihrer Artikel zum online Lesen aus. Ihre Online-Artikel sind größtenteils deutschsprachig und befassen sich mit den Themengebieten Java Performance Tuning, Concurrent Programming, Java Generics, Enumeration Types, Closures und Core Java.


Hier geht es zum Lesestoff

Mittwoch, 26. August 2009

instanceof ist das goto von Java.

Die instanceof Abfrage ist bei guter Programmierung ebenso vermeidbar, wie das goto in anderen Sprachen. Ist man doch gezwungen auf eine Klasseninstanz abzufragen, sollte überlegt werden, ob nicht im Softwaredesign etwas umzustellen ist.

[Update 1.9.10]
Im übrigen lohnt sich ein Blick auf diesen Artikel, warum instanceof manchmal doch nicht so schlecht ist, wie man allgemein glaubt.

Samstag, 4. Juli 2009

Stream toByteArray()

InputStreams sind eine tolle Sache. Kann man mit Ihnen standardisiert Daten auslesen - ganz gleich woher, der Code zum Einlesen braucht auch dann nicht verändert zu werden, wenn die Daten von einer anderen Quelle kommen.


Kann man die Datehn aus dem Stream jedoch nicht linear verarbeiten, bietet es sich an, die Daten erst einmal in den Speicher zu kippen. Üblicher Weise liest man dafür zunächst die Bytes ein, um anschließend irgend eine verarbeitende Klasse damit zu füttern. Alternativ kann man sich auch mittels mark und reset auf dem Stream bewegen, Das ist aber nur dann wirklich sinnvoll, wenn die erwartete Datenmenge ein vernünftiges Maß überschreitet. Neben der Unhandlichkeit ist es eben auch nicht besonders performant auf diesem Wege zu arbeiten.


Um zum Punkt zu kommen, gibt es eine einfache und gängige Lösung, Daten aus einem InputStream in ein Bytearray zu lesen. Das Beispiel kopiert die Daten aus einem InputStream in einen ByteArrayOutputStream, dem man anschließend das Bytearray entnehmen kann.


  ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}

Diese Systematik sieht man sehr häufig. Im Grunde ist das eine einfache Kopierfunktion. Schlecht daran ist, dass die Daten zunächst in einen Puffer gelesen werden, dessen Inhalt anschließend weiterkopiert wird. Besser und schneller währe es, würde man die Daten direkt in das Ziel lesen. Leider ist die Gesamtmenge der Daten vor dem Auslesen nicht sicher zu ermitteln, weshalb die Größe des Zielbytearrays unbekannt ist. Für diesen Zweck habe ich die Klasse ByteArrayOutputStream erweitert und eine append Methode hinzugefügt, die Daten aus dem InputStream direkt in den Puffer des ByteArrayOutputStreams liest. Ist außerdem die Menge der Daten, die man der available Methode entnehmen kann, dicht an der Gesamtmenge oder enstpricht dieser sogar, läßt sich die Geschwindigkeit zum Einlesen um fast die Hälfte erhöhen. Bei einem FileInputStream erhält man via available() recht zuverlässig die Gesamtmenge der zu erwartenden Bytes, was unnötiges Zielpuffer vergrößern erspart.


    public class ByteBufferByteArrayOutputStream extends ByteArrayOutputStream {
ByteBufferByteArrayOutputStream() {
super(0);
}

public void attachBytesFromStream(InputStream in) throws IOException {
final int bufferSize = 2048;
final int available = in.available();
final int capacity = available > 0 ? available : bufferSize;

this.enlargeCapacityBy(capacity + bufferSize);
int read = 0;
while(read >= 0) {
super.count += read;
if(super.buf.length - count < bufferSize) {
this.enlargeCapacityBy(bufferSize);
}
read = in.read(super.buf, super.count, bufferSize);
}
}

private void enlargeCapacityBy(int size) {
byte newbuf[] = new byte[Math.max(buf.length << 1, super.buf.length + size)];
System.arraycopy(buf, 0, newbuf, 0, count);
super.buf = newbuf;
}

public ByteBuffer getByteBuffer() {
return ByteBuffer.wrap(super.buf, 0, super.count);
}
}

Weil das Einlesen immer in 2048 byte Schritten geschieht, ist das zugrundeliegende Bytearray am Ende etwas größer. Um trotzdem sinnvoll damit zu arbeiten wird das Bytearray in einen ByteBuffer gemapped, um anschließend komfortabel auf den Inhalt zugreifen zu können, ohne die überflüssigen 0 bytes am Ende berücksichtigen zu müssen. Benötigt man jedoch ein primitives Bytearray, kommt man um das Umkopieren leider nicht herum. Damit währe dann auch der Zeitgewinn hinüber.


Eine weitere flotte Möglichkeit währe da noch direkt auf den FileChannel zu gehen und die Datei via read(ByteBuffer) zu lesen. Dann kann man aber nicht mehr mit jeden x beliebigen InputStream verarbeiten.

Mittwoch, 17. Juni 2009

Programmfehler, eine Sache der Auslegung?

Wer kennt ihn nicht - den Programmfehler. Wird ein solcher aufgedeckt, geht nicht selten die Diskussion los, ob es denn nun ein Programmfehler oder etwas anderes, meist nicht näher definiertes ist. Programmierer sind da oftmals erfinderisch, geht es doch um ein Stück der Ehre und natürlich auch um die Sachkompetenz.

Besonders interessant ist der Umgang mit Fehlern in einem Programmierer/Kunden Verhältnis. Da kann der Programmierer nämlich tief in die Sachverhaltekiste greifen und in Erklärungsbereich vordringen, von denen der Normalmensch nicht die geringste Ahnung hat, ausgenommen er befasst sich nebenberuflich mit Themen wie Datenbanken, Transaktionssicherheit etc.

Ein ganz tolles Beispiel aus der Kategorie "Ausrede" ist mir heute beim Lesen der Antwort auf die Kleine Anfrage der FDP an die Bundesregierung mit dem Titel "Auswirkungen der Abwrackprämie" aufgefallen (PDF). Auf Seite sechs gibt es zur Frage, ob Antragsbestätigungen an falsche Adressen versendet worden seien die folgende Antwort:

Fehlleitungen von Eingangsbestätigungen sind nur zeitweise in einem geringen
Umfang von ca. 200 Fällen aufgetreten. Die Fehlleitungen sind darauf zurück-
zuführen, dass im Rahmen eines Serveraustausches der Hauptserver neu ge-
startet werden musste. Dadurch kam es in einzelnen Fällen zu einer doppelten
Vergabe von Antragsnummern. Ein Programmierungsfehler ist damit ausge-
schlossen. ...

Einen "Programmierungsfehler" würde ich bei der mehrfachen Nummernvergabe und dem Durchmischen mit den vorherigen Antragsnummerninhabern zumindest nicht kategorisch ausschließen. Wie es zu diesem offiziellen Statement wohl gekommen sein mag? Ich könnte mir so einen aufgebrachten Regierungsbeamten vorstellen, der sich bei dem beauftragen Dienstleister meldete und man dort - um Schadensbegrenzung bemüht - schnell etwas abstraktes, etwas, was irgendwie im Zusammenhang mit dem Fehler stand, aber eigentlich mehr nach "Höherer Gewalt" klingt, als Erklärung ab gab.

Der Bundesregierung lege ich mal den Wikipedia Artikel zu Programmfehler ans Herz. Die Erkenntniss dürfte durchaus erhellend sein, dass nahezu alles an einer Software, was nicht erwartungsgemäß funktioniert, ein Programmfehler ist. Auf der anderen Seite finde ich es schon sympatisch, dass man meint, dass eben keiner Schuld hat.


Samstag, 6. Juni 2009

Quaqua Look and Feel 5.2.1

Wer seiner Anwendung mehr Mac OS X Feeling verpassen möchte ist mit dem Quaqua L&F gut beraten. Das ganze läuft auch unter nicht OS X Betriebssystemen. Zusätzlich zum L&F kommen  noch die beiden Komponenten JBrowser und JSheet hinzu.

Will man seine Anwendung so richtig OS X mäßig herausputzen, bieten sich außerdem noch die "Mac Widgets for Java" an, über die ich bereits berichtet hatte.

via Java Insel Blog

Mittwoch, 3. Juni 2009

Yahoo! Stencil Kit v1.0

In der Yahoo! Design Pattern Library gibt es mit dem Stencil Kit eine ansehnliche Vorlage für diverse Webelemente. Bei dem Stencil Kit geht es mal nicht um Fertiggrafiken zum schmücken der Anwendung, sondern viel mehr um ein visuelles Gesamtkonzept für ansprechend gestaltete Webanwendungen.

Das Ganze steht unter CCL und liegt in den Formaten OmniGraffle, Visio (XML), PDF, PNG, SVG vor.

Link: http://developer.yahoo.com/ypatterns/wireframes

Mittwoch, 13. Mai 2009

Freie Icons für freie Software

icon_imageWer seine Software mit einer Benutzeroberfläche versieht, benötigt das Eine oder Andere Icon. Problematisch ist hierbei immer die Lizensierung. Die Zeit in der sich niemand daran gestört hat, wenn man halt irgendwelche Bilder aus dem Web genommen hat, sind lange vorbei. Andererseits gibt es für Entwickler von freier Software heutzutage einen Pool an qualitativ hochwertigen und freien Bildern. Hier noch ein paar Quellen mit zumeist CCL oder GPL Lizensierten Icons.


Icon Finder: http://www.iconfinder.net
Tango Desktop Projekt: http://tango.freedesktop.org
famfamfam: http://www.famfamfam.com
Wikimedia Iconsets: commons.wikimedia.org


[Update]

Eine weitere Suchmaschine für freie Icons: http://www.iconlet.com

[Update 2]

Flavours IconSet: http://www.smashingmagazine.com/2009/01/23/friday-freebies-flavours-icon-set-and-cute-tweeters-icon-set/

You can freely use it for both your private and commercial projects.

Flavour Extended IconSet: http://www.addictedtocoffee.de/

Montag, 11. Mai 2009

Google Collections

Die Google Collections bieten inzwischen eine recht ansehnliche und interessante Auswahl an. Besonders interessant für Caching Funktionen ist die MapMaker Klasse. Die bringt nämlich gleiche eine Unterstützung für Soft- und Weak Referenzen sowie eine zeitliche Haltegrenze mit.

Softreferenzen gibt es seit Java 1.2 und werden so lange vom Garbage Collector verschont, wie sie nicht anderweitig referenziert werden und der Speicher ausreicht. Wird der Speicher knapp, werden die über Softreferenzen referenzierten Objekte weggeräumt.

Weakreferenzen gibt es ebenfalls seit Java 1.2. Die von Weakreferenzen referenzierten Objekte werden immer dann vom Garbage Collector entfernt, wenn die referenzierten Objekte an keiner anderen Stelle mehr referenziert werden. Grundsätzlich gilt für die Soft- wie auch für die Weak Referenz, dass nur weggeräumt wird, wenn keine "stärkere" - also "normale" Referenz mehr vorhanden ist.

Der Timeout für Objekte in der MapMaker Klasse ist interessant, wenn auch nicht so locker einsetzbar, wie man auf den ersten Blick zu meinen glaubt. Der Timeout wird nämlich in einem statischen Zeitrahmen vergeben. Man kann also festlegen, das ein Objekt für eine fixe Zeit von z.B. 10 Minuten gehalten werden soll. Das macht aber nur dann wirklich sinn, wenn die Anwendungslogik das hergibt - man also weiß, dass Objekte tatsächlich nach einer bestimmten Zeit mit hoher Warscheinlichkeit nicht mehr benötigt werden. Werden die Objekte auch nach der fixen Zeit doch noch benötigt, heißt das, dass diese neu gebaut werden müssen. Interessant wird der MapMaker vor allem in Kombination mit Weak- und Soft Referenzen. Man kann also z.B. festlegen, dass Objekte nur so lange im MapMaker verweilen, wie sie keine "stärkeren" Referenzen mehr haben, jedoch auch nicht länger als 10 Minuten.

Benötigt man nur eine HashMap mit Weak Referenzen, bietet sich übrigens auch die java.util.WeakHashMap an, die es seit Java 1.4 gibt.

Beispiel:


 ConcurrentMap graphs = new MapMaker()
.concurrencyLevel(32)
.softKeys()
.weakValues()
.expiration(30, TimeUnit.MINUTES)
.makeComputingMap(
new Function() {
public Graph apply(Key key) {
return createExpensiveGraph(key);
}
});

Links: Google Collections, MapMaker (Javadoc)

Dienstag, 5. Mai 2009

case default:

Wird ein Programmierer Monate oder gar Jahre später gefragt, weshalb er Dinge so implementiert hat, wie sie später geworden sind, hat man eine gute Chance auf die Antwort "Das ist historisch so gewachsen". Mögliche Interpretationen dieser Antwort könnten diese sein:

1. Ich habe nicht mehr die geringste Erinnerung an diesen Code.
2. Das wurde damals aus Zeitdruck so hingeschludert und später hat sich keiner mehr dran getraut.
3. Keine Ahnung - das habe ich damals mal eben aus dem Internet kopiert und refaktorisiert.
4. Damals hielt ich das für eine gute Idee - später nicht mehr.
5. Inzwischen haben da so viele Leute dran rumgeschrieben, dass ich nicht mehr dir geringste Ahnung habe, was da überhaupt passiert.
6. Das war saukompliziert - machs doch besser!

Warum man immer Klammern setzen sollte

Häufiger treffe ich auf Code, bei dem sich der Programmierer zu schade war ein if durch Klammern einzugrenzen. Mir als gewohnten Klammersetzer fällt das beim Querlesen nicht selten erst auf den zweiten Blick auf. Ich kann mich gut an einen Fall erinnern, in dem ich eine Zeile an eben solch einem klammerlosen if einfügte und die Ergänzung in den nicht vorhandenen Klammern verortet sah. Anschließendes Wundern vorprogrammiert. Hier noch ein Beispiel - Welcher Fall trifft in der zweiten Ausgabe zu?



if (a)
if (b)
System.out.println("a und b sind true");
else
System.out.println("What is here?");

Sonntag, 3. Mai 2009

Links

The Java CIFS Client Library (jCIFS) ist eine Javaimplementierung des CIFS/SMB Netzwerkprotokolls.

Java Native Access (JNA) erlaubt die Verwendung nativer Bibliotheken ohne den ganze JNI Rattenschwanz. Neben Windows wird auch Linux und OSX unterstützt. Als Alternative - allerdings nur mit Windows Support - gibt es noch die Native Library Linker (nlink) Bibliothek.

furbelow kann man sich aus dem SVN Repository bei Sourceforge auschecken. Die Klassen sind gut dokumentiert und bestehen aus einm Zoo nützlicher Dinge für den Swingschrauber.

Und zuletzt noch einen Link zum Swingworker Blog, auf dem es allerlei nützliche Controls gibt. Darunter die Komponenten JWizard, JTitleSeparator, JPopupButton und die JMonthBox.

Donnerstag, 30. April 2009

Weißheit des Tages

Wenn Menschen etwas geändert haben möchten, fällt es ihnen leicht zu erklären, was ihnen am aktuellen Zustand nicht gefällt, aber sind oft nicht in der Lage zu beschreiben, wie sie es denn konkret gern hätten.

Samstag, 25. April 2009

Swing GUI Builder

Für die Entwicklung von Swing Anwendungen finde ich einen GUI Builder eine recht angenehme Sache. Man erhält zu Beginn der GUI-Entwicklung recht flott ansehnliche Ergebnisse und später muß man sich für kleinere Änderungen nicht durch den oft ewig langen GUI Code wühlen. Vor allem, wenn eine vielfalt an Komponenten in einem GridBagLayout versammelt sind, ist nachträgliches Ändern mit einiger Lesearbeit verbunden. All das kann ein GUI Builder vereinfachen.

Letztes Jahr habe ich nach langem wieder einmal mit einem neuen Swing Projekt begonnen. Da stand also als erstes die Frage nach einem vernünftigen GUI Builder im Raum. Früher habe ich das mit dem Netbeans eignenen GUI Builder Matisse gemacht. Dieses malsollte die Entwicklung jedoch mit Eclipse vonstatten. Ein Rundumblick freier Swing GUI Builder Plugins ließ aber recht schnell Ernüchterung einkehren. Die Auswahl ernst zu nehmender Plugins ist recht übersichtlich.

Zunächst habe ich mich dem Eclipse VEP befasst. Nach dem ich den Abhängigkeitszoo endlich im Griff hatte und das gute Stück in Augenschein nehmen konnte, dominierte vor allem das Gefühl der Enttäuschung. Trägheit und Bugs an allen Ecken und Enden haben mich das Plugin schnell ins Jenseits befördern lassen.

Das Jigloo Plugin, das ich mir als nächste vorgenommen habe, konnte mich ebenfalls nicht so recht überzeugen. Als angenehm habe ich das Arbeiten damit jedenfalls nicht empfunden und auch hier eine Vielzahl von Unzulänglichkeiten entdeckt. Beide GUI Builder scheinen mir erheblich besser für SWT als für die Swing Entwicklung geeignet zu sein. Also ging die GUI Entwicklung doch wieder mit Netbeans/Matisse vonstatten. Matisse verwendet XML-Daten und generiert daraus den Javacode - hat also nicht den Anspruch mit Livecode zu arbeiten, wie VEP und Jigloo. Letztere verplempern mit dem Livecode während des Bearbeits einiges an Zeit. Manuelle Änderungen am Code haben dann auch gleich spührbare Wartezeiten zur Folge.

Einige Zeit später bin ich noch auf das Eclipse Plugin Matisse4Eclipse gestoßen. Das Plugin basiert auf Netbeans Matisse, wurde jedoch für Eclipse umgeschrieben. Matisse4Eclipse ist eigentlich Bestandteil der kommerziellen MyEclipse Enterprise Workbench, läßt sich jeodch auch einzeln installieren. Matisse4Eclipse ist sehr flott, bringt aber leider einige Features des Orginals nicht mit. Währen Netbeans/Matisse die eingegebene Texte und Images gleich lokalisiert ablegt, muß diese Arbeit bei Matisse4Eclipse von Hand gemacht werden, was auch gleich zur Folge hat, dass die Komponenten im Designer keine Texte/Bilder anzeigen, sondern nur auf "user code" hinweisen. Weiteres Manko sind die wenig unterstützden Refactoring Möglichkeiten. Das umbenennen der Javaklassen hat zwar auch gleich die passende Auswirkung auf die dazugehörige Form-XML Datei, damit ist dann aber auch schon schluß mit den Möglichkeiten. Packages umbenennen, in denen sich eine Form-XML befindet, schlägt grundsätzlich fehl. Beim Umbennen oder Verschieben von Klassen werden die Referenzen in den Form-XML Dateien nicht mitgezogen. Hat man sich daran gewöhnt, sind es eben immer ein paar Handgriffe mehr, die man ausführen muß, um zu refaktorisieren.

Ebenfalls unangenehm aufgefallen ist mir die fehlende Unterstützung des ApplicationFramework, dass Netbeans/Matisse einem automatisch aufdrängt. Ganz Rund ist die Sache also nicht - bestenfalls ein Kompromiss. Die Kombination aus Eclipse und Matisse4Eclipse finde ich trotz alledem noch halbwegs angenehm. Alles in allem drängt sich mir aber das Gefühl auf, dass in Saceh Swing Builder seit langem nicht mehr viel passiert ist.

Links:
http://www.myeclipseide.com/
http://www.cloudgarden.com/jigloo/
http://www.eclipse.org/vep/WebContent/main.php

Effekthascherei für Swing

Wer schon immer neidisch auf die OSX GUI geschielt und sich geärgert hat, dass es die superbunten Effekte nicht auch für Swing gibt, dem wird das Swing-Bug Projekt mit sicherheit gefallen. Sieht man davon ab allzuviele Elemente in der JCarousel Komponente (s. Abbildung) einzufügen, funktioniert das ganze auch sehr flüssig. Das Swing-Bug Projekt bringt übrigens noch einiges mehr an Komponenten zum spielen mit.

Link: https://swing-bug.dev.java.net/

Mittwoch, 22. April 2009

Ein ♥ für Blogs

ein-herz-fuer-blogsStylespion hat sich vorgenommen die Linkkultur in Blogs ein wenig zu fördern und die Aktion "Ein Herz für Blogs" ins Leben gerufen. Die Idee finde ich gut. Deshalb nun meine deutschsprachigen Lieblingsblogs:


Das Fischblog beschäftigt sich auf eingängige Weise mit Naturwissenschaftlichen Themen. Ich finde die Beiträge angenehm zu lesen und auch für mich als weniger bedarften dieses Themas, gut verständlich.


Meine regelmäßige Portion Wirtschaft entnehme ich dem Blog von Egghat, der sich schwerpunktmäßig auf die US Wirtschaft bezieht, aber eben nicht nur.


Das Blog von Peter Kröner befasst sich mit Webdesign und Technik. Interessant finde ich hier vorwiegend die Artikel zum Thema CSS.


Donnerstag, 16. April 2009

Dateien kopieren

geht Häufig ist es bisher nicht vorgekommen, dass ich von einer Anwendung aus Dateien kopieren wollte. Auf die Frage, wie man das macht, hätte ich spontan den üblich Algorithmus wiedergegeben und auf die apache FileUtils verwiesen.


  byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}

Es geht aber auch besser - nämlich via FileChannel. Die FileChannel setzen weiter unten an und bieten ein paar Möglichkeiten zum Dateihandling auf nativer Ebene an, was dann etwas performanter vonstatten geht. Ein Beispiel, was ich hierzu gefunden habe:


public static void copyFile(File sourceFile, File destFile) throws IOException {
if(!destFile.exists()) {
destFile.createNewFile();
}

FileChannel source = null;
FileChannel destination = null;
try {
source = new FileInputStream(sourceFile).getChannel();
destination = new FileOutputStream(destFile).getChannel();
destination.transferFrom(source, 0, source.size());
}
finally {
if(source != null) {
source.close();
}
if(destination != null) {
destination.close();
}
}

Quelle javalobby

Donnerstag, 2. April 2009

Swing API Links

Und wieder einmal ein paar Links für alle Swing Schrauber.

The DJ Project
Hat sich ähnlich dem JDict Projekt dem Einbau nativer Komponenten in Swingverschrieben. Mit der Version 0.9.8 gibt es die folgenden Komponenten: JWebBrowser, JFlashPlayer, JVLCPlayer, JHTMLEditor, JSyntaxHighlighter, JWMediaPlayer (win32). Außerdem kommen noch ein paar kleinigkeiten, wie Thumbnail Creation oder File type associations mit. (Link)

Rubber Band
Erweiter die Java Komponenten JList, JTable und JTree um ein Rubber Band, mit dem der Benutzer ziemlich bequem eine Mehrfachauswahl tätigen kann. Ich finde das immer noch eine der besseren Selektionsmöglichkeiten. Schade das sich das nie wirklich in der UI Programmierung etabliert hat. (Link)

TreeWrapper
Ein netter Wrapper, der die am häufigsten benötigten Drag and Drop Features implementiert. (Link)


Donnerstag, 26. März 2009

Kaffee Klatsch

Großartigen Lesestoff für all diejenigen, die mit Softwareentwicklung zu tun haben. Kaffee Klatsch heißt das Magazin rund um das Thema Softwareentwicklung. Das Magazin kann kostenlos als PDF abonniert werden. Ansonsten einfach mal einen Blick in das Online Archiv werfen.

Link:
Kaffee Klatsch - Das Magazin rund um Software-Entwicklung

Mittwoch, 25. März 2009

Remote JBoss Client Development

Will man mit einem JBoss Client auf eine entfernte JBoss Applikation zugreifen, kann man das wunderbar mit ein paar SSH-Tunnel und einem Loopback Netzwerkinterface machen.

Zunächst die TCP Tunnel (local->remote) 1098 und 1099 sowie 4443 und 4444 zum JBoss Server aufbauen. Testen am besten per Telnet auf die Ports. Leider ist das nur die halbe Miete, weil die IP der Maschine, wo der JBoss läuft, noch nicht erreichbar ist. Das lässt sich aber umgehen, in dem man einen Loopback Netzwerkinterface einrichtet, das die IP der JBoss Maschine auf den localhost, wo die Tunnel auf Verbindung warten, weiterreicht.

Für Windows bietet sich die Kombination von Putty und dem Microsoft Loopback Adapter an, den man einfach als Netzwerkkarte einbinden kann.

Links:
Einrichten des Loopbackadapters: http://support.microsoft.com/kb/839013
Einrichten von Putty Tunnel: http://realprogrammers.com/how_to/set_up_an_ssh_tunnel_with_putty.html

Samstag, 7. März 2009

Niemals mit den Datentypen Float oder Double Geldbeträge berechnen!

Was für Tücken die Berechnung von Geldbeträgen mit Fließkommazahlen hat, erklärt Markus Kühle in einem sehr anschaulichen Beispiel, das es auch nicht an Unterhaltungswert mangeln lässt.

javathreads.de

Freitag, 6. März 2009

Bildinhalte erkennen

Bildinhalte von Computern erkennen zu lassen entbehrt nicht einer gewissen Faszination. Die Gesichtserkennung ist seit Jahren ein nicht enden wollendes Thema. Sehr interessant dazu ist OpenCV. Das Projekt vereint eine Vielzahl von Algorithmen und zeichnet sich durch gute Performance aus. Ein JNI zu den C/C++ Bibliotheken gibt mit dem Java OpenCV MatchTemplate oder dem Face Detection Library for Processing (PC) Projekt.

Zum Thema gibt es außerdem noch die Java API Face Recognition, die den Eigenfaces Algorithmus für die Gesichtserkennung einsetzt.

Weitere Infos zum Thema im Linux Magazin.

Links:
OpenCV Wiki
OpenCV Download

[Update]

Ebenfalls eine sehenswerte Java Implementierung ist The Face Annotation Interface (faint). http://faint.sourceforge.net/


[Update 2]

Sonntag, 1. März 2009

Versteckte Schätze

Egal in welches Gebiet man sich vorwagt, es gibt für eigentlich alles eine mehr oder weniger gut geeignete Java API. Es ist nur nicht immer ganz einfach eine passende zu finden. Zum Manipulieren von EXIF Bilddaten bin ich vor einiger Zeit auf die Sanselan API gestoßen. Ganz zufrieden war ich damit jedoch nie. Mangelnde Dokumentation, komplizierte Bedienung und die kontinuierliche Verweigerung, die in Jpeg EXIF eingebettete Thumbnails zu laden, waren einige Eigenheiten, die mir nicht gefallen haben. Durch Zufall ist mir gestern eine gut verteckte API in die Finger geraten, die durch Einfacheit besticht, die Thumbails lädt und die EXIV Daten auch wieder zurückschreiben kann. Eine Dokumentation existiert zwar scheinbar nicht, aber die API ist nahezu selbsterklärend. Gefunden habe ich dieses Goldstück im Java Image Manager (Jim) Projekt - einem Bildverwaltungsprogramm, das auf den ersten Blick mit einer ehr gewöhnungsbedürftigen Oberfläche und wenig Funktionsumfang daherkommt. Ein Blick ins Innere hat sich dafür umso mehr gelohnt. Die jim-io.jar, die mit dem Programm mitkommt, enthält so ziemlich alles, was ich von einer solchen API erwarten würde und auch der Sourcecode ist wieder mit dabei. Bleibt nur noch zu hoffen, dass sich keine schwerwiegenden Bugs finden, die mir die Freude über diesen Fund wieder nehmen. Hier noch ein paar Codefragmente zum Umgang mit jim-io.


    public Metadata readMetadata(File imageFile) throws MetadataException {
final JpegReader reader = new JpegReader();
final Metadata metadata = reader.readImage(imageFile);
final Iterator directoryIterator = metadata.getDirectoryIterator();

while (directoryIterator.hasNext()) {
Directory directory = directoryIterator.next();
if(directory instanceof ThumbnailTiffDirectory) {
byte[] thumbnailData = ((ThumbnailTiffDirectory)directory).getThumbnailData();
}
System.out.println(directory.getName());
Iterator tagIterator = directory.getTagIterator();
while (tagIterator.hasNext()) {
Tag tag = tagIterator.next();
System.out.println(tag.getTagName() + "="+ tag.getDescription());

}
}
return metadata;
}

public void updateMetadataTag(Tag tag, Object value) {
tag.update(value);
}

public void writeMetadata(Metadata metadata, File output) throws JpegProcessingException {
JpegWriter writer = new JpegWriter();
writer.writeImage(metadata, output);
}

Update Die Library entstammt eigentlich aus dem Metadata Extractor Projekt. Dank der Refactorisierungsmöglichkeiten moderner IDEs war das allerdings nicht mehr wirklich ersichtlich.

Update 2
Ergänzende Links zum Thema Exifdaten:
http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html
http://commons.wikimedia.org/wiki/Commons:Manipulation_von_Metadaten

Dienstag, 24. Februar 2009

Namespace abgrenzen

Über eine interessante Schreibweise bin ich neulich gestoßen. Nämlich die, den Namespace für lokale Variablen innerhalb einer Methode zu begrenzen:

public void test() {

{
String s = "test";
//... tu was mit dem String
}

// String s ist hier nicht mehr im Zugriff.
}

Mit dieser Schreibweise lassen sich Variablen voneinander abgrenzen, in dem diese nur für einen bestimmten Bereich der Methode sichtbar gehalten werden. Fängt man aber mit einer funktionalen Abgrenzung innerhalb einer Methode an, scheint es mir eher angebracht, diese Bereiche, die ohnehin einen eignen Namespace erhalten, gleich in eine neue Methode auszulagern, was gleichzeitig die Chance birgt, der Methode einen sprechenden Namen zu geben und damit die Lesbarkeit zu verbessern. Außerdem erhöht man damit die Wahrscheinlichkeit, dass wer anders im Team die Methode findet und Wiederverwendet, anstelle eine eigene neu zu schreiben. Nach einigem Abwegen habe ich für mich jedenfalls entschieden, dass ich diese Schreibweise nicht mag.

Samstag, 21. Februar 2009

Apache Betwixt

In meinem vorherigen Beitrag Konfiguration für Clientanwendungen bin ich bei der Apache Betwixt Library hängen geblieben. Mit Betwixt kann man recht ordentlich Javaklassen in XML und wieder zurückwandeln. Inzwischen bin ich auch dazu gekommen Betwixt mal einzusetzen. Ansich funktioniert die wirklich gut. Was allerdings im Nachhinein praktisch gewesen währe, währe eine Unterstützung für Annotaions, um die zu behandelnden Setter/Getter zu markieren. So werden beim Wegschreiben alle Methoden behandelt, die mit get beginnen und bei der Rückwandlung finden die passenden setter Verwendung. Außnahmen gibt es keine.

Ein großes Manko ist mir allerdings noch aufgefallen. String Arrays werden zwar korrekt weggeschrieben, die Rückwandlung funktioniert jedoch wenig gut. Als Alternative bleibt also doch nur wieder ein String mit Separator, den man später auseinanderschneidet. Dafür gibt es aber auch was bequemes aus der Apache Commons Library. Zum auseinanderschneiden: StringUtils.split("Eintrag1;Eintrag2", ';') und zum Zusammenfügen: StringUtils.join(String[] {"Eintrag1", "Eintrag2"}, ';'). Klarer Nachteil, neben der zusätzlichen Schreibarbeit, dass man das Trennzeichen mit Bedacht wählen sollte. Sonst hat man bei einer Benutzereingabe plötzlich einen Eintrag mehr als gewünscht. Alles in allem nicht optimal, aber für meine Zwecke wird es wohl ausreichen. Zumindestens kann sich so recht bequem eine hierarchische Konfigurationsstruktur erstellen.

Donnerstag, 19. Februar 2009

Linktips

Mastering Eclipse V3.4, Part 3: JDT text editor tips and tricks enthält auch für den geübten Eclipse Anwender   durchaus neues. Jedenfalls kannte ich "Automatically create locals" und "Breadcrumb bar" noch nicht. Oft ist man auch so eingefahren in seinem Nutzungsverhalten, dass man Neuerungen gar nicht mehr wahr nimmt. Die "Breadcrumb bar" gibt es erst seit Eclipse 3.4. Vermutlich der Grund, warum ich die noch gar nicht wahr genommen habe. Bei uns ist Eclipse 3.2 noch das höchste der Gefühle.

Top 25 Most Dangerous Programming Errors
ist eine Zusammenstellung von Klassikern der Programmierfehlerkunst, nur neu aufgelegt. Einige gefährlichen Programmierfehler, die SANS da nennt, sind für Javaprogrammierer aber ohnehin irrellevant.

L2FProd-Common Components bietet ein paar Komponenten, die man vor allem auch aus der Windowswelt kennt. Von früher kannte ich da noch das Skin Look And Feel. Common Components ist zwar nicht neu, aber absolut empfehlenswert für GUI Schrauber. Der JDirectoryChooser ist jedenfalls eine sehr nützliche Komponente und scheint gut zu funktionieren.

Mittwoch, 18. Februar 2009

Mac Widgets for Java

Wieder einmal was für Swing Liebhaber: mac widgets stellen die OS X üblichen Komponenten auch für Java/Swing zur Verfügung. Die Komponenten wurden vollständig in Java implementiert, so das diese auch plattformunabhängig funktionieren sollten. Version 0.9.4 (17.02.09)

Promo Abbildungen:

         


Mittwoch, 11. Februar 2009

Die unliebsamsten Dinge der Softwareentwicklung

Es gibt ja Sachen, die macht kaum ein Softwareentwickler gern und werden schnell vernachlässigt oder kurzerhand weggelassen. Hier die Top 6:

1. Dokumentation - Ganz gleich ob Code- oder Benutzerdokumentation. Die Benutzerdokumentation sollte eigentlich ohnehin nicht der Entwickler machen, häufig ist dem aber so. Entsprechend sieht auch das Ergebnis aus. Gute Codedokumentation sieht man noch seltener.

2. Testen - Tests schreiben kostet Zeit und erscheint unnötig, weil es Funktioniert ja alles. Die Nützlichkeit fertiger Tests tritt erst dann zutage, wenn im laufe der Fehlerbeseitigung weitere Fehler eingearbeitet werden. Das kann zu einer sehr langwierigen Fehlerbeseitigungskette führen, die der Kunde selten gern hat. 

3. Datenschutz - Sehr unliebsam, weil stört nur den Produktivitätsprozess des Entwicklers und scheint zunächst gar nicht wichtig, weil sieht ja keiner von außen.

4. Sicherheit - Nur wenige Entwickler machen sich Gedanken um die Sicherheit ihrer Software. Auch hier bemerkt ja zunächst niemand etwas und es macht mühe sich in der laufenden Entwicklung auch darüber noch Gedanken zu machen. Rein Funktional ist die Sicherheit ja egal.

5. Usability - Eine Oberfläche wird gern mal schnell hingestrickt, damit der Anwender die supergeilen Programmfunktionen auch benutzen kann. Es reicht leider nicht aus, mal eben ein paar Icons beim Grafikdesigner anzufordern. Ein echtes Usability Konzept ist bei vielen Projektentwicklungen nicht anzutreffen.

6. Kommunikation - Besonders die mit dem Kunden ist besonders lästig. Der Entwickler ist während des gesamten Kundengesprächs damit beschäftigt dem Kunden das auszureden, was der sich vorstellt oder, was ihm der Vertrieb vorher versprochen hat. Häufig kommt der Kunde auch noch auf Punkt 1-5 zu sprechen, was es dann abzuwiegeln gilt.

Top Ausrede des Softwareentwicklers ist übrigens der Zeitdruck - den es zweifelsfrei gibt! Auf der anderen Seite kosten einige der oben genannten Punkte im nachinein noch viel mehr Zeit. Sehr empfehlenswert dazu: Extreme Programming

Technorati-Tags: , , , , , , , ,

Dienstag, 10. Februar 2009

l2fprod commons PropertySheet

Das l2fprod commons Projekt enthält unter anderem eine PropertySheet Komponente. Nach dem ich ein paar Properties eingerichtet habe, die aufzuklappen sind, fehlte mir natürlich auf Anhieb ein feature - nämlich alle Einträge direkt nach der Initialisierung aufzuklappen. Hier stellt sich dann auch mal wieder der Vorteil von Open Source heraus - die Sourcecodes sind im Lieferumfang enthalten. Ein wenig Suchen und eine kurze Methode zum PropertySheetTable hinzugefügt, und schon ist alles in Butter. Das ganze sieht dann so aus:

  public void expandAll() {
      final PropertySheetTableModel sheetModel = getSheetModel();
      int rowCount = sheetModel.getRowCount();

      for (int i = 0; i < rowCount; i++) {
          final Item item = getSheetModel().getPropertySheetElement(i);
          if(!item.isVisible() && item.hasToggle()) {
              item.toggle();
              rowCount = sheetModel.getRowCount();
          }
      }
  }


Technorati-Tags: , , ,

Arbeitsalltag Kundenwünsche

Bekomme ich heute einen Bug/Kundenwunsch für ein Projekt rein, das ich bereits seit einigen Jahren betreue. Wird die Anwendung beendet, erscheint üblicher Weise ein Beenden Dialog. Sind eingegebene Daten noch nicht gespeichert, erscheint eine Speicherabfrage, jedoch der Beenden Dialog nicht mehr. Klingt zunächst nach einem Bug. Ist aber kein Bug, sondern ein Feature, was der Kunde ausdrücklich haben wollte. Jetzt wird beim Kunden erst einmal Nachgeforscht, wer das damals entschieden hat und warum das so sein sollte. Für mich ist der Kommunikationsoverhead jedenfalls erheblich größer, als der das Flag rauszunehmen.

Donnerstag, 22. Januar 2009

Es wird gespeichert

Unerwarteter Weise habe ich doch noch eine Antwort auf meine E-Mails von 1und1 erhalten. Kurz und Knapp schreibt mir die Datenschutzbeauftragte:

Der Gesetzgeber hat uns gem. § 113a TKG dazu verpflichtet, die
Verbindungsdaten für einen Zeitraum von sechs Monaten zu speichern.

Nicht, dass ich eine andere Antwort erwartet hätte. Jetzt kann ich mir aber zumindestens sicher sein - Big Brother ist über meinen Mailverkehr informiert, weiß wann ich online war und mit wem ich telefoniert habe. Zu der Frage, was nun gespeichert wird, habe ich viele, sich gegenseitig wiedersprechende Inhalt im Netz gefunden. Das BMJ fasst das Thema recht kurz, leicht verständlich und selbstbeweihräuchernd zusammen. Unsere Helden der Politik haben es der EU nämlich gegeben, in dem Sie die Mindestspeicherdauer auf 6 Monate beschränkt und die Speicherung von Webadressen nicht umgesetzt hat. Pünktlich zur praktischen Umsetzung der Speicherung scheint man über letzteres aber auch nicht mehr so glücklich zu sein (Link).

Montag, 5. Januar 2009

Konfiguration für Clientanwendungen

Jetzt ist mir das schon mehrfach passiert. Man programmiert mal eben ein Minniprogramm, das konfigurierbar sein soll. Je nach Anforderung werfe ich die Konfigurationsparameter eben per Kommandozeile mit rein oder benutze eben die System Properties alá System.getProperties().load(InputStream). Beides basiert auf dem Key/Value prinzip, was aber schnell mal umständlich werden kann, wenn man zum Beispiel eine Auflistung als Wert zu einem Key haben möchte. In meinem Fall müssen eine vielzahl von Pfaden einem Parameter zugeordnet werden. Soweit auch nicht weiter wild. Das kann man ja einfach mit einem Trennzeichen machen und das ganze dann auseinanderschneiden. Will man aber zu jedem Pfad noch weitere Eigenschaften reinreichen, wirds unhandlich.

Ich habe mir schon vor längerer Zeit mal überlegt was zu schreiben, mit dem ich komfortabel Konfigurationsdateien erstellen kann. Gekommen bin ich dazu freilich nie. Da nun das Problem wieder einmal aktuell geworden ist, und es ja schließlich nix gibt, wofür nicht irgendeine Javalibrary existiert, habe ich mich mal auf die Suche gemacht. Mir schwebte da was vor, womit ich Konfigurationsobjekte hierarchisch lesen und schreiben können wollte.

Als allererstes stößt man da natürlich auf IoC Container wie Spring. Damit läßt sich so ziemlich alles machen, was ich mir vorgestellt habe und noch ganz viel mehr, was ich allerdings gar nicht benötige. Zwar sehr interessant und sicher lohnenswert sich da mal einzuarbeiten, aber für meine Zwecke zu umfangreich.

Anschließend habe ich mir das Obix Framework mal angesehen. Leider ist die Dokumentation sehr dünn. Zumindestens kann Obix auch Collections komfortabel verwalten, was über die Fähigkeiten der System.properties schon mal hinaus geht. Die Konfiguration legt Obix dann im XML-Format ab.

Recht vielversprechend sieht das Apache Configuration Projekt aus. Damit lassen sich Objekte aus einer XML-Datei herstellen und Eigenschaften aus Properties oder Windows .ini Dateien auslesen. Will man nun aber mehr als nur Eigenschaften haben, also fertige Konfigurationsobjekte, kommt man um eine XML-Beschreibung des Objektes nicht umhin. Da ließe sich mit Xdoclet sicher was machen.

Letzendlich hängen geblieben bin ich bei dem Apache Betwixt Projekt. Dieses kann Objekte, die sich an das Javabean Naming halten, in XML schreiben und auch wieder herstellen. Das ganze dann auch noch ohne XML Beschreibung und einer API wie sie einfacher nicht sein könnte. Das ganze funkltioniert auch dann noch gut, wenn die Javabean weitere Javabeans enthält. Nach einigem rumspielen und Tests, werde ich Betwixt wohl erstemal benutzen. Der Ansatz zur Konfigurationsverwaltung mittels Javabeans ist auf jeden Fall sehr angenehm zu programmieren und auch die Erweiterung ist einfach. Einfach eine getter/setter Methode dazu tun, und schon hat man eine Eigenschaft mehr.


Samstag, 3. Januar 2009

Über eine Map Iterieren

Wenn ich alle Einträge einer Map durchlaufen wollte, habe ich für gewöhnlich das KeySet der Map hergenommen, einen Iterator geholt und dann drüber gelaufen:

        for (Iterator it = map.keySet().iterator(); it.hasNext();) {
            Object key = it.next();
            Object value = map.get(key);
        }

Das geht allerdings (in dieser Form seit Java 1.5) auch einfacher. Nämlich in dem man anstelle des KeySet das EntrySet verwendet:

        for (Map.Entry entry : map.entrySet()) {
            entry.getKey();
            entry.getValue();
        }


Diese foreach Konstruktion finde ich sehr angenehm und ich könnte mich glatt daran gewöhnen. Leider muss ich teilweise noch immer Java 1.4 kompatiblen Code schreiben.