Developing with TeamCity 7.1: from remote run to feature branches – Pavel Sher and Dmitry Neverov at Hypoport on Feb 18th

Gemeinsam mit der Java Usergroup Berlin-Brandenburg präsentieren wir am 18. Februar den Vortrag von Pavel Sher und Dmitry Neverov Developing with TeamCity 7.1: from remote run to feature branches. Einlaß und Zeit für Networking startet ab 18:30 Uhr. Der Vortrag beginnt um 19:00 Uhr.

Abstract
Continuous integration tools play important role in software development these days. In an ideal world every commit in version control system must be checked by running a build on it, builds must be fast and broken builds must be fixed quickly. But we do not live in the ideal world, so how we can protect ourselves from breaking changes? How we can minimize effects of breaking changes on our teammates?

This talk covers effective ways of using TeamCity, a CI server from JetBrains, with different version control systems. You will see how to commit only a verified code with help of pre-tested commits, how to use personal branches if you’re using Git or Mercurial, and how to implement your favorite DVCs workflow using TeamCity feature branches support.

Speaker

Dmitry Neverov – software developer in TeamCity project. Dmitry works in JetBrains for almost 3 years and his responsibilities include wide range of tasks related to distributed version control systems, from integration with Git and Mercurial to feature branches support in TeamCity core.

Pavel Sher – senior software developer and project manager in TeamCity. Pavel started working on TeamCity almost from the beginning, 7 years ago. As such he took part in many aspects of TeamCity functionality and is responsible for many architectural decisions in TeamCity core.

Anmeldung
Anmeldung erfolgt wie üblich über die Xing JUG BB Event-Einladung.

Tipp
Zusätzlich zu dem Vortrag gibt’s noch ein Goodie von Jetbrains:) Lasst euch überraschen!

jb

Update zur JavaOne und zu EE 7

Am 29.11. waren Wolfgang Weigend und Peter Doschkinow von Oracle im Rahmen einer JUG Veranstaltung bei uns. Sie haben Neues von der JavaOne und zu Java EE 7 berichtet. In den Folien von Wolfgang finden sich Details zum Java Community Process, zum Status von Java 7 und zur Roadmap von Java 8+.

Titel_JavaOne

Peters Folien führen unter anderem aus, warum der Fokus von Java EE 7 geändert wurde. Der Schwerpunkt hat sich von PaaS in Richtung HTML5 Features verschoben. Seine Folien enthalten ein paar interessante Beispiele für neue APIs.

TitelJEE7

Vielen Dank an beide für den Einblick in die aktuelle Entwicklung von Java und an die JUG-Berlin Brandenburg für die Organisation.

Dierk König spricht bei uns über GPars

Gemeinsam mit der Java User Group Berlin-Brandenburg präsentieren wir am 16.10.2012 einen Vortrag von Dierk König zum Thema:

“GPars – Parallele Programmierung für Dich und mich”

Seit jeher bietet die Java platform gute Unterstützung für die nebenläufige Programmierung. Die Bordmittel für multithreading und Synchronisation haben aber ihre Tücken. Dierk König stellt daher zusätzliche Konzepte für den vereinfachten Umgang mit Nebenläufigkeit vor: fork/join, map/reduce, Aktoren, Agenten und Datenflüsse. Der Beispielcode wird mit GPars vorgeführt, Groovys Standardbibliothek für Nebenläufigkeit.

Speaker

Dierk König (JavaOne Rock Star) ist Fellow bei der Canoo Engineering AG in Basel. Er betreibt das Open-Source-Projekt Canoo WebTest und ist Committer in den Projekten Groovy, Grails, GPars und GroovyFX. Er publiziert und spricht auf internationalen Konferenzen zu Themen moderner Softwareentwicklung. Er ist Autor des Buchs “Groovy in Action”. Twitter: @mittie

Die Anmeldung erfolgt wie üblich über die XING Gruppe der JUG Berlin-Brandenburg.

Verwendung eines SMTP-Servers in Unit-Tests

Im Rahmen von Unit-Tests möchte man die Anbindung externer Systeme vermeiden um Stabilität der Tests zu gewährleisten. Leider hat man genau dann Probleme, wenn man gerade diese Anbindung oder die Integration mit externen Systemen testen möchte.

Für solche Unit-Test mit integrativem Charakter kann man Mocks verwenden, die recht spezifisch für den jeweiligen Anwendungsfall selbst implementiert werden. Wenn es allerdings an die Implementierung eines Mail-Server Mocks geht, ist der Aufwand der Eigenimplementierung oft nicht mehr gerechtfertigt.

Verwendung eines Fake SMTP-Servers

Mit dem Dumbster Fake SMTP Server gibt es schon eine fertige Lösung. Dumbster kann zur Laufzeit ohne umfangreiche Konfiguration gestartet werden und verhält sich wie ein echter SMTP Server:

SimpleSmtpServer.start()

Per Default lauscht der SMTP-Server auf Port 25, was auf manchen Systemen entweder nicht erlaubt ist, oder auf Systemen mit eigenem Mailserver nicht funktioniert, weil der Port bereits vergeben ist. Speziell auf Unix-Systemen ist es empfehlenswert einen Port über 1024 zu wählen, damit man keine root-Rechte benötigt. Der gewünschte Port wird einfach in der start()-Methode übergeben. Um einen freien Port zu finden, bietet sich die Implementierung einer Hilfsmethode an, die statisch aufrufbar ist und mit JDK-Mitteln einen unbenutzten Port liefert:

class PortFinder {
  public static int getAvailablePort() {
    try {
      ServerSocket socket = new ServerSocket(0);
      int unusedPort = socket.getLocalPort();
      socket.close();
      return unusedPort;
    }
    catch (IOException e) {
      throw new RuntimeException("getAvailablePort", e);
    }
  }
}

Der Start des SMTP-Servers sieht nun so aus:

  int smtpPort = PortFinder.getAvailablePort();
  SimpleSmtpServer simpleSmtpServer = SimpleSmtpServer.start(smtpPort);

Ein typischer Unit-Test würde nun so konfiguriert werden, dass Mails an localhost und den oben ermittelten smtpPort gesendet werden.

Einbindung in Spring Integration

Für die Anbindung eines externen Mail-Servers bietet sich Spring Integration mit seinen Mail Channel Adaptern an. Eine Konfiguration im Produktivcode könnte mit Hilfe des Namespace Supports den Mailserver wie folgt definieren:

...
  <si-mail:outbound-channel-adapter channel="outboundMail" mail-sender="mailSender"/>
  <bean id="mailSender">
    <property name="javaMailProperties" ref="javaMailProperties"/>
    <property name="host" value="smtp.example.com"/>
  </bean>
...

Wird der Test als AbstractTestNGSpringContextTests implementiert, kann die MailSender-Bean auf einfache Weise überschrieben werden. Der SimpleSmtpServer wird ebenfalls als Bean zur Verfügung gestellt. Relevant ist hier das Attribut primary="true" an der Bean mit der überschriebenen id="mailSender":

  <bean id="smtpPort" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="staticMethod" value="de.hypoport.blog.PortFinder.getAvailablePort"/>
  </bean>

  <bean id="simpleSmtpServer" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="staticMethod" value="com.dumbster.smtp.SimpleSmtpServer.start"/>
    <property name="arguments" ref="smtpPort"/>
  </bean>

  <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl" primary="true">
    <property name="javaMailProperties" ref="javaMailProperties"/>
    <property name="host" value="localhost"/>
    <property name="port" ref="smtpPort"/>
  </bean>

Der Test kann nun wie folgt implementiert werden, er bindet sowohl die produktive Spring-Konfiguration als auch die oben aufgeführte Test-Konfiguration ein:

@Test
@ContextConfiguration({"classpath:spring-config/mailsender.spring.xml",
"classpath:spring-config/mailsender-test.spring.xml"})
public class SendMailTest extends AbstractTestNGSpringContextTests {

  @Autowired
  private SimpleSmtpServer simpleSmtpServer;
  @Resource(name = "inputChannel")
  private MessageChannel inputChannel;

  @Test
  public void testSend() throws Exception {
    String expectedSubject = "Mail Subject";
    Message<MimeMessage> mimeMessage = MessageBuilder.withPayload(createMimeMessage()).build();

    inputChannel.send(mimeMessage);
    simpleSmtpServer.stop();

    assertThat(simpleSmtpServer.getReceivedEmailSize()).isEqualTo(1);
    SmtpMessage email = (SmtpMessage) simpleSmtpServer.getReceivedEmail().next();
    assertThat(email.getHeaderValue("Subject")).isEqualTo(expectedSubject);
  }

  private MimeMessage createMimeMessage() {
    // das Erzeugen der MimeMessage ist hier nicht relevant
    return null;
  }
}

Dumbster bietet mehr als die hier gezeigten Möglichkeiten, die Menge der empfangenen Mails oder auch deren Inhalte zu verifizieren. Einige Beispiele findet man in den Beispielen der Dumbster Dokumentation.

Agile Prozesse spielerisch erleben

Wir veranstalten seit 2008 regelmäßig alle fünf Wochen einen Hypoport internen IT Wissenstag. Dieser bietet uns die Möglichkeit uns über existierende wichtige Themen nicht nur Team-, sondern auch Geschäftsfeld-übergreifend auszutauschen. Die Inhalte werden von den Mitarbeitern bestimmt und organisiert und umfassen das gesamte Spektrum von fachlichen und technischen Themen. Wir wollen damit kommende Probleme innovativ lösen, eingetretene Pfade verlassen und attraktivere Produkte entwickeln.

Spielerisch lernen

Eine wichtige Voraussetzung für Kommunikation und Zusammenarbeit ist das Verständnis für agile Prozesse. Etwas spielerisch zu erleben kann hier viel wichtigere Erkenntnisse schaffen, als das theoretische Vermitteln von Prinzipien und Prozessen. Im Folgenden wollen wir von unseren Erfahrungen mit spielerische Ansätzen der Wissensvermittlung berichten.

Marshmallow Challenge

Eine gute Möglichkeit, um einige Ideen hinter agilen Prozessen zu erleben, ist die sogenannte Marshmallow Challenge. Die zentralen Aspekte dieses Spiels sind die Zusammenarbeit und Selbstorganisation in einem Team und das Finden von kreativen Lösungen. Die Teilnehmer erfahren, warum iteratives Vorgehen mit schnellen Feedback Zyklen und ständiger Verbesserung bei der Bewältigung unbekannter Herausforderungen so erfolgreich ist.

Die gegeneinander antretenden Teams sollen innerhalb von 18 Minuten einen möglichst hohen freistehenden Spagetti Turm mit einer Marshmallow Spitze bauen.

Ihnen stehen für die Herausforderung folgende Materialien zur Verfügung:

  • 20 Spagetti
  • ein Meter Schnur
  • ein Meter Klebeband
  • ein Marshmallow

Vier Teams bestehend aus 4 bis 5 Mitgliedern aus den unterschiedlichen Bereichen stellten sich an einem Wissenstag diesem Wettstreit. Die Teams legten mit viel Kreativität und Engagement los und man sah Wunderwerke in den Himmel wachsen. Hierbei verfolgten die Akteure die unterschiedlichsten Strategien und brachten die größte Unbekannte, den Marshmallow, unterschiedlich früh in Spiel. Von einer erfolgreichen “Ta-Da” Präsentation des höchsten Turms, bis zu einem “Oh-Oh” einer der Schwerkraft Tribut zollenden Konstruktion Sekunden vor der offiziellen Messung, war alles vertreten.

Unsere langjährige Erfahrung mit agilen Prozessen spiegelte sich auch in dem Gesamtergebnis wieder. Drei von vier Teams erbauten 70 bis 75 Zentimeter Höhe Türme. Laut Tom Wujec liegt die durchschnittlich erreichte Turmhöhe bei rund 50 cm. Es wird vielleicht für Überraschung sorgen, welche Menschen die kreativsten und höchsten Türme bauen.

Wer diese Teams neben uns sind und weitere Hintergründe zur Marshmallow Challenge finden sich im TED Talk von Tom Wujec und dem dazugehörigen Blog. Mit viel Spaß die Grundprinzipien von agilen Prozessen zu erleben, war eine spannende und empfehlenswerte Erfahrung.

Kanban Pizza Game

In unseren vorherigen Artikeln zu Kanban in der Softwareentwicklung – Praxis-Check bei Hypoport und Kanban & Kaizen – Fallstudie hat Andreas bereits von unseren Kanban Erfahrungen berichtet. Wir haben bei Hypoport viele produktübergreifende Projekte, in denen sowohl Scrum als auch Kanban Teams in die Produktentwicklung involviert sind.

Mit dem Einsatz beider Ansätze ergaben sich verschiedene Fragenstellungen, z.B.:

  • Was unterscheidet Scrum von Kanban, wo beide Ansätze doch eine große Schnittmenge der Werte und Prinzipien haben?
  • Wie fühlt es sich an mit Kanban zu arbeiten?
  • Was hat es mit Flow, Pull statt Push und fortwährender Verbesserung auf sich?

Diesen Fragen haben wir uns an unserem letzten Wissenstag mit dem Kanban Pizza Game von agile42 spielerisch genähert. Beim Kanban Pizza Game bekommen die Mitspieler ein Gefühl für die Einführung von Kanban auf einem beliebigen Prozess. Im Vordergrund steht das Erleben und Fühlen von Kanban, das Verinnerlichen von Pull statt Push und warum ein gleichmäßiger Fluss in Kanban so wichtig ist.

Ziel des Spiels ist es als Team möglichst viele fertige Pizzastücken zu produzieren. Gespielt wird in Teams mit 4 bis 5 Personen, die sich nicht nur auf die Produktion der Pizzastücken konzentrieren können, sondern gleichzeitig Verschwendung vermeiden und sich auf Änderungen einstellen müssen.

Erste Runde

Stellen wir uns folgende Situation vor: Wir eröffnen einen neue Pizza Bäckerei und wollen zu Beginn so viele Hawaii Pizza Stücke wie möglich herstellen. Es ist unser Eröffnungstag und wir verschenken Pizza Stücken an viele Kunden, um unser Geschäft zu etablieren.

Kanban kann mit sehr wenigen Veränderungen auf jeden existierenden Prozess angewandt werden. Die Teams starten in die erste Runde und etablieren einen “natürlichen” Prozess für die Pizza Produktion.

Die konkreten Vorgaben lauten: “Produziert so viele Pizza Stücken wir möglich und vermeidet Verschwendung!”

Ein fertiges Pizzastück Hawaii Pizza besteht aus:

  • einem dreieckigen Pizzaboden aus einem Papierstück mit genicktem Rand
  • roter Tomatensause, aufgebracht durch einen roten Edding
  • 3 Stücken Schicken aus orangem Papier
  • 3 Stücken Ananas aus gelbem Papier
  • und jedes Pizza Stück muss im Ofen (einer gekennzeichneten Station mit unten stehenden Regeln) gebacken werden

Nach einer vorher nicht angegeben Zeit wird die erste Runde beendet und jedes fertig produzierte Pizzastück wird mit 5 Punkten bewertet. Die Teams zählen stolz die erreichten Punkte.

Aber es gab noch die im zweiten Teil des Satzes formulierte Vorgabe, die Auswirkungen auf die erreichten Punkte hat. Vermeidet Verschwendung! Dies traf die Teams hart.

Von der Gesamtsumme werden nun Punkte für jedes Materialstück innerhalb des Fertigungsprozesses abgezogen. Dies bedeutet konkret:

  • minus 2 Punkte für einen Pizzaboden
  • minus 1 Punkt für zwei Belagstücke (Ananas- oder Schinkenstück)

Im nächsten Schritt werden die Grundpraktiken von Kanban auf den aktuellen Prozess angewandt:

  • die Visualisierung des Prozesses durch Abteilen der einzelnen Arbeitsstationen
  • die Begrenzung der Menge angefangener Arbeit durch Setzen eines Limits an den Stationen
  • der Messung und Optimierung des Durchlaufens der einzelnen Arbeitspakete durch den Prozess (Durchfluss), wird nach jeder Runde durch das Punktesystem für fertige Pizzastücken und Punkteabzug für nicht verwendete Materialien repräsentiert

Zweite Runde

Die Teams erhalten 5 min Zeit die Stationen durch Klebeband auf dem Tisch zu visualisieren, Limits für diese Stationen zu definieren und ihren Prozess zu verbessern.

Die zweite Runde startet und die Teams produzieren wie in der vorherigen Runde Hawaii Pizzastücken und zählen im Anschluss die Punkte.

Dritte Runde

„Jetzt wird es ernst. Unser Pizza Laden nimmt seinen regulären Betrieb auf und wir produzieren auf Bestellungen.“

Auf einer Bestellung befindet sich die Anzahl der zu produzierenden Pizzastücken und es werden nur fertige Bestellungen gewertet. Die Teams erhalten 2 min Zeit ihren Prozess anzupassen bevor es in die dritte Runde geht.

Vierte Runde

Wie im echten Leben bekommen wir Anforderungen, die unsere bisherigen Prozesse durcheinander bringen. „Unser Pizza Laden expandiert und wir nehmen als zusätzliche Sorte die Rucola Pizza mit auf.“

Eine Rucola Pizza besteht aus:

  • einem dreieckigen Pizzaboden mit genicktem Rand
  • roter Tomatensause
  • 7 Rucola Streifen aus grünem Papier
  • jedes Pizza Stück muss im Ofen gebacken werden
  • der Rucola muss nach dem Backen auf die Pizza gelegt werden, da er ansonsten im Ofen verbrennt

Das Kanban Pizza Game hat allen Teilnehmern eine Menge Spaß gemacht und konnte die Grundprinzipien von Kanban gut vermitteln. Gerade die Reflektionsphase regt zu Gesprächen und aktiver Auseinandersetzung mit diesen Themen an.

Die vorgestellten Spiele eignen sich nicht nur für Teilnehmer, die sich frisch mit agilen Werten und Prinzipien beschäftigen. Die spielerische Auseinandersetzung mit agilen Ansätzen ermöglicht auch erfahrenen Teams, einen anderen Blick auf die eigene Arbeitsorganisation zu werfen und rückt die agilen Prinzipien wieder in den Aufmerksamkeitsfokus.

Unit- und Integration-Test eines MicroService mit Maven

Was ist ein MicroService? In unserem Kontext ist es ein (kleines) Modul der Gesamtanwendung, welches seinen Dienst als Webapplikation (.war) anbietet. Das konkrete Schnittstellen-Protokoll ist für diesen Artikel nicht entscheidend. Möglich ist klassisch SOAP, REST aber auch Spring HttpInvoker. Ein MicroService ist eine gute Möglichkeit Sollbruchstellen in die Gesamtanwendung einzubauen.

Nun zum eigentlichen Thema: Wie teste ich einen solchen Service? Im Grunde wie immer, d.h. viele Unit-Tests und ein paar ausgewählte Integration-Tests. Die Integration-Tests sollen zeigen, dass die angebotenen Schnittstellen des Services funktionieren und alles richtig konfiguriert ist. Die Integration-Tests, die die Gesamtanwendung, d.h. das Netz aller Services testet, ist hier nicht Bestandteil.

Wie macht man das jetzt mit Maven? Eine Variante ist die Unit-Tests und Integration-Tests zu trennen. Vor der integration-test Phase einen Tomcat zu starten, dann seine Integration-Tests auszuführen und anschließend wieder den Tomcat zu stoppen. Tomcat, weil wir diesen nicht nur lokal einsetzen und somit “gleicher” zur Produktion sind. Eine echte Plugin-Auswahl fand nicht statt, wir sind einfach mit dem tomcat7-maven-plugin gestartet.

Mit Maven Tomcat automatisch starten und stoppen

  <build>
    <plugins>
      ..
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.0-beta-1</version>
        <configuration>
          <contextFile>${project.basedir}/src/test/resources/test-context.xml</contextFile>
        </configuration>
        <executions>
          <execution>
            <id>tomcat-run</id>
            <goals>
              <goal>run-war-only</goal>
            </goals>
            <phase>pre-integration-test</phase>
            <configuration>
              <fork>true</fork>
            </configuration>
          </execution>
          <execution>
            <id>tomcat-shutdown</id>
            <goals>
              <goal>shutdown</goal>
            </goals>
            <phase>post-integration-test</phase>
          </execution>
        </executions>
      </plugin>

    </plugins>
  </build>

Das Starten des Tomcats binden wir an die pre-integration-test Phase (Zeile 17). Wichtig ist fork auf true zu setzen (Zeile 19), da sonst Maven nach Start des Tomcats stehen bleibt. Das Beenden binden wir entsprechend an die post-integration-test Phase (Zeile 27). Wenn keine context.xml in der webapp enthalten ist, muss eine per contextFile angeben werden (Zeile 9).

So, unser Tomcat startet und stoppt nun beim Ausführen von mvn integration-test.

Mit Maven innerhalb eines Modules Unit- und Integration-Tests trennen

Nächster Schritt ist die Unit- und Integration-Tests zu trennen. Im Netz empfehlen einige dies in separaten Maven-Modulen zu tun. Wir finden es sinnvoller dies über die Test-Phasen zu steuern:

  <build>
    <plugins>
      ..
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
          <skip>true</skip>
          <trimStackTrace>false</trimStackTrace>
        </configuration>
        <executions>
          <execution>
            <id>unit-tests</id>
            <phase>test</phase>
            <goals>
              <goal>test</goal>
            </goals>
            <configuration>
              <skip>false</skip>
              <includes>
                <include>**/*Test.java</include>
              </includes>
              <excludes>
                <exclude>**/*IntegrationTest.java</exclude>
              </excludes>
            </configuration>
          </execution>
          <execution>
            <id>integration-tests</id>
            <phase>integration-test</phase>
            <goals>
              <goal>test</goal>
            </goals>
            <configuration>
              <skip>false</skip>
              <includes>
                <include>**/*IntegrationTest.java</include>
              </includes>
            </configuration>
          </execution>
        </executions>
      </plugin>

    </plugins>
  </build>

In Zeile 8 wird das Default-Test-Verhalten vom maven-surefire-plugin ausgeschaltet. Durch zwei einzelne <execution/>'s können wir unterschiedliche <configuration/>'s an unterschiedliche Phasen binden (Zeile 14 und 30). In der test Phase werden alle Klassen mit Endung Test.java ausgeführt außer jene mit Endung IntegrationTest.java. In der integration-test Phase werden nun lediglich alle Klassen mit Endung IntegrationTest.java ausgeführt. Vielen Dank an HDave, der letzteres auf Stackoverflow schön erklärt.

Hast du ähnliche Anwendungsfälle? Wie hast du diese gelöst?

Oliver Gierke von SpringSource kommt am 14. Juni 2012 nach Berlin

Gemeinsam mit der Java Usergroup Berlin-Brandenburg präsentieren wir am 14. Juni den Vortrag von Oliver Gierke Huch, wo ist meine Architektur hin?. Einlaß und Zeit für Networking startet ab 18:30 Uhr. Der Vortrag beginnt um 19:00 Uhr.

Vortrag
Wenn Applikationen über eine bestimme Größe oder einen bestimmten Zeitraum hinaus wachsen wird Modularität ein Kernaspekt für Wartbarkeit. Designentscheidungen die getroffen wurden sind kaum noch im Code wiederzufinden, Abhängigkeiten zwischen einzelnen Modulen der Applikation wachsen oft wild. Der Vortrag Patterns und Best Practices rund um generelle Code-Organisation und Package-Strukturen vor um eine solide Grundlage für langlebige Java-Applikationen zu legen, sowie eine möglichkeit mit Spring lose gekoppelte Komponenten und dedizierte Erweiterungspunkte in Applikationen zu definieren und zu verwenden.

Speaker
Oliver Gierke ist Teil des Spring Data Teams bei SpringSource, a division of VMware und leitet dort das JPA, MongoDB und Core Modul. Seit über 6 Jahren widmet er sich dem Entwicklen von Java Enterprise Applikationen, Open Source Projekten und ist Mitglied der JPA 2.1 Expert Group. Seine Arbeitsschwerpunkte liegen im Bereich Softwarearchitektur, Spring und Persistenztechnologien. Er ist regelmäßiger Sprecher auf deutschen und internationalen Konferenzen sowie Autor von Fachartikeln.

Nie mehr ohne JSON Serializer

JSON Serializer in Debugging Session verwenden

Welcher Java Entwickler kennt es nicht: Nach einigen konzentrierten Versuchen hat die Programmausführung endlich an exakt der richtigen Stelle angehalten. Alle Daten sind im kleinen Debugging Fenster erreichbar. Schade nur, das meine IDE keine Möglichkeit bietet, den riesigen Objektgraphen nach meinem relevanten Eintrag zu durchsuchen. Oder per EMail an die Fachabteilung zu verschicken.

Dabei ginge das sehr einfach: Mit einem auf reflection basierenden Objekt-Serialisierer. Dieser erzeugt ohne vorherige Konfiguration aus einem beliebig tiefen Objektgraphen einen String z.B. im JSON Format.

Und genau das kann während einer Debugging Session genutzt werden, wenn im Projekt ein Json Serializer eingebunden ist. Im „Evaluate“ Dialog oder unter „Watches“ wird der Serializer aufgerufen. Der entstandene String lässt sich dann leicht kopieren und weiter verarbeiten.

new flexjson.JSONSerializer()
    .prettyPrint(true).deepSerialize(myObjectGraph);

Als Framework um JSON zu erzeugen empfiehlt sich FlexJson. Dieses bietet für diesen Anwendungsfall Vorteile gegenüber dem zweiten Platzhirsch Jackson: Dank der Builder-API kann der Aufruf leicht parametrisiert werden und dennoch bleibt es ein Einzeiler. Im Beispiel oben wurde pretty-printing aktiviert. Einstellbar sind z.B. auch die Rekursionstiefe und Excludes. Die Darstellung von Java Collections erfolgt sehr übersichtlicher als Json-arrays.

Wer besser XML als Json lesen kann, erhält die gleiche Funktionalität mit Hilfe der XStream Bibliothek.

new XStream(new StaxDriver()).toXML(myObjectGraph);

Produktives Logging

Die Log-Ausgaben auf dem Produktivsystem sind of sehr kanpp, denn die toString() Methode ist nicht aussagekräftig überschrieben. Ein Rückschluss über den Systemzustand erhalte ich so nicht. Auch in diesem Fall kann die Situation verbessert werden. Einfach den als JSON serialisierten Objektgraphen loggen! Hier empfiehlt es sich, pretty printing auszuschalten um einzeilige Logausgaben zu erhalten.

Entwickler loggen manchmal bei wichtigen Ereignissen oder Zustandsübergängen eine Zusammenfassung der relevanten Informationen. Dieses erfolgt im Code oft durch (sehr) lange und schwer lesbare String.format Aufrufe. Die Lesbarkeit und Erweiterbarkeit kann einfach erhöht werden, wenn eine Map aus Beschreibung-Wert-Paaren erstellt und in JSON serialisiert wird:

Map pairs = new HashMap();
pairs.put("AngebotAnnahme", "durchgeführt");
pairs.put("AnnahmeStatus",getAnnahmeStatus());
pairs.put("Vorgang", teilVorgang.getVorgangId());
pairs.put("fuehreKostenpflichtigeDiensteAus",
                fuehreKostenpflichtigeDiensteAus);
LOG.info(jsonSerializer.toJson(pairs));

Fazit

Ein JSON Serialisierer hilft mir als Entwickler, sehr einfach und spontan einen Snapshot meines Systems zu erstellen. Beim Debuggen genauso wie im Produktivbetrieb.