Archiv der Kategorie Diplomarbeit.. ftw!

Statische und metrische Codeanalyse (java, eclipse)

Ein äußerst umfangreiches Tool habe ich heute vorzustellen: Eclipse Metrics Plugin. Zwar taucht es in einigen Google Ergebnissen auf, aber teilweise auf eine alte Eclipse-3.1-Version verlinkt. Das ist nicht nur dumm, es funktioniert auch nicht mehr mit 3.4.

Der Updatevorgang via UpdateSite funktionierte leider nicht; aber das manuelle Herunterladen der entsprechenden Plugindatei dagegen schon. Es ist eine Jar-Datei, welche einfach in den plugins-Ordner geschubst wird.

Anschließend (nach einem Neustart Eclipse’) muss in den Projekteinstellungen “Metrics” zunächst aktiviert werden; danach lässt sich via Export->Metrics eine entsprechende umfangreihe Statistik generieren. Aber eine beherzte Warnung: Ohne Vorkenntnisse kommt man nur bedingt weit.

Was etwa eine zyklomatische Zahl oder was etwa “Feature Envy” ist, sollte man entweder wissen oder sich das Wissen zeitnah aneignen. Eine spontane Suche ergab diese kleine Arbeit, sollte für den Anfang reichen.

Stand der Diplomarbeit: Knapp 17 KLOC. Refactoring noch nicht abgeschlossen.

Für LaTeX: Wörter, Überschriften und anderes zählen

Als kleines Perlscript: folk.uio.no

Falls man das Dokument in mehrere Dateien aufgesplittet hat (Includes), so hilft: texcount.pl document.tex -inc. Um nur das Gesamtergebnis anzuzeigen: texcount.pl document.tex -inc -total.

Java-Swing-Komponenten als Bild / Snapshot

Für unsere Anwendung (ähm, halt Diplomarbeit ftw!) wollte ich eine Export-als-Bild-Funktion für die Anzeige des aktuellen Graphen einbauen. Dabei handelt es sich um eine JComponent, die über das JUNG-Framework dargestellt wird.

Während jetzt Apple-Benutzer leichtfertig über dieses Feature lachen können, ist dies für Hauptzielgruppe der Anwendung (also Windowsbenutzer) eine sinnvolle Funktion. Es hat sicherlich wenig Sinn, umständlich einen Komplett-Screenshot anfertigen zu müssen.. viel einfacher kann das Programm das ja selbst machen.
Es gibt eine Reihe von Suchtreffern in Google, die durchaus lesenswert sind.

Die Grundidee ist, dass man sich selbst ein Graphics-Objekt erstellt und dann die JComponent darauf arbeiten lässt. Im Falle von Swing ist dies idR vom Framework vorgegeben (nämlich für den Bildschirm), hier aber wollen wir ja ein eigenes Bild haben. Die Höhe und Breite ist in den meisten Fällen von der Komponente zu erfragen.
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

Anschließend brauchen wir das zugehörige Graphics-Objekt, denn damit arbeiten die Paint-Methoden. Clue Nummer 1: Man könnte in Versuchung kommen, und einfach getGraphics() zu nehmen – ist ja auch naheliegend. Tatsächlich erstellt das aber auch nur ein Graphics-Objekt, während createGraphics() ein Graphics2D-Objekt erstellt. Und in den meisten Fällen braucht man das auch.
Graphics2D g = bi.createGraphics();

Anschließend muss man sich entscheiden, welche Zeichenroutine man anstoßen will. Es gibt prinzipiell folgende Möglichkeiten: paint(Graphics), paintComponent(Graphics) und paintAll(Graphics). Sofern paintComponent() ausreicht, diese nutzen. Im Falle des JUNG-Graphen mit verschiedenen Subelementen und eigenem Renderer funktioniert jedoch nur paintAll(Graphics) auf allen System zuverlässig. Während paint(Graphics) unter MacOS und Linux noch funktioniert, produziert es unter Windows unschöne Ergebnisse.

Anschließend kann man mit dem statischen Aufruf ImageIO.write(bi, "png", file); das gesamte Bild als — hier PNG — speichern. Achtung: Dies ist eine JavaSE6-Klasse, in den Vorgängern benötigt man dann den Umweg über FileStream & Co.

[1] jung.sourceforge.net
[2] java.sun.com

Tags: , , , ,

Code-Coverage, Eclipse, jUnit

eclemma-1

Joa, es ist wieder Zeit für einen Artikel in der Java/DA-Reihe.

Als erstes und sehr einfach zu testendes Kriterium gilt beim Testen die Code Coverage. Eigentlich sehr simpel, denn es quantifiziert nur die Code-Coverage, also von wie vielen Zeilen Code (Instructions) tatsächlich wie viele (bzw. welche) auch ausgeführt werden. Da man dies natürlich gerne automatisiert machen möchte, sind Tests wie mit jUnit ideal. Aber, auch normale Anwendungen sind mitzutracen und den Codecoverage ist zu ermitteln.

eclemma-2

Für Eclipse gibt es dazu ein prima Plugin namens EclEmma. Und auch schnell über die Update-URL im Manager installiert. EclEmma dient dabei als eine Art Wrapper für verschiedene Launchtypen – also beispielsweise als normale Applikation oder einen jUnit-Test bzw eine ganze Suite (Plugins). Das Ergebnis wird nach Beendigung des Programms/Tests innerhalb von Eclipse in einer Baumstruktur dargestellt; sehr schön ist auch die grafische Hervorhebung direkt im Sourcecode. Alternativ kann man sich das Ergebnis auch als HTML exportieren lassen.

Tags: , , , , ,

Nullpointer-Exceptions verhindern

DZone.com sei Dank: Gestern ‘mal wieder einen lesenswerten Artikel gefunden. Diesmal: How to Avoid NullPointerExceptions (NPE)?. Vor allem der letzte Absatz Common Practices ist zu empfehlen.

Tags: , ,

Starten einer JAR unter Mac OSX – Bad version number?

Wir hatten dieses Thema bereits indirekt durch den ApplicationBundler im Beitrag vorletzter Woche besprochen.. aber hier nochmal zum eigentlichen Problem und dessen Lösung.

Der Fehler verursacht die aktuell ausgewählte Java-Version (und das ist bei den meisten Leuten der Standard Java 1.5.0). Wenn jedoch die Jar mit Java 1.6 kompiliert wurde, kann der 1.5-Loader damit nichts anfangen bzw. schützt aus naheliegenden Gründen vor der Ausführung. Zwar ist auf Mac OS X System der Version 10.5 auch Java 1.6 installiert, dieses ist jedoch kein Standard.

Es gibt dafür nun drei Möglichkeiten:

  1. Der Benutzer startet die JAR nicht mit Doppelklick bzw. dem Kommando “java -jar JarFile.jar” sondern mit der direkten Angabe im Frameworkverzeichnis.. diese Lösung ist inakzeptabel.
  2. Der Benutzer stellt seine Default-JVM auf 1.6 um.. das machen die Entwickler eh, aber der Benutzer wird auch damit überfordert sein. Auch keine akzeptable Lösung.
  3. Man erstellt eine Mac-Application mit entsprechenden Application-Bootloader und einer Art Manifest, wo eingestellt wird, welche Java-Version verwendet werden muss. Damit findet sich Java 1.6 sogar dann, wenn man als Default 1.4 eingestellt hat. Außerdem hat es den positiven Nebeneffekt, dass die “technische” Jar vor dem Benutzer durch ein Anwendungsymbol kaschiert wird.

Tags: ,

TestSuites in Eclipse mit jUnit 4 (Nachtrag)

Das Problem: Wenn man in einem Projekt eine Reihe von Testcases gemacht hat, dann sind diese meist (natürlich) auf verschiedene Packages verteilt. Außerdem gibt es ja reine Komponententests als auch Usecasetests (soweit möglich), oder das Testen zweier oder mehrere Komponenten im Verbund. Schlussendlich also eine große Anzahl von “TestCase”-Klassen, die jeweils mehrere Tests haben. Ideal wäre also, wenn man diese ganzen Testcases zusammenpacken könnte.. und dann auch ausführen könnte.

jUnit bietet (in Eclipse) dafür die Option TestSuite an. Eine TestSuite ist ja auch genau das, was wir brauchen. Leider zeigt der Wizard keine unserer TestCases an.. warum? Nach einigem Recherchieren (viele Suchergebnisse zeigen indirekt noch auf jUNit 3.8) ist die Frage eigentlich simpel gelöst.. wenn man denn weiß, wie ;)

Als erstes müssen alle TestCase-Klassen (d.h. hier die Klasse MyTests, die @Test-Methoden enthält) eine neue Methode erhalten:

public static junit.framework.Test suite() {
return new JUnit4TestAdapter(MyTests.class);
}

Damit erkennt der Wizard für eine TestSuite nun auch jene Klassen.

Falls man es lieber manuell machen möchte (Beispiel): suite.addTest(MyTests.suite());f

Es ist übrigens kein Problem, TestSuites zu verschachteln – dafür einfach das Prozedere “wiederholen” bzw. suite.addTest(MyOtherSuite.suite()) schreiben. Tipp: Es gibt die äußerst hilfreiche Methode suite.setName(string) – damit man sich in der jUnit-Baumansicht nicht verwirrt.

Nachtrag:

Wesentlich eleganter ist natürlich der Annotation-Weg. Die “SuperTestSuite” braucht “nur” so auszusehen:

@RunWith(Suite.class)
@SuiteClasses( { MySuite1.class, MySuite2.class, MySuite3.class })

public class AllTests {
}

Tags: , , ,

Java-Applikation als Mac-Anwendung deployen (Ant)

Wie bereits berichtet, ist es von Vorteil, der Buildprozess mit einem Ant-Script zu automatisieren. Um eine Mac-Application zu erstellen, muss man nur wissen, wie eine solche Application aufgebaut ist.. der Rest ist ein Klacks.

Eine Mac-Application ist ein Verzeichnis mit der Erweiterung .app. Die Struktur einer Application (wir nennen sie im Folgenden Application) sieht wie folgt aus:

  • Application.app
    • Contents
      • Info.plist — Properties-Datei für die Anwendung und Java
      • MacOS — Verzeichnis
        • JavaApplicationStub — Bootloader für Javaprogramme
      • PkgInfo — Datei mit Entwicklerinfo
      • Resources — Verzeichnis mit dem eigentlichen Javaprogramm
        • Java
          • Die Jars und so.

Den Bootloader befindet sich auf einem Mac in dem Ordner /System/Library/Frameworks/JavaVM.framework/Resources/MacOS/JavaApplicationStub.

Prinzipiell kann man sich diese Struktur komplett selber erstellen; es ist aber zu Empfehlen, den initialen Prozess durch das Programm /Developer/Applications/Utilities/Jar Bundler zu machen. Mit Hilfe dieses Programmes lässt sich für eine bereits fertige JAR die Application erstellen.

Anschließend kopiert man das erstellte Resultat – quasi als Vorlage – in ein Verzeichnis für die Builds. In meinem Fall in dem build_data Verzeichnis. Ein Ant-Task erstellt darauf hin im Verzeichnis deploy eine Application. Die Vorlage ist idealerweise auch im SVN und auch später noch veränderbar – beispielsweise durch das Ändern des Applicationicon, -titel oder anderen Einstellungen.

Wichtig 1: Bei Verwendung von FatJar muss man als Package für die Main den Bootloader von FatJar (com.simontuffs.onejar.Boot) verwenden. Dies erkennt das Programm Jar Bundler aber auch automatisch.

Wichtig 2: Beim Kopieren der Dateien kann es passieren, dass die Rechte an der JavaApplicationStub verloren gehen. Diese muss als ausführbar markiert sein. Ein entsprechender Ant-Befehl stellt das sicher.

<target name="makeMac" depends="makeNormal">
<copy todir="deploy/Application.app">
<fileset dir="build_data/Application.app"/>
</copy>
<!-- chmod the application stub file executable -->
<chmod file="deploy/Application.app/Contents/MacOS/JavaApplicationStub" perm="755"/>
<copy file="deploy/Application.jar" tofile="deploy/Application.app/Contents/Resources/Java/Application.jar" />
</target>

Tags: , ,

Automatischer Deploy von Java-Applikationen oder: Ant Builds mit externen Jars und SVN-Informationen

Der Eclipse-verwöhnte Programmierer braucht sich eigentlich nicht mit Begriffen wie Deploy oder Build herumschlagen — zumindestens nicht so lange man in der Entwicklung ist. Ein Knopfdruck auf “Run” und das Programm läuft. Sowohl alle lokalen Resourcen als auch alle externen Jars werden gefunden, eingebunden und können einwandfrei genutzt werden.

Möchte man die Applikation nun fertigstellen und anderen zur Verfügung stellen – oder früher im Rahmen von Enduser-Tests – so kommt es bei großen Projekten unweigerlich zu Problemen.

Im Folgenden beschäftige ich mit den Problemen:

  1. Wie exportiere ich ein Projekt mit vielen externen Jars einfach und sicher in ein lauffähiges Jar?
  2. Wie stelle ich sicher, das sowohl in der Entwicklungsumgebung als auch in der Jar alle Bilder o.ä. Ressourcen wiedergefunden werden?
  3. Wie nutze ich einen eigenen Buildprozess und
  4. Wie kann ich im Buildprozess Zusatzinformationen wie die aktuelle SVN-Revision oder das Build-Datum verwerten?

Den Rest des Eintrags lesen. »

Tags: , , , ,

Neue Reihe “Diplomarbeit.. ftw!”

da-build-160409-01

So, wenn man spontane Ideen hat, sollen sie ja ganz gut sein. Fein, der Titel ist ‘mal ganz spontan entstanden, weil mir nichts besseres eingefallen ist. :)

Seit diesem Monat stecke ich in meiner Diplomarbeit: Die Entwicklung eines Tools, mit dem man die Abhängigkeiten von Views und

Triggern in einer Datenbank analysiert, parst und anschließend visuell (sprich in Graphen) anzeigt. Das ganze muss auch persistent gespeichert werden, da der Prozess je nach Größe der Datenbank etwas dauern kann.

Für rund vier Wochen intensiven Arbeitens (zu zweit) hat unsere in Java geschriebene Applikation bereits große Fortschritte gemacht. Sowohl das Auslesen als auch das Parsen von mehrschichtigen Views klappt, als auch das Lesen und Speichern in einen nichtflüchtigen Speicher (HSQLDB). Außerdem haben wir bereits einen Prototypen zur Visualisierung.

Anbei einen Screenshot der aktuellen Build (Mac OS X). Die Anwendung sieht unter einem Mac leider immer noch sehr “Java” aus. Die Menubar habe ich zwar bereits nach oben “verdonnert”, aber es reicht nicht aus. Abhilfe schafft hier das das Projekt MacWidgets, das eine Reihe von Swing-Komponenten selbst zeichnet. Mit dem optionalen Code da-build-160409-02sieht die Anwendung bereits etwas schniker aus.

Weitere technische Details zur Anwendung:

  • HSQLDB als lokale Datenbank zum Ablegen der Schemata und Datenbankverbindungen
  • Hibernate als OR-Wrapper um Hibernate; die Anwendung produziert 0 Sql-Statements
  • JUNG2 als Graphenframework zum Zeichnen der Elemente (späterer Blogeintrag wird dies zeigen)
  • JavaBuilders/SwingX als idealer Layouter für Formulare, wie unseren Connectiondialog (späterer Blogeintrag wird dies zeigen)

Tags: , , ,