Wikitext-Darstellung mit Tapestry5

Bietet eine Webanwendung die Eingabe langer Texte an, so sollte dem Benutzer auch die Möglichkeit gegeben werden, solche Texte zu strukturieren oder zu formatieren. Dazu kann man natürlich HTML als Eingabe zulassen. Dies hat jedoch zweierlei Implikationen: Zum einen muß der Anwender HTML können, zum anderen öffnet man durch das Zulassen der Eingabe von HTML-Code auch ein Einfallstor für Angriffe. Es gibt jedoch eine Alternative: Wikitext. Hierbei handelt es sich um eine leicht zu erlernende Auszeichnungssprache, die in verschiedenen „Dialekten“ vorliegt. Ich möchte mit diesem Eintrag auf die Darstellung derart formatierter Texte in einer Tapestry5-Anwendung eingehen. weiterlesen Wikitext-Darstellung mit Tapestry5

TabPanel mit Tapestry5 und Bootstrap

Heute gibt es mal wieder einen Artikel aus der Entwicklerkiste.

Für eine derzeit von mir entwickelte Webanwendung möchte ich gern Daten thematisch sortiert in einem TabPanel anzeigen. Die von mir für das Layout verwendete Bibliothek Twitter Bootstrap liefert bereits das Stylesheet und die Javascript-Funktionen mit. Nun gilt es nur noch, diese mit dem ebenfalls verwendeten Tapestry-Framework zu verheiraten. Dies muß im wesentlichen geschehen, um die Informationen des clientseitig ausgewählten Tabs nicht zu verlieren. Nichts liegt also näher, eine eigene Tapestry-Komponente mit anhängendem Template zu entwickeln. Ich habe zwar zunächst Google-Consulting betrieben und bin auch in der Tat auf fertige Lösungen gestoßen (u.a. ChenilleKit), aber die passen entweder nicht ins Layout oder sind einfach zu übertrieben… Und eine solche Komponente selbst zu entwickeln, ist leichter, als ich zunächst angenommen hatte. weiterlesen TabPanel mit Tapestry5 und Bootstrap

Ärger mit .AppleDouble-Verzeichnissen via AFP

Neulich habe ich eine Webanwendung zur Installation auf meinem Tomcat vorbereitet. Das Ganze geschah auf meinem MacBook Pro und den Serverfreigaben, die über AFP angesprochen wurden. Nach dem Start der Anwendung sah auch alles ganz gut aus, bis auf…

Tomcat Fehlermeldung

Das Schlimme daran ist ja, daß man AFP dieses unsinnige Zumüllen von Verzeichnisse nicht mal wirklich abgewöhnen kann.
Für mich ist diese Aktion jedoch wieder der dezente Hinweis darauf, regelmäßig in den serverseitigen Verzeichnisse staubzuwischen. Und das kann man bspw. so machen:

find . -name \.AppleDouble -type d -exec rm -rvf {} \;

Dieser Befehl ermittelt unterhalb eines Verzeichnisses und allen Unterverzeichnissen alle Dateien bzw. Verzeichnisse mit dem Namen .AppleDouble und löscht diese gleichzeitig.

Java: DTOs automatisiert erstellen

Hin und wieder verwende ich das „antiquierte“ Entwurfsmuster des Datentransferobjekts (kurz DTO), um Daten zwischen Benutzeroberfläche und Backend auszutauschen. Dieses Muster war vor einigen Jahren speziell im EJB-Umfeld verbreitet, da die dort eingesetzten Entity Beans nicht zur Oberfläche gereicht werden konnten. Also hat man die für die Anzeige notwendigen Daten in ein einfaches Java-Objekt kopiert und dieses zur Oberfläche geschickt. Ich benutze dieses Muster häufiger und auch aktuell wieder in einer Tapestry-Anwendung. Der Grund hierfür: Durch den Einsatz der @Validate-Annotation würde man die Objekte des Datenmodells mit GUI-spezifischen Annotationen vermischen. Und sowas mag ich irgendwie garnicht… 🙂
Nun wird vielleicht der eine oder andere, der schon einmal DTOs eingesetzt hat, bemerkt haben, daß das Hin-und-her-Kopieren der Eigenschaften eine bisweilen nervige Arbeit sein kann. So ging es mir zumindest vor ein paar Tagen wieder. Also habe ich mir etwas überlegt, um diesen Prozeß zu vereinfachen bzw. fast vollständig zu automatisieren. Diese Idee möchte ich in diesem Artikel näher vorstellen. weiterlesen Java: DTOs automatisiert erstellen

Bekloppter Code IV

Heute: Bedingte Ausführung von Geschäftslogik abhängig vom Loglevel:

Csvheader item = csvheaderDAO.findByPeriod(period);
if (item != null && item.getPeriod() == period)  {
	if (log.isDebugEnabled()) {
		log.debug("Aktualisierung des CSV Headers");
	}
	item.setHeader(header);
	item.setChangedBy(user);
	item.setChangedAt(new Timestamp(System.currentTimeMillis()));
} else if (log.isDebugEnabled()) {
	log.debug("neues Objekt des CSV Headers erzeugen.");
	item = new Csvheader();
	item.setPeriod(period);
	item.setHeader(header);
	item.setCreatedBy(user);
	item.setCreatedAt(new Timestamp(System.currentTimeMillis()));
	csvheaderDAO.persist(item);
}

Bekloppter Code III

Die heutige Preisfrage: Wie geht man wohl mit XML-Daten um?
Die Antwort zumindest im aktuellen Projekt führt einem die erschreckende Wahrheit vor Augen. Mich bestürzt vor allem die eklatante Mißachtung von Standards und das Ignorieren von vorhandenen Frameworks, welche die Arbeit mit XML-Daten optimieren würden. Stattdessen werden von allen möglichen Teams eigenen Lösungen gefrickelt und XML mit Java-Standardmitteln verarbeitet: Strings! Nicht, daß man eine XML-Datei bspw. mit SAX, DOM, JDOM oder $INSERT_YOUR_PREFERRED_XML_PARSER_HERE verarbeiten könnte, das wäre ja zu leicht.

currRequestId = zeile.substring(zeile.indexOf("") + 11, 
        zeile.indexOf(""));

Die Krönung ist dann, auch SOAP-Nachrichten auf diese Art und Weise zu erzeugen. Ist zu Fuß vermutlich viel einfacher, als – im Falle von Java – den Web Services Stack oder Axis zu verwenden.

Very dirty workaround

Diese Fehlermeldung ist einem Kollegen auf dem aktuellen Projekt vor einigen Tagen über den Weg gelaufen, als er eine Blick in die Logdateien warf:

2010-03-16 18:06:24,523 FATAL [TA_KP20 / 488917180557516]
[MessageListenerThreadPool : 0]
DefaultTLProcessor - An unchecked exception has been caught.
java.lang.NullPointerException
        at PIObjectEnricherVeryDirtyWorkarroundForBugs1842and1924.enrich(PIObjectEnricherVeryDirtyWorkarroundForBugs1842and1924.java:62)

Da sage mal noch einer, Fehler würden nicht korrigiert werden oder gar, Entwickler hätten keinen Humor…

Bekloppter Code I

Folgendes Stück Code habe ich die Tage fabriziert und mich gewundert, warum Findbugs gleich zweimal laut anschlägt:

Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
    conn = DriverMananger.getConnection(...);
    ...
} catch (SQLException e) {
    ...
} finally {
    ...
    if (conn == null)
        conn.close();
}

db4o und BigDecimal

Ich bin mittlerweile zum millionsten Mal über db4o und dessen Problem mit dem Java-Datentypen BigDecimal gestolpert.
Merke: In der Standardkonfiguration kann die objektorientierte Datenbank db4o Objekte vom Typ java.math.BigDecimal nicht korrekt speichern. Die Unterschiede hierfür scheinen – wenn man den Foren auf der Webseite folgt – über die Zeit unterschiedlich zu sein. Mal heißt es, es läge am fehlenden Standardkonstruktor, ein andermal, besondere transiente Felder seien daran schuld. Wie auch immer, es hat sich gezeigt, daß es mindestens drei Möglichkeiten gibt, mit dem Problem umzugehen.
Wichtig in allen drei Fällen ist, daß die Konfiguration von db4o vor dem Öffnen der Datenbank bzw. einer Datenbankverbindung stattfinden muß. weiterlesen db4o und BigDecimal