Posts mit dem Label Maven werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Maven 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.

20.11.2012

Maven - Filtering von Resourcen

Auf der Suche nach einer Möglichkeit eine Webanwendung durch den Timestamp und die POM-Version zu kennzeichnen bin ich über die Möglichkeit des Filterings gestolpert.


Über das Filtering ist es recht leicht möglich eine bereits bestehende Properties-Datei zu erweiterten und mit den gewünschten Informationen zu versehen. Der Einfachheit halber wird an dieser Stelle nur das Filtering beschrieben, die Anwendung selbst wird als Konsolenanwendung gebaut. Der Aufbau der Anwendung ist der folgende:


Die Anwendung wird nach dem Packaging auf der Konsole gestartet. Die Anwendung selbst ist nicht mehr als das Lesen der Properties und das nachfolgende Schreiben auf der Konsole.



Ein erster Aufruf zeigt die folgende Ausgabe auf der Konsole:


Wie zu sehen ist, werden die Properties zur Laufzeit noch nicht ersetzt. Für ein Filtering der Resource-Dateien wird eine Erweiterung des POM benötigt.


Nach diesem Schritt ist es möglich, Properties zum Zeitpunkt des Packagings ersetzen zu lassen. Das gilt natürlich auf allen Einträgen im Resource-Verzeichnis. Nach dem Packaging ändert sich die Ausgabe wie folgt:


Zu sehen ist, dass die erste Property, ${pom.version}, als Standardproperty ersetzt werden konnte. Die andere Property, ${last.build}, bleibt allerdings unaufgelöst. Das liegt daran, dass diese noch nicht im POM definiert ist.


Sobald diese definiert ist, kann eine Ausgabe wie gewünscht realisiert werden.


Es gibt unterschiedliche Szenarien in denen ein Filtering zum Einsatz kommen kann. Nicht nur das Hinzufügen von Build-Informationen zu Web-Anwendungen, sondern auch das Ersetzen von speziellen Informationen für Tests, Stage-sepzifische Builds oder anderen spezielleren Einsatzzwecken.

Nice to know.

13.10.2012

Maven Build Profiles - Test unterschiedlicher JPA Provider

Für einen zukünftigen Vortrag habe ich mir mir heute die unterschiedlichen JPA Provider etwas genauer angeschaut.
Auf dem Plan standen, neben Hibernate, EclipseLink oder auch OpenJPA.


Um für die Betrachtung eine möglichst schnell zu wechselnde Laufzeitumgebung zu haben, habe ich mir die Maven Build Profiles mal wieder ins Gedächtnis gerufen. Ziel der Build Profiles ist es ja, dass man recht leicht zwischen dedizierten Umgebungen wechseln kann. Gleichzeitig kann man in den Build-Profilen aber auch selektiv Dependencies oder Properties überschreiben, setzen oder neu definieren. Also eigentlich genau das richtig für mein Unterfangen, oder?

Begonnen habe ich mit einer einfachen Entität, dem Standard-Beispiel quasi. Basis für die gesamte Betrachtung war eine einfache Person mit ein paar wenigen Attributen.


Eine einfache und leicht zu verstehende Entität. Um die Provider möglichst einfach zu testen, habe ich einen kleinen JUnit-Test erstellt. Dieser versucht eine Person zu erstellen, diese zu persistieren und schlussendlich auch wieder aus der Datenbank zu lesen.


Der Test selbst ist unspektakulär, der EntityManager wird vor jedem Test erstellt und es wird eine Transaktion geöffnet. Nach jedem Test wird der EntityManager wieder geschlossen. Interessant ist allerdings noch die Erzeugung der EntityManagerFactory. Dies wird vor dem Test selbst in der @BeforeClass Methode ausgeführt und sieht wie folgt aus:


Der Name der Persistence-Unit wird an dieser Stelle aus einer System-Property ausgelesen. Je nach Provider wird eine der drei Persistence-Units für die Erzeugung der EntityManagerFactoryherangezogen.

Damit diese Property vom Buildprozess aus gesteuert werden kann, wird das Surefire-Plugin um einen Konfigurationseintrag erweitert.


Mit Hilfe dieser Property können nun die Build Profiles elegant die Werte überschreiben und damit die zugehörige Persistence-Unit für den Test auswählen.


Durch diese Konfiguration kann für jeden Provider ein eigenständiges Profil erstellt werden, welches, von den anderen Profilen unabhängig, eigene Dependencies definiert und vollkommen autark aufgerufen werden kann. Damit ist ein Wechsel des Providers bereits während der Testphase möglich.


Ein Aufruf von mvn clean test -P EclipseLink liefert dann direkt die folgende Ausgabe.


In beiden Fällen wird die Auswahl der Persistence-Unit über die überschriebene Property getätigt. Die Dependencies und sonstigen Einstellungen werden ebenfalls aus dem aktivierten Profil entnommen.

Der Code ist wie immer im Repository verfügbar.

15.01.2012

Xtend - Eclipse-Einrichtung mit einem "Hello World"

Nach dem wirklich hervorragenden Vortrag von und bei der Auftaktveranstaltung der Java User Group - Ostfalen wurde mein Interesse für die Java Erweiterung Xtend geweckt. Daher habe ich mich an ein einfaches erstes Beispiel gesetzt, welches das Aufsetzen der Umgebung und ein kleines Programm zeigt.

Das Aufsetzen der Entwicklungsumgebung ist Dank eines hervorragenden Plugins rechtschaffen einfach und kann ohne größeren Aufwand realisiert werden. Vorrausetzung ist lediglich ein JDK größer oder gleich der Version 5.
Die IDE wird fertig konfiguriert bereits auf der Projektseite zum Downlad angeboten, so dass weiterer Konfigurationsaufwand entfällt. Der Einfachheit halber habe ich mich für den Download der kompletten IDE entschieden, so dass ich meine bestehende Installation nicht anpassen muss.


Die bereitgestellte Version ist ein Eclipse Indigo mit bereits vorinstallierten Plugins für die Entwicklung mit Xtend.


Die Plugins können aber auch über den Marketplace von Eclipse nachgeladen werden. Ein entsprechender Eintrag steht dort zur Verfügung. Weitere Plugins können natürlich wie gewohnt installiert werden. So habe ich für die Beispiele das M2Eclipse und das Subclipse Plugin nachinstalliert.

Nach der erfolgreichen Installation folgt ein erstes Beispiel für den Umgang mit Xtend. Für ein realisitisches Beispiel wird die Runtime nicht über Eclipse eingebunden sondern wird mittels Maven Plugin in den Buildprozess integriert. Danke auch an  Dafür wird folgende Dependency ergänzt:


Damit später sowohl die Dependency für die Bibliotheken, als auch die Dependencies für das Build-Plugin aufgelöst werden können, müssen zwei Repositories ergänzt werden.


Im Anschluss wird das build-helper-maven-plugin konfiguriert.



Damit die, durch Xtend, generierten Sourcen nach einem Clean erneut erstellt werden, muss das maven-clean-plugin für diesen Schritt erweitert werden.


Nun kann auch das letzte Plugin zum Lifecycle hinzugefügt werden, so dass die Sourcen generiert werden.


Nach diesen Schritten sollten die Dependencies nach einem kurzen Build des Workspace in der Projekthierarchie zu finden sein.


In einigen Fällen kann es nun zu einer Fehlermeldung durch das M2Eclipse Plugin kommen. Dies ist ein Bug innerhalb des Plugins und bereits bekannt. Tritt eine der beiden folgenden Fehlermeldungen auf, gibt es eine Möglichkeit diesen Fehler zu beheben.

Plugin execution not covered by lifecycle configuration: org.eclipse.xtend2:xtend-maven-plugin:2.2.0:compile (execution: default, phase: generate-sources)

Plugin execution not covered by lifecycle configuration: org.eclipse.xtend2:xtend-maven-plugin:2.2.0:testCompile (execution: default, phase: generate-test-sources)

In diesem Fall wird ein Wechsel des Xtend Plugins vorgenommen und für den Build die Version 2.2.1 verwendet.


Nun kann das erste Beispiel erstellt werden, wie in jeder neuen Sprache ein "Hello World". Dazu wird eine einfache Xtend Klasse erstellt.


Nachdem die Klasse angelegt worden ist und ein erster Build über den Workspace gelaufen ist, sollte eine generierte Klasse im Verzeichnis src/main/xtend-gen vorhanden sein.


Ein Vergleich der beiden Klassen macht direkt kleine, aber wesentliche Unterschiede deutlich.


Im letzten Schritt wird nun die eigentliche Methode implementiert, so dass die ersten Nachrichten an die Welt verschickt werden können.


Wie also zu sehen ist, bietet Xtend eine schöne Möglichkeit effektiver zu arbeiten und teils überflüssige Typbezeichner oder auch Sprachelemente wegzulassen. Sicherlich gewöhnungsbedürftig, aber auf jeden Fall eine spannende Spacherweiterung für den Java-Entwickler! Da lohnt es sich über den Tellerrand zu schauen, demnächst sicherlich mehr!

Das Beispiel ist als komplettes Projekt wie immer im Repository zu finden!