Eclipse Buildship - nach der IDE kommt die Cloud

Ich bin in letzer Zeit fleißig meine Eclipse Projekte auf Gradle konvertieren. Gradle ist ein Build Tool. Apache Maven, Apache Ant sind bekannte Größen. Wieso sollte man Gradle nutzen? Gradle ist das neuste Build Tool, Standard für jedes Android Projekt, zudem ist die Syntax für die Konfiguration erheblich kompakter als bei z.B. Maven, welches auf XML setzt. Lässt man alles bei den Defaults, so muss praktisch nichts geändert werden.

1. Build Tools

Mithilfe von Gradle kann ein Java Projekt automatisch gebaut werden. Und das überall, unabhängig von der IDE. Außerdem kümmert sich Gradle um Abhängigkeiten, Artefakte wie fremde Bibliotheken, die beim Bauen automatisch von zentralen Quellen wie Maven Central heruntergeladen werden. Selbstredend werden beim Bauen auch Unit-Tests automatisch mit ausgeführt. Dank dem Gradle Wrapper-Skript kann das Projekt sofort und überall von jedermann gebaut werden - ob Windows, Linux oder Mac OS X, das Ausführen des Wrapperskripts genügt, um Gradle selbst automatisch im Projektordner herunterzuladen, welches daraufhin das Projekt baut.

Bei einem Build werden ausführlichste Test-Reports generiert, die die Resultate von jUnit-Tests festhalten.

2. Continuous Integration

Erst Build-Tools öffnen die Tür zur Continuous Integration, CI. Beispiele dafür sind Jenkins und Travis CI. CI bedeutet im Wesentlichen, dass das Bauen, sowie Testen, durch das Build Tool automatisch geschieht, bei jedem Commit (Änderung) am Code. Somit wird sichergestellt, dass das Projekt immer baut und sich noch so verhält wie Vorgegeben, bevor es freigegeben wird.

3. Continuous Deployment / Delivery

Automatisches, reproduzierbares Bauen und Testen des Projekts übernehmen Build Tools wie Gradle und Dienste wie Jenkins. Es gibt nur ein Problem: Man kontrolliert die Umgebung beim Kunden nicht, die Produktivumgebung.

Containersysteme wie Docker versprechen hier Abhilfe: Indem nicht mehr die Applikation selbst, sondern ein Application Container eingesetzt wird, welcher alle Abhängigkeiten wie Programmbibliotheken (bei Java eher weniger relevant) oder z.B. spezielle JVM-Versionen enthält, wird eine immer gleiche, reproduzierbare Umgebung geschaffen, was garantiert, dass sich das Programm überall gleich verhält. Docker Container basieren fast ausschließlich auf einer minimalen Linux-Variante.

4. Cloud

Tools wie Docker Swarm, Apache Mesos oder Google Kubernetes erlauben die Orchestrierung von Containern, also das Verwalten von Containern in einem Cluster aus mehreren Rechnern. Willkommen in der Cloud. Man hat bloß noch eine einzige, große Ressource an Rechenleistung. Hier kann je nach Last horizontal skaliert werden.  

Schritt 4 ist schwierig, dieser kostet nämlich Geld. Was ich toll finde, dass GitHub, Docker Hub und Travis CI für Opensource-Projekte gratis genutzt werden dürfen. Ergo sind Schritt 1-3 abgedeckt, jeder kann sie mit minimalem Aufwand in sein Projekt integrieren.

  • GitHub und Docker Hub Verknüpfung für automatische Dockerfile Builds - CD
  • GitHub und Travis CI Verknüpfung für CI
  • GitHub als zentraler Git Server und Verwaltungsoberfläche
  • GitHub mit JitPack.io Verknüpfung - Bereitstellen von Build-Artefakten
  • GitHub Pages für Javadoc Hosting

Existierende Eclipse Projekte für Gradle konvertieren

Wie bekomme ich nun möglichst schmerzfrei existierende, normale Eclipse Java Projekte in ein Gradle Projekt konvertiert? Zuerst einmal muss die Buildship Erweiterung aus dem Eclipse Marketplace installiert sein.

Hier erstellt man ein neues Gradle Projekt, von diesem können die * .project * .classpath * build.gradle

in`s eigene Projekt kopiert werden. Dies ist Voraussetzung, dass Eclipse das Projekt nachher richtig erkennt. Eclipse bitte während den Änderungen geschlossen halten.

Weil Eclipse so buggy wie immer ist, ist es besser, in diesem neuen, leeren Gradle Projekt einfach den src Ordner zu löschen, anschließend den Rest vom alten Projekt entsprechend der Verzeichnisstruktur rüberzukopieren.

Weiterhin muss nur noch die Verzeichnishierarchie entsprechend dem Gradle Standard angepasst werden.

Vorher:

├── src
│   └── net
│		└── dckg
│			└── asdf
│				└── MyClass.java
└── test
	└── net
		└── dckg
			└── asdf
				└── MyTestClass.java

Nachher:

└── src
	├── main
	│   └── java
	│		└── net
	│			└── dckg
	│				└── asdf
	│					└── MyClass.java
	└── test
		└── java
			└── net
				└── dckg
					└── asdf
						└── MyTestClass.java

Eclipse Buildship (Gradle) Projekte

Ich empfehle, mit Eclipse immer ein Gradle Projekt anzulegen. Spart unnötige Arbeit.

JAR bauen

Handelt es sich bei dem Projekt um eine Library, kann man eine .jar bauen lassen Dazu in die build.gradle folgendes hinzufügen:

sourceCompatibility = 1.8
version = '1.0'

jar {
	manifest {
		attributes 'Implementation-Title': 'net.dckg.asdf',
				   'Implementation-Version': version
	}
}

Ist das Projekt auf GitHub, so kann mit JitPack für andere Gradle/Maven-User automatisch eine Dependency bereitgestellt werden.

Gebaut wird immer mit gradle build

Javadocs

Javadocs können mit gradle myJavadocs generiert werden, in der build.gradle:

task myJavadocs(type: Javadoc) {    
	source = sourceSets.main.allJava
	classpath = configurations.compile
	destinationDir = file("./doc/")
}

Applikation

Für eine standalone-Applikation sind ledigleich zwei Zeilen in der build.gradle anzupassen, es ist die Main-Klasse, die angegeben werden muss. Ausgeführt wird die Applikation mit gradle run. Weiterhin wird eine .zip generiert mit resultierendem JAR, sowie Bash / Batch Skript zum Ausführen des Programms.

Externe Libs

Es reicht praktisch eine Zeile mit dem dependency-Namen, eventuell muss noch eine Zeile mit dem Repository hinzugefügt werden. Möchte man eine .jar direkt lokal einfügen, so kann man diese mit entsprechender Direktive im libs Ordner platzieren. Das bietet sich an, wenn die Dependency nicht in einem eigenen Maven/etc. Repository online publiziert wurde.

.gitignore

Eine passende .gitignore gibt es hier.

Tests

Alles, was an jUnit-Tests im Unterverzeichnis src/test/java/ liegt, wird bei jedem Build ausgeführt. Siehe dazu auch die generierten Reports im build Ordner.

Travis CI Integration (GitHub)

Man legt im Root des Projekts die .travis.yml Datei an und verknüpft das Projekt mit Travis CI.

  Update 17.02.2017 Eclipse Projektkonvertierungsanleitung geändert.

Update 09.03.2017

Eclipse Dependency synchronisieren

Fügt man dem Projekt via build.gradle eine neue Lib hinzu, wird diese erst einmal nicht erkannt, d.h. Eclipse kennt die Klassen, das Paket nicht. Dazu kann man rechts auf den Projektordner klicken, Gradle auswählen und dort auf den einzigsten Eintrag, das Projekt mit Gradle synchronisieren.

Sollte dies fehlschlagen, durch Fehlermeldung, so kann es sein, dass der Projektordner anders als das Projekt, wie es in der settings.gradle spezifiziert wurde, heißt. Das sollte die Fehlermeldung aber auch sagen.

Projektverzeichnisname und Projektname in der settings.gradle müssen immer übereinstimmen!