Posts mit dem Label Tutorial werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Tutorial werden angezeigt. Alle Posts anzeigen

19.02.2015

Continuous Delivery mit Hilfe von Maven

In vielen Projekten habe ich bereits das Problem gehabt, dass der Transfer der Artefakte vom Repository auf eine Test-Instanz sich nur mit Mühe automatisieren lässt. Gerade das Kopieren der Artefakte ist in der Regel ein wichtiger Punkt - wie ist sichergestellt, dass die Artefakte für das Deployment mit den Artefakten aus dem Repository übereinstimmen? Eigentlich nur dann, wenn diese auch direkt aus dem Repository kommen und ohne Veränderung oder eigenen Buildprozess auf den Server kopiert werden.

Für diese Probleme existieren unterschiedliche Lösungsansätze, vom Shell- oder Powershell-Skriptbis hin zu CI-Lösungen, die direkt aus dem Buildserver Artefakte auf den Server kopieren. Nachteil ist, dass alle Lösungen in irgendeinerweise von der Plattform abhängig sind.
Eine Lösung ist, dass das Kopieren der Artefakte über das Buildtool geregelt wird. Dabei wird ausgenutzt, dass die Verbindung zwischen Buildtool und Repository bereits ohne Probleme funktioniert und auch die Ablage / der Bezug der entsprechenden Dateien erfolgt an zentraler Stelle. Natürlich ist immer noch ein kleiner Anteil an plattformabhängigem Skript notwendig, aber der Großteil der Arbeit - beispielsweise Verbindungsaufbau, Bezug der Artefakte aus dem Repository, Authentifizierung am Repository - wird durch das Buildtool erledigt. Voraussetzungen für diese Lösung sind:
  • zentrales, vom Server erreichbares Repository (Nexus, Archiva, ...)
  • Installation von Maven auf dem Server
  • Scheduler für ein geplantes Ausführen von Tasks
Die Installation der entsprechenden Tools wird an dieser Stelle nicht genauer erläutert, diese sollte bereits bekannt sein (oder kann in der Dokumentation nachgelesen werden).

Für das Kopieren der Artefakte wird ein einfaches Maven-Projekt aufgesetzt, bestehend aus nicht mehr als einem POM. Das POM beinhaltet zum einen die Angaben zum Repository...




... als auch den zentralen Abschnitt für das Kopieren der Artefakte in das Verzeichnis für das Deployment. Für eine bessere Lesbarkeit wurden die Pfade des Servers in Properties ausgelagert und separat platziert.



Für das Kopieren wird ein spezielles Plugin genutzt, das Maven Dependency Plugin. Das Plugin bietet eine Menge nützlicher Goals und kann unter anderem für das Kopieren von *.jar Dateien aus einem Repository genutzt werden.




Es wird definiert, dass in package Phase zusätzliche Aktionen ausgeführt werden - die beiden hier definierten Artefakte werden in die entsprechenden Verzeichnisse kopiert. Im ersten Schritt wird die Webanwendung selbst kopiert, im zweiten Schritt wird der Treiber für den Zugriff auf die Datenbank kopiert (dieser wird nicht von der Webanwendung mitgeliefert, da diese nicht wissen soll auf welche Datenbank zugegriffen wird).


Neben den obligatorischen Angaben der groupId, der artifactId, der version und des type, werden weitere Angaben getätigt.



Für die Webanwendung wird definiert, dass Artefakte überschrieben werden können, das Output-Verzeichnis wird festgelegt und der Dateiname für die Anwendung wird ebenfalls definiert. Das gleiche wird für den Treiber ebenfalls angegeben.


Das Kopieren der Dateien ist somit erledigt und wird automatisch durch Maven ausgeführt. Was bleibt ist allerdings der manuelle Aufwand für die Vorbereitung des Deployments. Dafür muss ein entsprechendes, plattformabhängiges Skript erstellt werden.

Je nach Betriebssystem und der eigentlichen Installation des Tomcat unterscheidet sich das Skript in wenigen Details. Das oben angeführte Skript ist ausgelegt für das Deployment eines Artefaktes auf einem einzelnen Server, welcher als Dienst gestartet wurde. Es werden die Verzeichnisse gelöscht und danach wird mit einem einzigen Aufruf das Artefakt in das entsprechende Verzeichnis kopiert.


Dieses Skript kann dann mit dem entsprechenden Scheduler eingeplant und ausgeführt werden.


Alles in allem eine schlanke Methode für das kontinuierliche Deployment von Artefakten auf einem Server. Natürlich mit Schwächen, gerade beim Deployment auf einem Cluster oder komplexen Deployments die nacheinander erfolgen müssen, aber für einfache Anwendungen auf singulären Instanzen sicherlich eine akzeptable und vor allem stabile Lösung.

23.07.2014

Apache Tomcat - Umstellung 'Apache Commons Logging' auf 'log4j'

Viele Entwickler haben bereits mit dem Tomcat gearbeitet und der ein oder andere wird sich sicherlich auch schon einmal Gedanken um das Logging gemacht haben. In der Default-Konfiguration wird das Logging über Apache Commons Logging realisiert. Dieses Framework ist ein leichtgewichtiger Wrapper um viele andere Loggingframeworks.


Damit ist das Logging im Tomcat so konfiguriert, dass ohne Kenntnis über die darunterliegende Logging-Implementierung das Level des Loggings feingranular reguliert werden kann. Seit dem Tomcat 6 wird eine interne Implementierung des Frameworks verwendet, so dass die unterschiedlichen Webanwendungen durchaus ihre eigene Kopie der Apache Commons Logging Bibliotheken mitbringen können. Durch die unterschiedliche ClassLoader sind die Implementierungen voneinander getrennt und haben keinen Einfluss aufeinander.

In manchen Fällen sind die Einstellungen für das Logging aber nicht ausreichend und der Einsatz eines erweiterten, speziellen Frameworks gewünscht. Aus diesem Grund ist es möglich, dass der Tomcat für den Einsatz von log4j konfiguriert wird. Dafür sind nur wenige, einfache Schritte notwendig. Aber zuerst ein Blick auf den Output ohne log4j.



Zuerst wird eine Konfigurationsdatei für das Logging erstellt. Diese wird als log4j.properties direkt im lib Verzeichnis unter $CATALINA_HOME abgelegt. Eine beispielhafte Konfiguration könnte wie folgt ausschauen:


Als Template eignet sich auch sehr gut die Vorlage in der offiziellen Dokumentation zur Einrichtung des Loggings.

Im Anschluss werden die zusätzliche notwendigen Bibliotheken, tomcat-juli* und log4j heruntergeladen und für eine globale Konfiguration im lib Verzeichnis unter $CATALINA_HOME platziert. Dabei ist darauf zu achten, dass eventuell vorhandene Dateien ersetzt werden. tomcat-juli* kann dabei über die Extra-Downloads für den Tomcat heruntergeladen werden, log4j kann direkt über die Projektseite bezogen werden.





Zur Sicherheit sollte im Anschluss noch die logging.properties unter $CATALINA_BASE/conf/ gelöscht werden. Im Anschluss kann der Tomcat wieder gestartet werden.


Merkwürdigerweise sieht die Ausgabe genauso aus, wie bereits vorher gesehen. Die Lösung erschließt sich nicht auf den ersten Blick, das Problem ist aber trotzdem leicht zu lösen. Ein Blick auf den Classpath offenbart den Fehler.


Augenscheinlich liegt im $CATALINA_BASE/bin/ noch eine weitere tomcat-juli.jar Bibliothek. Diese ist natürlich nicht auf den Einsatz bzgl. log4j vorbereitet und muss daher ebenfalls gepatcht werden. Hier bieten sich unter Unix zwei Möglichkeiten an, einmal das Kopieren der Datei aus dem $CATALINA_BASE/lib/ oder das Erstellen eines Symlinks. Der Einfachhalt halber wird die Datei an dieser Stelle kopiert und überschrieben. Der anschließende Start des Servers sollte dann das folgende Bild zeigen.


Die Ausgabe ist deutlich kürzer geworden und innerhalb des Log-Verzeichnisses finden wir die entsprechenden Logs.


Die werden nun durch log4j mit dem entsprechenden Pattern gefüllt.


Wichtig ist allerdings, dass bei einem solchen Ansatz die log4j Bibliotheken sofort allen Anwendungen zur Verfügung stehen. Das kann natürlich zu Problemen in den Anwendungen führen. Sollte Anwendungen mit Apache Commons Logging arbeiten, so wird automatisch als darunterliegende Implementierung log4j gewählt. Diese Einschränkungen sollten bei der Konfiguration dringend beachtet werden.

31.08.2013

Checkstyle - System.out | System.err | ex.printStackTrace

Der Vortrag von Dirk Weil bei der JUG Ostfalen hat mal wieder gezeigt, dass gerade die statischen Werzeuge durchaus eine wichtige Rolle in der täglichen Entwicklung spielen. Der gesamte Vortrag war eine hervorragende Auffrischung für alle die, die mit den Regeln und Möglichkeiten von PMD, Findbugs oder Checkstyle nicht unbedingt vertraut sind.

Eine spannende Möglichkeit von Checkstyle war mir bis zum Vortrag aber noch gar nicht in den Sinn gekommen. Die Überprüfung von Aufrufen von System.out / System.err / System.gc oder auch das "Logging" von Exceptions per printStackTrace.

Der Grund dafür ist sicherlich, dass es keine Standardregeln für diese Prüfungen gibt. Glücklicherweise aber existiert mit dem RegexpSingleline-Modul eine mächtige Möglichkeit mit Hilfe von regulären Ausdrücken auch diese Fälle abzudecken.

printStackTrace

Die Nutzung von printStackTrace wird durch die bestehenden IDE Einstellungen gerne als Template mit in einen catch-Block integriert. Die Ausgabe der Exception über System.err ist allerdings in den meisten Systemen zurecht nicht erlaubt. Soll die Exception ausgegeben werden, so ist ein Logging-Framework das Mittel der Wahl. Um dieses Verhalten sicher zu stellen, wird eine eigene Regel erstellt.

 

Damit ist sichergestellt, dass folgende Verfehlungen:



direkt durch Checkstyle erkannt und dokumentiert werden.



System.err | System.out

Ähnlich wie printStackTrace ist auch bei der Nutzung von System.err oder System.out ein Logging-Framework die bessere Wahl. Nicht nur, dass dort Details, wie Zeilennummern, Thread-Id oder Klasse ausgegeben werden können, kann außerdem auch zentral das Level des Loggings beeinflusst werden.



Wird also System.out oder System.err innerhalb des Codes genutzt, wird bei der Analyse durch Checkstyle der Fehler direkt erkannt und dokumentiert.





Die Regeln dafür sind mit Hilfe von regulären Ausdrücken schnell erstellt.



System.exit(int) | System.gc()

Niemand wird in webbasierten Anwendungen System.exit(int) oder System.gc() direkt aufrufen. Da es aber auch hier immer mal zu versehentlichen Aufrufen oder sonstigen Fehlern kommen kann, ist eine Überprüfung mittels Checkstyle sinnvoll. Eine wie folgt definierte Methode...



... führt automatisch zu Fehlern bei der Überprüfung.



Die zugehörigen Checkstyle-Regeln sind folgendermaßen definiert: