Kapitel 1. Erste Schritte: Kompilieren und Ausführen von Java

Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com

1.0 Einleitung

In diesem Kapitel geht es um einige Einstiegsaufgaben, die du beherrschen musst, bevor du weitermachen kannst. Man sagt, dass man krabbeln muss, bevor man laufen kann, und laufen, bevor man Fahrrad fahren kann. Bevor du irgendetwas in diesem Buch ausprobieren kannst, musst du in der Lage sein, deinen Java-Code zu kompilieren und auszuführen. Deshalb fange ich hier an und zeige dir verschiedene Möglichkeiten, wie du das machen kannst: mit dem JDK, der integrierten Entwicklungsumgebung (IDE) und den Build-Tools (Ant, Maven usw.). Ein weiteres Problem, mit dem die meisten Leute konfrontiert werden, ist die korrekte Einstellung von CLASSPATH. Das wird als nächstes behandelt. Danach folgen Warnungen vor Auslaufmodellen, die du wahrscheinlich bei der Pflege von altem Java-Code antreffen wirst. Das Kapitel endet mit einigen allgemeinen Informationen über bedingte Kompilierung, Unit-Tests, Assertions und Debugging.

Wenn du Java noch nicht installiert hast, musst du es herunterladen. Beachte, dass es verschiedene Downloads gibt. Das JRE (Java Runtime Environment) war bis Java 8 ein kleinerer Download für Endbenutzer. Da es viel weniger Desktop-Java gibt als früher, wurde das JRE zugunsten von jlink abgeschafft, um einen benutzerdefinierten Download zu erstellen (siehe Rezept 15.8). Der JDK- oder Java SDK-Download ist die vollständige Entwicklungsumgebung, die du brauchst, wenn du Java-Software entwickeln willst.

Standard-Downloads für die aktuelle Version von Java sind unter auf der Website von Oracle verfügbar.

Manchmal findest du Vorabversionen der nächsten Java-Version auf http://jdk.java.net. Das gesamte JDK wird als Open-Source-Projekt gepflegt, und der OpenJDK-Quellbaum wird (mit Änderungen und Ergänzungen) zur Erstellung der kommerziellen und unterstützten Oracle JDKs verwendet.

Wenn du bereits mit deiner IDE zufrieden bist, kannst du diesen Teil überspringen. Er dient dazu, sicherzustellen, dass jeder seine Programme kompilieren und debuggen kann, bevor wir weitermachen.

1.1 Java kompilieren und ausführen: Standard JDK

Problem

Du musst dein Java-Programm kompilieren und ausführen.

Lösung

Dies ist einer der wenigen Bereiche, in denen das Betriebssystem deines Computers die Portabilität von Java beeinträchtigt, also lass uns diese Probleme zuerst aus dem Weg räumen.

JDK

Das Java Development Kit (JDK) für die Befehlszeile zu verwenden, ist vielleicht die beste Möglichkeit, um mit den neuesten Verbesserungen in Java Schritt zu halten. Vorausgesetzt, du hast das Standard-JDK am Standardort installiert und/oder seinen Speicherort in deinem PATH festgelegt, solltest du in der Lage sein, die Kommandozeilen-JDK-Tools auszuführen. Verwende die Befehlejavac zum Kompilieren und java zum Ausführen deines Programms (und, nur unter Windows, javaw, um ein Programm ohne Konsolenfenster auszuführen), etwa so:

C:\javasrc>javac HelloWorld.java

C:\javasrc>java HelloWorld
Hello, World

C:\javasrc>

Wenn das Programm auf andere Klassen verweist, für die der Quellcode verfügbar ist (im selben Verzeichnis), eine kompilierte .class-Datei aber nicht, kompiliert javac sie automatisch für dich. Ab Java 11 kannst du bei einfachen Programmen, die keine solche Co-Kompilierung benötigen, die beiden Vorgänge kombinieren, indem du einfach die Java-Quelldatei an den Befehl java übergibst:

	$ java HelloWorld.java
	Hello, Java
	$
	

Wie du an der (fehlenden) Ausgabe des Compilers sehen kannst, funktionieren sowohl javac als auch die Java-Kompilierung nach der Unix-Philosophie "no news is good news": Wenn ein Programm in der Lage war, das zu tun, was du von ihm verlangt hast, sollte es sich nicht die Mühe machen, dir mitzuteilen, dass es das getan hat.

Es gibt eine optionale Einstellung namens CLASSPATH , die in Rezept 1.5 besprochen wird und die bestimmt, wo Java nach Klassen sucht. CLASSPATH Wenn diese Einstellung gesetzt ist, wird sie sowohl von javac als auch von java verwendet. In älteren Java-Versionen musste man CLASSPATH so einstellen, dass es "." einschließt, um ein einfaches Programm aus dem aktuellen Verzeichnis auszuführen; das ist bei aktuellen Java-Implementierungen nicht mehr der Fall .

Der javac-Compiler von Sun/Oracle ist die offizielle Referenzimplementierung. Es gab mehrere alternative Open-Source-Befehlszeilen-Compiler, darunter Jikes und Kaffe, die aber größtenteils nicht mehr aktiv gepflegt werden.

Es gab auch einige Java-Runtime-Klone, darunter Apache Harmony, Japhar, die IBM Jikes Runtime (von derselben Website wie Jikes) und sogar JNode, ein komplettes, eigenständiges, in Java geschriebenes Betriebssystem; aber seit die Sun/Oracle JVM Open Source (GPL) ist, werden die meisten dieser Projekte nicht mehr gepflegt. Harmony wurde im November 2011 von Apache aufgegeben.

macOS

Das JDK ist eine reine Befehlszeile. Am anderen Ende des Spektrums, wenn es um das Verhältnis zwischen Tastatur und Bildschirm geht, steht der Apple Macintosh. Es wurden schon viele Bücher darüber geschrieben, wie toll die Mac-Benutzeroberfläche ist, und ich werde mich nicht in diese Debatte einmischen. macOS (Release 10.x des Betriebssystems) basiert auf BSD Unix (und "Mach"). Daher verfügt es über eine reguläre Befehlszeile (das Programm Terminal, das unter /Programme/Dienstprogramme versteckt ist) sowie über die traditionellen Unix-Befehlszeilen-Tools und die grafischen Mac-Tools. Wenn du macOS verwendest, kannst du die JDK-Befehlszeilen-Tools oder eines der modernen Build-Tools nutzen. Kompilierte Klassen können mit dem Jar Packager, der in Rezept 15.6 beschrieben wird, in klickbare Anwendungen verpackt werden. Mac-Fans können eines der vielen vollständigen IDE-Tools verwenden, die in Rezept 1.3 besprochen werden. Apple bietet XCode als IDE an, die aber nicht sehr Java-freundlich ist.

1.2 Java kompilieren und ausführen: GraalVM für bessere Leistung

Problem

Du hast gehört, dass Graal eine JVM von Oracle ist, die schneller ist als das Standard-JDK, und du möchtest sie ausprobieren. Graal verspricht eine bessere Leistung und bietet die Möglichkeit, Programmiersprachen zu mischen und deinen Java-Code für eine bestimmte Plattform vorzukompilieren.

Lösung

Lade GraalVM herunter und installiere es.

Diskussion

GraalVM bezeichnet sich selbst als "eine universelle virtuelle Maschine für Anwendungen, die in JavaScript, Python, Ruby, R, JVM-basierten Sprachen wie Java, Scala, Clojure, Kotlin und LLVM-basierten Sprachen wie C und C++ geschrieben wurden".

Beachte, dass sich Graal schnell verändert. Dieses Rezept spiegelt den aktuellen Stand zum Zeitpunkt der Drucklegung (Ende 2019) wider, aber es kann sein, dass es bereits neuere Versionen und geänderte Funktionen gibt, wenn du bereit bist, es zu installieren.

Bei Redaktionsschluss basiert GraalVM auf OpenJDK 11, was bedeutet, dass du Module und andere Java 9-, 10- und 11-Funktionen nutzen kannst, aber keine Unterstützung für Java 12-, 13- oder 14-Funktionen hast. Du kannst dein eigenes Graal auf späteren Versionen bauen, da der vollständige Quellcode auf GitHub liegt.

Weitere Informationen überGraalVM findest du auf derWebsite . Siehe auchdiese Präsentationvon Chris Thalinger, der seit anderthalb Jahrzehnten an JVMs arbeitet.

Beginne auf der Downloadseite.Du musst dich zwischen der Community Edition und der Enterprise Edition entscheiden. Um Lizenzprobleme zu vermeiden, beginnt dieses Rezept mit der Community Edition. Du kannst einen Tarball für Linux, macOS und Windows herunterladen. Es gibt an dieser Stelle keinen offiziellen Installer. Um sie zu installieren, öffne ein Terminalfenster und versuche Folgendes (das gewählte Verzeichnis ist für macOS):

$ cd /Library/Java/JavaVirtualMachines
$ tar xzvf ~/Downloads/graalvm-ce-NNN-VVV.tar.gz # replace with actual version
$ cd
$ /usr/libexec/java_home -V # macOS only
11.0.2, x86_64:	"OpenJDK 11.0.2"
	/Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home
   1.8.0_221, x86_64:	"GraalVM CE 19.2.0.1"
	/Library/Java/JavaVirtualMachines/graalvm-ce-19.2.0.1/Contents/Home
$

Bei den meisten Linux-Versionen kannst du nach der Installation eines JDKs denStandardbefehlalternatives verwenden, um dieses zu deinem Standard zu machen. Unter MacOS bestätigt die Ausgabe des java_home-Befehls, dass du GraalVM installiert hast, aber es ist noch nicht deine Standard-JVM. Um das zu tun, musst du deine PATH einstellen:

export JAVA_HOME=<where you installed GraalVM>/Contents/Home
export PATH=$JAVA_HOME/bin:$PATH

Achte darauf, dass du :$PATH am Ende der Zeile einfügst (kein Leerzeichen), sonst scheinen alle deine Standard-Befehlszeilen-Tools zu verschwinden (wenn du diesen Fehler gemacht hast, logge dich einfach aus und wieder ein, um deinen Pfad wiederherzustellen). Ich schlage vor, dass du deine Anmeldeskripte erst aktualisierst, wenn du sicher bist, dass deine Einstellungen korrekt sind.

Jetzt solltest du die Graal-Version von Java ausführen. Das solltest du nun sehen:

$ java -version
openjdk version "1.8.0_222"
OpenJDK Runtime Environment (build
  1.8.0_222-20190711112007.graal.jdk8u-src-tar-gz-b08)
OpenJDK 64-Bit GraalVM CE 19.2.0.1 (build 25.222-b08-jvmci-19.2-b02, mixed mode)

Deine Ausgabe kann sich unterscheiden, aber solange dort "GraalVM" steht, sollte alles in Ordnung sein.

Graal enthält eine Reihe nützlicher Tools, darunter native-image, das in einigen Fällen eine Klassendatei in eine ausführbare Binärdatei für die jeweilige Plattform übersetzen kann, was die Startgeschwindigkeit optimiert und auch die Downloadgröße reduziert, die für die Ausführung einer einzelnen Anwendung benötigt wird. Das native-image-Tool muss separat übergu install native-image heruntergeladen werden.

In Rezept 18.4 werden wir einige der anderen Nicht-Java-Sprachen ausprobieren.

1.3 Kompilieren, Ausführen und Testen mit einer IDE

Problem

Es ist umständlich, mehrere Tools für die verschiedenen Entwicklungsaufgaben zu verwenden.

Lösung

Verwende eine integrierte Entwicklungsumgebung (IDE), die das Bearbeiten, Testen, Kompilieren, Ausführen, Debuggen und die Paketverwaltung kombiniert.

Diskussion

Viele Programmierer/innen finden, dass die Verwendung einer Handvoll separater Tools - ein Texteditor, ein Compiler und ein Runner-Programm, ganz zu schweigen von einem Debugger - zu viel ist. Eine IDE fasst all diese Werkzeuge in einem einzigen Toolset mit einer grafischen Benutzeroberfläche zusammen. Es gibt viele IDEs, und die besseren von ihnen sind voll integrierte Tools mit eigenen Compilern und virtuellen Maschinen. Klassenbrowser und andere Funktionen von IDEs runden die Benutzerfreundlichkeit dieser Werkzeuge ab. Heutzutage verwenden die meisten Entwickler eine IDE, weil sie dadurch ihre Produktivität steigern können. Obwohl ich als Kommandozeilen-Junkie angefangen habe, finde ich, dass IDE-Funktionen wie die folgenden mich produktiver machen:

Code-Vervollständigung:: Ians Regel lautet hier, dass ich nie mehr als drei Zeichen eines Namens eintippe, der der IDE bekannt ist; lass den Computer das Tippen übernehmen!Inkrementelle Kompilierungsfunktionen:: Notiere und melde Kompilierungsfehler, während du tippst, anstatt zu warten, bis du fertig getippt hast.Refactoring:: Die Möglichkeit, weitreichende, aber verhaltenserhaltende Änderungen an einer Codebasis vorzunehmen, ohne Dutzende von einzelnen Dateien manuell bearbeiten zu müssen.

Darüber hinaus habe ich nicht vor, die Vorzüge der IDE gegenüber dem Kommandozeilenprozess zu diskutieren; ich verwende beide Modi zu unterschiedlichen Zeiten und bei unterschiedlichen Projekten. Ich werde nur ein paar Beispiele für die Verwendung einiger Java-basierter IDEs zeigen.

Die drei beliebtesten Java-IDEs, die auf allen gängigen Computerplattformen und einigen Nischenplattformen laufen, sind Eclipse, NetBeans und IntelliJ IDEA. Eclipse ist die am weitesten verbreitete IDE, aber auch die anderen haben einen besonderen Platz in den Herzen und Köpfen einiger Entwickler. Wenn du für Android entwickelst, wurde das ADT traditionell für Eclipse entwickelt, ist aber inzwischen zu IntelliJ übergegangen, das die Grundlage für Android Studio, die Standard-IDE für Android, und für Googles andere mobile Plattform, Flutter, bildet. Alle drei IDEs sind plug-in-basiert und bieten eine große Auswahl an optionalen Plug-ins und Plug-ins von Drittanbietern, um die IDE zu erweitern, z. B. um andere Programmiersprachen, Frameworks und Dateitypen zu unterstützen. Während der folgende Absatz die Erstellung und Ausführung eines Programms mit Eclipse zeigt, bieten die IDEs von IntelliJ IDEA und NetBeans alle ähnliche Funktionen.

Eine der beliebtesten plattformübergreifenden Open-Source-IDEs für Java ist Eclipse, die ursprünglich von IBM entwickelt wurde und heute von der Eclipse Foundation betreut wird, der Heimat vieler Softwareprojekte wie Jakarta, dem Nachfolger der Java Enterprise Edition. Die Eclipse-Plattform dient auch als Grundlage für andere Tools wie die SpringSource Tool Suite (STS) und den Rational Application Developer (RAD) von IBM. Alle IDEs tun im Grunde das Gleiche, wenn du anfängst. Das Beispiel in Abbildung 1-1 zeigt, wie du ein neues Projekt startest.

jcb4 0101
Abbildung 1-1. Starten eines neuen Projekts mit dem Eclipse New Java Class Wizard

Der inAbbildung 1-2 gezeigte Eclipse New Java Class Wizard zeigt, wie du eine neue Klasse erstellst.

jcb4 0102
Abbildung 1-2. Erstellen einer neuen Klasse mit dem Eclipse New Java Class Wizard

Eclipse verfügt wie alle modernen IDEs über eine Reihe von Refactoring-Funktionen, die in Abbildung 1-3 dargestellt sind.

jcb4 0103
Abbildung 1-3. Refactoring in Eclipse

Und natürlich kannst du mit allen IDEs deine Anwendung ausführen und/oder debuggen.Abbildung 1-4 zeigt das Ausführen einer Anwendung; zur Abwechslung und Neutralität wird dies mit IntelliJ IDEA gezeigt.

macOS enthält Apples Developer Tools. Die wichtigste IDE ist Xcode. Leider unterstützen die aktuellen Versionen von Xcode die Java-Entwicklung nicht wirklich, so dass ich sie für unsere Zwecke nicht empfehlen kann. Sie ist in erster Linie für diejenigen gedacht, die nicht portierbare Anwendungen (nur für iOS oder OS X) in den Programmiersprachen Swift oder Objective-C entwickeln. Auch wenn du mit OS X arbeitest, solltest du für die Java-Entwicklung eine der drei Java-IDEs verwenden.

Microsoft VSCode (früher Teil von Visual Studio) hat in letzter Zeit in Java-Kreisen einige Aufmerksamkeit bekommen, aber es ist keine Java-spezifische IDE. Probiere es aus, wenn du magst.

Wie wählst du eine IDE aus? Vielleicht wird sie von deiner Organisation vorgegeben oder von der Mehrheit deiner Entwickler-Kollegen gewählt. Da alle drei großen IDEs (Eclipse, NetBeans und IntelliJ) kostenlos heruntergeladen werden können und zu 100 % Open Source sind, solltest du sie alle ausprobieren und herausfinden, welche am besten zu deiner Art der Entwicklung passt. Unabhängig davon, welche Plattform du für die Java-Entwicklung verwendest, solltest du, wenn du eine Java-Laufzeitumgebung hast, eine Vielzahl von IDEs zur Auswahl haben.

jcb4 0104
Abbildung 1-4. IntelliJ-Programmausgabe

Siehe auch

Auf den Websites der einzelnen IDEs findest du eine aktuelle Liste mit Ressourcen, darunter auch Bücher. In Tabelle 1-1 findest du die jeweilige Website.

Tabelle 1-1. Die drei wichtigsten Java-IDEs und ihre Websites
Produktname Projekt-URL Hinweis

Eclipse

https://eclipse.org/

Grundlage der STS, RAD

IntelliJ Idee

https://jetbrains.com/idea/

Grundlage von Android Studio

Netbeans

https://netbeans.apache.org

Überall laufen lassen, wo JavaSE läuft

Diese großen IDEs sind erweiterbar; in ihrer Dokumentation findest du eine Liste der vielen, vielen verfügbaren Plug-ins. Die meisten von ihnen ermöglichen es dir, Plug-ins innerhalb der IDE zu finden und zu installieren. Bei Eclipse kannst du den Eclipse Marketplace benutzen, der sich unten im Hilfemenü befindet. Wenn du ein Plug-in schreiben möchtest, das die Funktionalität deiner IDE erweitert, kannst du das auch in Java tun.

Für Eclipse habe ich einige nützliche Informationen unterhttps://darwinsys.com/java. Die Seite enthält eine Liste von Shortcuts, die die Produktivität der Entwickler erhöhen.

1.4 Java mit JShell erforschen

Problem

Du möchtest Java-Ausdrücke und APIs schnell ausprobieren, ohne jedes Mal eine Datei mit public class X { public static void main(String[] args) { …​ } erstellen zu müssen.

Lösung

Verwende JShell, den REPL-Interpreter (Read-Evaluate-Print-Loop) von Java.

Diskussion

Seit Java 11 ist JShell ein Standardbestandteil von Java. Mit ihr kannst du Java-Anweisungen eingeben und auswerten lassen, ohne eine Klasse und ein Hauptprogramm erstellen zu müssen. Du kannst sie für schnelle Berechnungen verwenden, um eine API auszuprobieren, um zu sehen, wie sie funktioniert, oder für fast jeden anderen Zweck; wenn du einen Ausdruck findest, der dir gefällt, kannst du ihn in eine reguläre Java-Quelldatei kopieren und dauerhaft speichern. JShell kann auch als Skriptsprache über Java verwendet werden, aber der Overhead beim Starten der JVM bedeutet, dass sie für schnelles Skripting nicht so schnell ist wie awk, Perl oder Python.

REPL-Programme sind sehr praktisch und keine neue Idee (LISP-Sprachen aus den 1950er Jahren enthalten sie). Du kannst dir Kommandozeileninterpreter (CLIs) wie die Bash- oder Ksh-Shells unter UNIX/Linux oder Command.com und PowerShell unter Microsoft Windows als REPLs für das gesamte System vorstellen. Viele interpretierte Sprachen wie Ruby und Python können ebenfalls als REPLs verwendet werden. Java hat endlich seine eigene REPL, JShell. Hier ist ein Beispiel für ihre Verwendung:

$ jshell
|  Welcome to JShell -- Version 11.0.2
|  For an introduction type: /help intro

jshell> "Hello"
$1 ==> "Hello"

jshell> System.out.println("Hello");
Hello

jshell> System.out.println($1)
Hello

jshell> "Hello" + sqrt(57)
|  Error:
|  cannot find symbol
|    symbol:   method sqrt(int)
|  "Hello" + sqrt(57)
|            ^--^

jshell> "Hello" + Math.sqrt(57)
$2 ==> "Hello7.54983443527075"

jshell> String.format("Hello %6.3f", Math.sqrt(57)
   ...> )
$3 ==> "Hello  7.550"

jshell> String x = Math.sqrt(22/7) + " " + Math.PI +
   ...> " and the end."
x ==> "1.7320508075688772 3.141592653589793 and the end."

jshell>

Einige offensichtliche Merkmale und Vorteile kannst du hier sehen:

  • Der Wert eines Ausdrucks wird gedruckt, ohne dass du jedes Mal System.out.println aufrufen musst, aber du kannst ihn aufrufen, wenn du willst.

  • Werte, die keiner Variablen zugewiesen werden, erhalten synthetische Bezeichner, wie $1, die in nachfolgenden Anweisungen verwendet werden können.

  • Das Semikolon am Ende einer Anweisung ist optional (es sei denn, du gibst mehr als eine Anweisung in eine Zeile ein).

  • Wenn du einen Fehler machst, bekommst du sofort eine hilfreiche Nachricht.

  • Du kannst die Vervollständigung mit einem einzigen Tabulator erreichen, wie bei der Vervollständigung von Shell-Dateinamen.

  • Du kannst den relevanten Teil der Javadoc-Dokumentation zu bekannten Klassen oder Methoden mit einem Doppel-Tab aufrufen.

  • Wenn du ein schließendes Anführungszeichen, eine Klammer oder eine andere Interpunktion weglässt, wartet JShell einfach auf dich und gibt eine Eingabeaufforderung (…​) aus.

  • Wenn dir ein Fehler unterläuft, kannst du die "Shell History" (Pfeil nach oben) verwenden, um die Anweisung aufzurufen und sie zu korrigieren.

JShell ist auch beim Prototyping von Java-Code nützlich. Ich wollte zum Beispiel einen dieser Gesundheits-Timer, der dich alle halbe Stunde daran erinnert, aufzustehen und dich ein bisschen zu bewegen:

$ jshell
|  Welcome to JShell -- Version 11.0.2
|  For an introduction type: /help intro

jshell> while (true) { sleep (30*60); JOptionPane.showMessageDialog(null,
  "Move it"); }
|  Error:
|  cannot find symbol
|    symbol:   method sleep(int)
|  while (true) { sleep (30*60); JOptionPane.showMessageDialog(null, "Move it");}
|                 ^---^
|  Error:
|  cannot find symbol
|    symbol:   variable JOptionPane
|  while (true) { sleep (30*60); JOptionPane.showMessageDialog(null, "Move it");}
|                                ^---------^

jshell> import javax.swing.*;

jshell> while (true) { Thread.sleep (30*60); JOptionPane.showMessageDialog(null,
"Move it"); }

jshell> while (true) { Thread.sleep (30*60 * 1000);
  JOptionPane.showMessageDialog(null, "Move it"); }

jshell> ^D

Ich habe dann die endgültige Arbeitsversion in eine Java-Datei namens MoveTimer.java geschrieben, eine class Anweisung und eine main() Methode um die Hauptzeile herum eingefügt, die IDE angewiesen, das Ganze neu zu formatieren, und es in meinem darwinsys-api Repository gespeichert.

Experimentiere also ruhig mit JShell. Wenn du etwas gefunden hast, das dir gefällt, benutze entweder /save oder kopiere es und füge es in ein Java-Programm ein und speichere es.

Mehr über JShell erfährst du imOpenJDK JShell Tutorial.

1.5 Effektiver Einsatz von CLASSPATH

Problem

Du musst deine Klassendateien in einem gemeinsamen Verzeichnis aufbewahren, sonst kämpfst du mit CLASSPATH.

Lösung

Setze CLASSPATH auf die Liste der Verzeichnisse und/oder JAR-Dateien, die die gewünschten Klassen enthalten.

Diskussion

CLASSPATH ist eine Liste von Klassendateien in einer beliebigen Anzahl von Verzeichnissen, JAR-Dateien oder ZIP-Dateien. Genau wie die , die dein System zum Auffinden von Programmen verwendet, wird die von der Java-Laufzeit verwendet, um Klassen zu finden. Selbst wenn du etwas so Einfaches wie PATH CLASSPATH java HelloWorld eingibst, sucht der Java-Interpreter an jedem der Orte, die in deinem genannt werden, bis er eine Übereinstimmung findet. Lass uns ein Beispiel durchspielen. CLASSPATH

Die CLASSPATH kann als Umgebungsvariable auf die gleiche Weise gesetzt werden wie andere Umgebungsvariablen, z. B. die Umgebungsvariable PATH. In der Regel ist es jedoch besser, die CLASSPATH für einen bestimmten Befehl in der Befehlszeile anzugeben:

C:\> java -classpath c:\ian\classes MyProg

Angenommen, dein CLASSPATH wäre auf C:\classes;. unter Windows oder ~/classes:. unter Unix oder Mac eingestellt. Angenommen, du hast gerade eine Quelldatei namens HelloWorld.java (ohne Package-Anweisung) in HelloWorld.class im Standardverzeichnis (deinem aktuellen Verzeichnis) kompiliert und versucht, sie auszuführen. Wenn du unter Unix eines der Kernel-Tracing-Tools (trace, strace, truss, oder ktrace) ausführst, würdest du wahrscheinlich das Java-Programm open oder stat oder access die folgenden Dateien sehen:

  • Einige Datei(en) im JDK-Verzeichnis

  • Dann ~/classes/HelloWorld.class, die er wahrscheinlich nicht finden würde

  • Schließlich ./HelloWorld.class, die es finden, öffnen und in den Speicher einlesen würde

Die vage Formulierung "einige Datei(en) im JDK-Verzeichnis" ist versionsabhängig. Du solltest dich nicht mit den JDK-Dateien beschäftigen, aber wenn du neugierig bist, kannst du sie in den Systemeigenschaften finden (siehe Rezept 2.2). Früher gab es eine Variable namens sun.boot.class.path, aber die ist nicht mehr zu finden. Suchen wir nach einer Eigenschaft mit boot im Namen:

jshell> System.getProperties().forEach((k,v) -> {
 ... if (((String)k).contains("boot")) System.out.println(k + "->" +v);})
sun.boot.library.path->/usr/local/jdk-11/lib

Der Grund, warum ich und andere vorschlagen, CLASSPATH nicht als Umgebungsvariable zu setzen, ist, dass wir keine Überraschungen mögen. Es ist leicht, ein JAR zu deinem CLASSPATH hinzuzufügen und dann zu vergessen, dass du das getan hast; ein Programm könnte dann bei dir funktionieren, aber nicht bei deinen Kollegen, weil sie nichts von deiner versteckten Abhängigkeit wissen. Und wenn du eine neue Version zu CLASSPATH hinzufügst, ohne die alte Version zu entfernen, kann es zu Konflikten kommen.

Beachte auch, dass die Angabe des Arguments -classpath dazu führt, dass die Umgebungsvariable CLASSPATH ignoriert wird.

Wenn du CLASSPATH trotzdem als Umgebungsvariable setzen willst, kannst du das tun. Angenommen, du hast auch die JAR-Datei installiert, die die unterstützenden Klassen für die Programme aus diesem Buch enthält, darwinsys-api.jar (der tatsächliche Dateiname, wenn du ihn herunterlädst, kann eineVersionsnummer als Teil des Dateinamens enthalten). Du könntest dann deine CLASSPATH aufC:\classes;C:\classes\darwinsys-api.jar;. unter Windows oder~/classes:~/classes/darwinsys-api.jar:. unter Unix einstellen.

Beachte, dass du den vollständigen Namen der JAR-Datei explizit angeben musst. Im Gegensatz zu einer einzelnen Klassendatei ist eine JAR-Datei nicht verfügbar, wenn du sie in ein Verzeichnis in deinem CLASSPATH einfügst.

Bestimmte spezialisierte Programme (z. B. ein Webserver, auf dem ein Servlet Container läuft) verwenden möglicherweise weder bootpath noch CLASSPATH genau wie gezeigt; diese Anwendungsserver stellen in der Regel ihre eigenen ClassLoader zur Verfügung (siehe Rezept 17.5 für Informationen zu Klassenladern). Bei EE-Web-Containern zum Beispiel setzt du deine Web-App CLASSPATH so, dass sie das Verzeichnis WEB-INF/classes und alle JAR-Dateien unter WEB-INF/lib enthält.

Wie kannst du ganz einfach Klassendateien in ein Verzeichnis in deinem CLASSPATH erzeugen? Der Befehl javac hat die Option -d dir, die angibt, wohin die Ausgabe des Compilers gehen soll. Wenn ich zum Beispiel -d verwende, um die HelloWorld-Klassendatei in meinem $HOME/classes-Verzeichnis abzulegen, gebe ich einfach Folgendes ein (beachte, dass ich von nun an den Paketnamen zusätzlich zum Klassennamen verwende, wie ein gutes Kind):

javac -d $HOME/classes HelloWorld.java
java -cp $HOME/classes starting.HelloWorld
Hello, world!

Solange sich dieses Verzeichnis in meinem CLASSPATH befindet, kann ich unabhängig von meinem aktuellen Verzeichnis auf die Klassendatei zugreifen. Das ist einer der Hauptvorteile von CLASSPATH.

Während diese Beispiele die explizite Verwendung von java mit -classpath zeigen, ist es in der Regel bequemer (und reproduzierbar), ein Build-Tool wie Maven(Rezept 1.7) oder Gradle zu verwenden, die automatisch die CLASSPATH sowohl für die Kompilierung als auch die Ausführung bereitstellen.

Beachte, dass es ab Java 9 auch einen Modulpfad (Umgebungsvariable MODULEPATH, Kommandozeilenargument --module-path entry[:,…​]) mit der gleichen Syntax wie der Klassenpfad gibt. Der Modulpfad enthält Code, der modularisiert wurde; das Java-Modulsystem wird in Rezept 2.5 und Rezept 15.9 behandelt.

1.6 Herunterladen und Verwenden der Codebeispiele

Problem

Du möchtest meinen Beispielcode ausprobieren und/oder meine Hilfsklassen verwenden.

Lösung

Lade das neueste Archiv mit den Quelldateien des Buches herunter, entpacke es und führe Maven aus (siehe Rezept 1.7), um die Dateien zu kompilieren.

Diskussion

Der Quellcode, der in diesem Buch als Beispiel verwendet wird, ist in mehreren Quellcode-Repositories enthalten, die seit 1995 kontinuierlich weiterentwickelt werden. Diese sind in Tabelle 1-2 aufgeführt.

Tabelle 1-2. Die wichtigsten Quellen-Repositories
Name des Repositorys GitHub URL Paketbeschreibung Ungefähre Größe

javasrc

http://github.com/IanDarwin/javasrc

Java Code Beispiele/Demos

1.400 Klassen

darwinsys-api

http://github.com/Iandarwin/darwinsys-api

Eine veröffentlichte API

200 Klassen

Du kannst diese Repositories von den in Tabelle 1-2 angegebenen GitHub-URLs herunterladen. GitHub bietet dir die Möglichkeit, eine ZIP-Datei mit dem aktuellen Stand des gesamten Repositories herunterzuladen und einzelne Dateien auf der Weboberfläche einzusehen. Der Download mit git clone statt als Archiv ist vorzuziehen, weil du dann jederzeit mit einem einfachen git pull-Befehl aktualisieren kannst. Und bei der Menge an Aktualisierungen, die diese Codebasis für die aktuelle Version von Java erfahren hat, wirst du sicher auch nach der Veröffentlichung des Buches noch Änderungen finden.

Wenn du mit Git nicht vertraut bist, lies "CVS, Subversion, Git, Oh My!

javasrc

Dies ist das größte Repo und besteht hauptsächlich aus Code, der geschrieben wurde, um eine bestimmte Funktion oder API zu zeigen. Die Dateien sind in Unterverzeichnissen nach Themen geordnet, von denen viele mehr oder weniger den Buchkapiteln entsprechen - zum Beispiel ein Verzeichnis für Strings-Beispiele(Kapitel 3), Regex für reguläre Ausdrücke(Kapitel 4), Zahlen(Kapitel 5) und so weiter. Das Archiv enthält auch den Index nach Namen und den Index nach Kapiteln von der Download-Seite, damit du die Dateien, die du brauchst, leicht finden kannst.

Die javasrc-Bibliothek ist weiter in ein Dutzend Maven-Module unterteilt (siehe Tabelle 1-3), damit du nicht ständig alle Abhängigkeiten für alles auf deinem CLASSPATH benötigst.

Tabelle 1-3. JavaSrc Maven Module
Verzeichnis/Modulname Beschreibung

pom.xml

Maven übergeordnetes Pom

Rdemo-web

R-Demo mit einem Web-Framework

Desktop

AWT und Swing (nicht mehr im Java Cookbook enthalten)

ee

Enterprise-Kram (nicht mehr im Java Cookbook enthalten)

graal

GraalVM Demos

jlink

JLink-Demos

json

JSON-Verarbeitung

Haupt

Enthält den Großteil der Dateien, d.h. diejenigen, die aufgrund von CLASSPATH oder anderen Gründen nicht in einem der anderen Module enthalten sein müssen.

restdemo

REST-Dienst Demo

Funke

Apache Spark Demo

Testen

Code zum Testen

unsicher

Demo der Klasse Unsafe

xml

XML-Zeug (nicht mehr im Java Cookbook enthalten)

darwinsys-api

Ich habe eine Sammlung nützlicher Dinge aufgebaut, indem ich einige wiederverwendbare Klassen aus javasrc in meine eigene API verschoben habe, die ich in meinen eigenen Java-Projekten verwende. Ich verwende Beispielcode daraus in diesem Buch und ich importiere Klassen daraus in viele der anderen Beispiele. Wenn du also die Beispiele einzeln herunterlädst und kompilierst, solltest du zuerst die Datei darwinsys-api-1.x.jar (für den neuesten Wert von x) herunterladen und sie in dein CLASSPATH einbinden. Wenn du den javasrc-Code mit Eclipse oder Maven baust, kannst du diesen Download überspringen, da das Maven-Skript auf oberster Ebene mit der JAR-Datei für diese API beginnt.

Eine kompilierte JAR-Datei von darwinsys-api ist inMaven Central verfügbar; du findest sie, indem du nach darwinsys suchst. Dies ist das aktuelle Maven-Artefakt:

<dependency>
   <groupId>com.darwinsys</groupId>
   <artifactId>darwinsys-api</artifactId>
   <version>1.1.3</version>
</dependency>

Diese API besteht aus etwa zwei Dutzend com.darwinsys Paketen, die in Tabelle 1-4 aufgelistet sind. Die Struktur ähnelt der Standard-Java-API; das ist beabsichtigt. Diese Pakete umfassen mittlerweile etwa 200 Klassen und Schnittstellen. Für die meisten von ihnen gibt es eine Javadoc-Dokumentation, die mit dem Quellcode-Download eingesehen werden kann.

Tabelle 1-4. Die com.darwinsys-Pakete
Paketname Paketbeschreibung

com.darwinsys.csv

Klassen für Dateien mit kommagetrennten Werten

com.darwinsys.database

Klassen für den Umgang mit Datenbanken in allgemeiner Form

com.darwinsys.diff

Vergleich Dienstprogramme

com.darwinsys.genericui

Allgemeines GUI-Zeug

com.darwinsys.geo

Klassen, die sich auf Ländercodes, Provinzen/Staaten usw. beziehen

com.darwinsys.graphics

Grafiken

com.darwinsys.html

Klassen (bisher nur eine) für den Umgang mit HTML

com.darwinsys.io

Klassen für Ein- und Ausgabeoperationen, die Javas zugrunde liegende I/O-Klassen nutzen

com.darwinsys.jsptags

Java EE JSP-Tags

com.darwinsys.lang

Klassen für den Umgang mit Standardfunktionen von Java

com.darwinsys.locks

Pessimistische Sperr-API

com.darwinsys.mail

Klassen für den Umgang mit E-Mails, vor allem eine Komfortklasse für das Senden von E-Mails

com.darwinsys.model

Beispielhafte Datenmodelle

com.darwinsys.net

Networking

com.darwinsys.preso

Präsentationen

com.darwinsys.reflection

Reflexion

com.darwinsys.regex

Reguläre Ausdrücke: ein REDemo-Programm, eine Grep-Variante

com.darwinsys.security

Sicherheit

com.darwinsys.servlet

Servlet-API-Helfer

com.darwinsys.sql

Klassen für den Umgang mit SQL-Datenbanken

com.darwinsys.swingui

Klassen, die bei der Erstellung und Verwendung von Swing-GUIs helfen

com.darwinsys.swingui.layout

Ein paar interessante LayoutManager-Implementierungen

com.darwinsys.testdata

Testdatengeneratoren

com.darwinsys.testing

Prüfwerkzeuge

com.darwinsys.unix

Unix-Helfer

com.darwinsys.util

Ein paar verschiedene Hilfsklassen

com.darwinsys.xml

XML-Dienstprogramme

Viele dieser Klassen werden in diesem Buch als Beispiele verwendet; suche einfach nach Dateien, deren erste Zeile wie folgt beginnt:

package com.darwinsys;

Du wirst auch feststellen, dass viele der anderen Beispiele Importe aus den com.darwinsys Paketen haben.

Allgemeine Hinweise

Am besten verwendest du git clone, um eine Kopie der beiden Git-Projekte herunterzuladen, und machst dann alle paar Monate einen git pull, um Aktualisierungen zu erhalten. Alternativ kannst du von derKatalogseite dieses Buches eine einzelne Schnittmenge beider Bibliotheken herunterladen, die fast ausschließlich aus Dateien besteht, die tatsächlich im Buch verwendet werden. Dieses Archiv wird aus den Quellen erstellt, die bei der Formatierung dynamisch in das Buch eingebunden werden, und sollte daher genau die Beispiele widerspiegeln, die du im Buch siehst. Es wird aber nicht so viele Beispiele enthalten wie die drei Einzelarchive, und es ist auch nicht garantiert, dass alles kompiliert werden kann, weil Abhängigkeiten fehlen, und es wird auch nicht oft aktualisiert. Wenn du aber nur Teile in ein Projekt kopieren willst, an dem du gerade arbeitest, ist dies vielleicht die richtige Wahl. Links zu all diesen Dateien findest du auf meiner eigenen Website für dieses Buch; folge einfach dem Link Downloads.

Die beiden separaten Repositories enthalten mehrere in sich geschlossene Projekte, die sowohl mit Eclipse(Rezept 1.3) als auch mit Maven(Rezept 1.7) gebaut werden können. Beachte, dass Maven beim ersten Aufruf eines Projekts automatisch eine Vielzahl von Bibliotheken abruft, die Voraussetzung für die Erstellung sind. Maven stellt also sicher, dass du mit einer schnellen Internetverbindung online bist. Wenn du dich dafür entscheidest, einzelne Teile zu bauen, findest du die Liste der Abhängigkeiten in der Datei pom.xml. Wenn du andere Werkzeuge als Eclipse oder Maven verwendest, kann ich dir mit den im Download enthaltenen Steuerdateien leider nicht helfen.

Wenn du eine ältere Java-Version als Java 12 hast, werden einige Dateien nicht kompiliert. Du kannst Ausschlusselemente für die Dateien erstellen, die bekanntermaßen nicht kompiliert werden.

Mein gesamter Code in den beiden Projekten wird unter der am wenigsten restriktiven Lizenz veröffentlicht, der Zwei-Klausel-BSD-Lizenz . Wenn du ihn nützlich findest, baue ihn in deine eigene Software ein. Du brauchst mich nicht um Erlaubnis zu bitten, sondern kannst ihn einfach mit Quellenangabe verwenden. Wenn du damit reich wirst, schick mir etwas Geld.

Tipp

Die meisten Kommandozeilenbeispiele beziehen sich auf Quelldateien, vorausgesetzt, du befindest dich in src/main/java, und auf lauffähige Klassen, vorausgesetzt, du befindest dich im Build-Verzeichnis (z. B. normalerweise target/classes) oder hast es zu deinem CLASSPATH hinzugefügt. Dies wird nicht bei jedem Beispiel erwähnt, da dies eine Menge Papier verschwenden würde.

Caveat lector

Die Repos sind seit 1995 in Entwicklung. Das bedeutet, dass du einige Codes finden wirst, die nicht mehr auf dem neuesten Stand sind oder nicht mehr den bewährten Methoden entsprechen. Das ist nicht überraschend: Jeder Code wird alt, wenn er nicht aktiv gepflegt wird. (Deshalb zitiere ich an dieser Stelle den Song "Do You Really Want to Hurt Me" von Culture Club: "Gib mir Zeit, mein Verbrechen zu erkennen.") Wenn die Ratschläge im Buch nicht mit dem Code übereinstimmen, den du im Repo gefunden hast, solltest du das im Hinterkopf behalten. Eine der Praktiken von Extreme Programming ist das kontinuierliche Refactoring, also die Möglichkeit, jeden Teil der Codebasis jederzeit zu verbessern. Wundere dich nicht, wenn der Code im Online-Quellcodeverzeichnis von dem im Buch abweicht; es vergeht kaum ein Monat, in dem ich den Code nicht verbessere, und die Ergebnisse werden ziemlich oft übertragen und veröffentlicht. Wenn es also Unterschiede zwischen dem, was im Buch steht, und dem, was du auf GitHub findest, gibt, sei froh und nicht traurig, denn du hast den Vorteil der Rückschau. Außerdem können die Leute auf GitHub ganz einfach über Pull Requests beitragen; das macht es so interessant. Wenn du einen Fehler oder eine Verbesserung findest, schick mir einen Pull Request! Das konsolidierte Archiv auf der Seite für dieses Buch wird nicht mehr so häufig aktualisiert werden.

1.7 Automatisieren von Abhängigkeiten, Kompilieren, Testen und Bereitstellen mit Apache Maven

Problem

Du willst ein Tool, das alles automatisch erledigt: deine Abhängigkeiten herunterlädt, deinen Code kompiliert, deine Tests kompiliert und ausführt, die App verpackt und installiert oder bereitstellt.

Lösung

Verwende Apache Maven.

Diskussion

Maven ist ein Java-zentriertes Build-Tool, das ein ausgeklügeltes, verteiltes Abhängigkeitsmanagementsystem enthält, das auch Regeln für die Erstellung von Anwendungspaketen wie JAR-, WAR- und EAR-Dateien und deren Verteilung auf eine Reihe verschiedener Ziele enthält. Während ältere Build-Tools sich auf das Wie konzentrieren, konzentrieren sich Maven-Dateien auf das Was, d.h. auf die Angabe, was du tun willst.

Maven wird durch eine Datei namens pom.xml (für Project Object Model) gesteuert. Eine pom.xml könnte zum Beispiel so aussehen:

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>my-se-project</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>my-se-project</name>
  <url>http://com.example/</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

Hier wird ein Projekt mit dem Namen my-se-project (mein Standard-Projekt) angegeben, das in eine JAR-Datei gepackt wird. Es hängt vom JUnit 4.x-Framework für Unit-Tests ab (siehe Rezept 1.10), benötigt es aber nur zum Kompilieren und Ausführen von Tests. Wenn ich mvn install in das Verzeichnis mit diesem POM eintippe, stellt Maven sicher, dass es eine Kopie der angegebenen Version von JUnit (und alles, wovon JUnit abhängt) hat. Dann kompiliert es alles (indem es den CLASSPATH und andere Optionen für den Compiler setzt), führt alle Unit-Tests aus und erzeugt, wenn sie alle bestanden sind, eine JAR-Datei für das Programm. Diese wird dann in meinem persönlichen Maven-Repository (unter ~/.m2/repository) installiert, so dass andere Maven-Projekte von meiner neuen Projekt-JAR-Datei abhängen können. Beachte, dass ich Maven nicht sagen muss, wo sich die Quelldateien befinden oder wie sie zu kompilieren sind - all das wird von vernünftigen Standardeinstellungen auf der Grundlage einer klar definierten Projektstruktur erledigt. Der Programmquelltext wird in src/main/java erwartet und die Tests in src/test/java; wenn es sich um eine Webanwendung handelt, wird die Web-Root standardmäßig in src/main/webapp erwartet. Natürlich kannst du diese Einstellungen außer Kraft setzen .

Beachte, dass selbst die vorangehende Konfigurationsdatei nicht von Hand geschrieben werden muss und auch nicht geschrieben wurde; Mavens Archetyp-Generierungsregeln erlauben es, die Startversion eines beliebigen von mehreren hundert Projekttypen zu erstellen. So wurde die Datei erstellt:

$ mvn archetype:generate \
    -DarchetypeGroupId=org.apache.maven.archetypes \
    -DarchetypeArtifactId=maven-archetype-quickstart \
    -DgroupId=com.example -DartifactId=my-se-project

[INFO] Scanning for projects...
Downloading: http://repo1.maven.org/maven2/org/apache/maven/plugins/
    maven-deploy-plugin/2.5/maven-deploy-plugin-2.5.pom
[several dozen or hundred lines of downloading POM files and Jar files...]
[INFO] Generating project in Interactive mode
[INFO] Archetype [org.apache.maven.archetypes:maven-archetype-quickstart:1.1]
    found in catalog remote
[INFO] Using property: groupId = com.example
[INFO] Using property: artifactId = my-se-project
Define value for property 'version':  1.0-SNAPSHOT: :
[INFO] Using property: package = com.example
Confirm properties configuration:
groupId: com.example
artifactId: my-se-project
version: 1.0-SNAPSHOT
package: com.example
 Y: : y
[INFO] ------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype:
    maven-archetype-quickstart:1.1
[INFO] ------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.example
[INFO] Parameter: packageName, Value: com.example
[INFO] Parameter: package, Value: com.example
[INFO] Parameter: artifactId, Value: my-se-project
[INFO] Parameter: basedir, Value: /private/tmp
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: /private/tmp/
    my-se-project
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6:38.051s
[INFO] Finished at: Sun Jan 06 19:19:18 EST 2013
[INFO] Final Memory: 7M/81M
[INFO] ------------------------------------------------------------------------

Alternativ kannst du auch mvn archetype:generate ausführen und den Standard aus einer ziemlich langen Liste auswählen. Der Standard ist ein Java-Schnellstart-Archetyp, der den Einstieg erleichtert.

Die IDEs (siehe Rezept 1.3) bieten Unterstützung für Maven. Wenn du zum Beispiel Eclipse verwendest, ist M2Eclipse (m2e) ein Eclipse-Plug-in, das die Abhängigkeiten deines Eclipse-Projekts aus deiner POM-Datei erstellt; dieses Plug-in wird standardmäßig mit den aktuellen Java Developer Builds von Eclipse ausgeliefert. Das Plug-in wird standardmäßig mit den aktuellen Java Developer Builds von Eclipse ausgeliefert. Es ist auch für einige ältere Versionen verfügbar; Details zum Plug-in findest du auf der Eclipse-Website.

Eine POM-Datei kann jedes der Standard-Goals neu definieren. Zu den üblichen Maven-Goals (die standardmäßig so definiert sind, dass sie etwas Sinnvolles tun) gehören die folgenden:

sauber

Entfernt alle erzeugten Artefakte

kompilieren.

Kompiliert alle Quelldateien

Test

Kompiliert und führt alle Unit-Tests aus

Paket

Baut das Paket

installieren

Installiert pom.xml und das Paket in dein lokales Maven-Repository zur Verwendung durch deine anderen Projekte

einsetzen.

Versucht, das Paket zu installieren (z. B. auf einem Anwendungsserver)

Die meisten Schritte rufen implizit die vorherigen Schritte auf. Zum Beispiel kompiliert packagealle fehlenden Klassendateien und führt die Tests aus, wenn dies nicht bereits in diesem Durchlauf geschehen ist.

Es gibt ein optionales distributionManagement Element in der POM-Datei oder ein -DaltDeploymentRepositoryauf der Befehlszeile, um einen alternativen Bereitstellungsort anzugeben. Es gibt anwendungsserver-spezifische Ziele, die von den Anbietern von Anwendungsservern bereitgestellt werden; ein Beispiel ist der WildFly Application Server (vor einem Jahrzehnt oder mehr als JBoss AS bekannt), bei dem du einige zusätzliche Plug-ins gemäß der Dokumentation installierst und dann auf dem Anwendungsserver mit

mvn wildfly:deploy

anstelle des normalen Deployments. Da ich diese Maven-Beschwörung häufig verwende, habe ich einen Shell-Alias oder eine Batch-Datei mwd, um auch das zu automatisieren.

Vor- und Nachteile von Maven

Maven kann mit komplexen Projekten umgehen und ist sehr konfigurierbar. Ich baue die Projekte darwinsys-api und javasrc mit Maven und überlasse es Maven, die Abhängigkeiten zu finden, wodurch der Download des Projektquellcodes kleiner wird (eigentlich wird der Download-Overhead auf die Server der Projekte selbst verlagert). Die einzigen wirklichen Nachteile von Maven sind, dass es eine Weile dauert, bis man sich damit vertraut gemacht hat, und dass es schwer zu diagnostizieren ist, wenn etwas schief läuft. Eine gute Internetsuchmaschine ist dein Freund, wenn etwas fehlschlägt.

Ein Problem, das ich befürchte, ist, dass sich ein Hacker Zugang zur Website eines Projekts verschaffen und eine neue Version eines POMs ändern oder installieren könnte. Maven holt sich automatisch aktualisierte POM-Versionen. Es verwendet jedoch Hash-Signaturen, um zu überprüfen, dass die Dateien während des Download-Prozesses nicht manipuliert wurden, und alle hochzuladenden Dateien müssen mit PGP/GPG signiert werden, so dass ein Angreifer sowohl den Upload-Account als auch die Signierschlüssel kompromittieren müsste. Mir ist jedoch nicht bekannt, dass dies jemals passiert ist.

Siehe auch

Beginne auf http://maven.apache.org.

1.8 Automatisieren von Abhängigkeiten, Kompilieren, Testen und Bereitstellen mit Gradle

Problem

Du willst ein Build-Tool, das dich nicht dazu zwingt, eine Menge XML in deiner Konfigurationsdatei zu verwenden.

Lösung

Nutze das einfache Build-Dateiformat von Gradle mit der Konfiguration nach Konvention für kürzere Build-Dateien und schnelle Builds.

Diskussion

Gradle ist das jüngste in der Reihe der Build-Tools (Make, Ant und Maven). Gradle bezeichnet sich selbst als "das Automatisierungswerkzeug für Unternehmen" und ist mit den anderen Build-Tools und IDEs integriert.

Im Gegensatz zu den anderen Java-basierten Tools verwendet Gradle nicht XML als Skriptsprache, sondern eine domänenspezifische Sprache (DSL), die auf der JVM- und Java-basierten Skriptsprache Groovy basiert.

Du kannst Gradle installieren, indem du es von der Gradle-Website herunterlädst, die ZIP-Datei entpackst und das Unterverzeichnis bin zu deinem Pfad hinzufügst.

Dann kannst du mit Gradle arbeiten. Angenommen, du verwendest das Standard-Quellverzeichnis(src/main/java, src/main/test), das unter anderem von Maven und Gradle gemeinsam genutzt wird, dann wird die Beispieldatei build.gradle in Beispiel 1-1 deine App bauen und deine Unit-Tests ausführen.

Beispiel 1-1. Beispiel build.gradle-Datei
# Simple Gradle Build for the Java-based DataVis project
apply plugin: 'java'
# Set up mappings for Eclipse project too
apply plugin: 'eclipse'

# The version of Java to use
sourceCompatibility = 11
# The version of my project
version = '1.0.3'
# Configure JAR file packaging
jar {
    manifest {
        attributes 'Main-class': 'com.somedomainnamehere.data.DataVis',
        'Implementation-Version': version
    }
}

# optional feature: like -Dtesting=true but only when running tests ("test task")
test {
    systemProperties 'testing': 'true'
}

Du kannst die umfangreichen Investitionen der Industrie in die Maven-Infrastruktur nutzen, indem du Zeilen wie diese in deine build.gradle einfügst:

# Tell Gradle to look in Maven Central
repositories {
    mavenCentral()
}

# We need darwinsys-api for compiling as well as JUnit for testing
dependencies {
    compile group: 'com.darwinsys', name: 'darwinsys-api', version: '1.0.3+'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

Siehe auch

Es gibt noch viel mehr Funktionen in Gradle. Beginne auf der Gradle-Website und sieh dir die Dokumentation an.

1.9 Umgang mit Auslaufwarnungen

Problem

Dein Code ließ sich früher sauber kompilieren, aber jetzt gibt er Warnungen vor der Veralterung aus.

Lösung

Du musst geblinzelt haben. Entweder lebst du gefährlich mit den Warnungen oder du überarbeitest deinen Code, um sie zu beseitigen.

Diskussion

Jede neue Version von Java enthält eine Menge leistungsstarker neuer Funktionen, aber zu einem hohen Preis: Während der Entwicklung dieser neuen Funktionen finden die Java-Betreuer einige alte Funktionen, die nicht richtig gemacht wurden und nicht mehr verwendet werden sollten, weil sie sie nicht wirklich reparieren können. Bei der ersten großen Überarbeitung stellten sie zum Beispiel fest, dass die Klasse java.util.Date einige schwerwiegende Einschränkungen in Bezug auf die Internationalisierung aufwies. Daher sind viele Methoden und Konstruktoren der Klasse Date als "veraltet" gekennzeichnet. Laut dem American Heritage Dictionary bedeutet "etwas verwerfen" "seine Missbilligung ausdrücken". Die Java-Entwickler missbilligen also die alte Art und Weise, Dinge zu tun. Versuche, diesen Code zu kompilieren:

import java.util.Date;

/** Demonstrate deprecation warning */
public class Deprec {

    public static void main(String[] av) {

        // Create a Date object for May 5, 1986
        @SuppressWarnings("deprecation")
        // EXPECT DEPRECATION WARNING without @SuppressWarnings
        Date d = new Date(86, 04, 05);
        System.out.println("Date is " + d);
    }
}

Was ist passiert? Als ich es kompilierte (bevor ich die @SuppressWarnings() Anmerkung hinzufügte), bekam ich diese Warnung:

C:\javasrc>javac Deprec.java
Note: Deprec.java uses or overrides a deprecated API.  Recompile with
"-deprecation" for details.
1 warning
C:\javasrc>

Wir folgen also den Anweisungen. Für Details, kompiliere mit -deprecation, um die zusätzlichen Details zu sehen:

C:\javasrc>javac -deprecation Deprec.java
Deprec.java:10: warning: constructor Date(int,int,int) in class java.util.Date
has been deprecated
                Date d = new Date(86, 04, 05);          // May 5, 1986
                         ^
1 warning

C:\javasrc>

Die Warnung ist einfach: Der Date Konstruktor, der drei Integer-Argumente benötigt, ist veraltet. Wie kann man das beheben? Die Antwort ist, wie bei den meisten Fragen zur Verwendung, in der Javadoc-Dokumentation der Klasse nachzuschlagen. In der Einführung auf der Seite Date heißt es unter anderem:

Die Klasse Date repräsentiert einen bestimmten Zeitpunkt mit einer Genauigkeit von einer Millisekunde.

Vor dem JDK 1.1 hatte die Klasse Date zwei zusätzliche Funktionen. Sie ermöglichte die Interpretation von Datumswerten als Jahr, Monat, Tag, Stunde, Minute und Sekunde. Außerdem ermöglichte sie das Formatieren und Parsen von Datumsstrings. Leider war die API für diese Funktionen nicht internationalisierbar. Ab JDK 1.1 sollte die Klasse Calendar verwendet werden, um zwischen Datums- und Zeitfeldern zu konvertieren, und die Klasse DateFormat , um Datumsstrings zu formatieren und zu parsen. Die entsprechenden Methoden in Date sind veraltet.

Und in der Beschreibung des Drei-Ganzzahl-Konstruktors heißt es in der Date javadoc:

Date(int year, int month, int date)

Veraltet. Ab JDK Version 1.1, ersetzt durch Calendar.set(year + 1900, month, date)oder GregorianCalendar(year + 1900, month, date).

Natürlich wurde die ältere Klasse Date durch LocalDate und LocalDateTime (siehe Kapitel 6) ersetzt, so dass du dieses Beispiel nur in altem Code sehen würdest, aber die Prinzipien des Umgangs mit Verfallswarnungen sind wichtig, weil viele neue Versionen von Java Verfallswarnungen zu Teilen der API hinzufügen, die vorher "OK" waren.

Generell gilt: Wenn etwas veraltet ist, solltest du es nicht mehr in neuem Code verwenden und bei der Wartung des Codes darauf achten, dass die Verwerfungswarnungen entfernt werden.

Neben Date (Java 8 enthält eine ganz neue Datums-/Uhrzeit-API; siehe Kapitel 6) sind die wichtigsten Bereiche der Standard-API, in denen vor der Veraltung gewarnt wird, die wirklich alte Ereignisbehandlung und einige Methoden (einige von ihnen sind wichtig) in der Klasse Thread.

Du kannst auch deinen eigenen Code verwerfen, wenn du einen besseren Weg gefunden hast, Dinge zu tun. Setze eine @Deprecated Annotation direkt vor die Klasse oder Methode, die du verwerfen möchtest, und/oder verwende ein@deprecated Tag in einem javadoc-Kommentar (siehe Rezept 15.2). Der javadoc-Kommentar ermöglicht es dir, die Verwerfung zu erklären, während die Annotation für einige Tools leichter zu erkennen ist, da sie zur Laufzeit vorhanden ist (so kannst du Reflection verwenden; siehe Kapitel 17).

Siehe auch

Es gibt noch zahlreiche andere Tools, die deinen Java-Code zusätzlich prüfen, siehe meine Website zum Prüfen von Java-Programmen.

1.10 Mit Unit-Tests die Korrektheit des Codes aufrechterhalten: JUnit

Problem

Du willst deinen Code nicht debuggen müssen.

Lösung

Nutze Unit-Tests, um jede Klasse während der Entwicklung zu überprüfen.

Diskussion

Es ist zeitaufwändig, einen Debugger zu benutzen, und es ist viel schlimmer, einen Fehler im veröffentlichten Code zu finden! Es ist besser, vorher zu testen. Die Methode der Unit-Tests gibt es schon lange; sie ist ein bewährtes Mittel, um deinen Code in kleinen Blöcken zu testen. In einer OO-Sprache wie Java werden Unit-Tests in der Regel auf einzelne Klassen angewendet, im Gegensatz zu System- oder Integrationstests, bei denen ein kompletter Abschnitt oder sogar die gesamte Anwendung getestet wird.

Ich bin seit langem ein Verfechter dieser grundlegenden Testmethodik. Die Entwickler der Software-Methode, die unter dem Namen Extreme Programming (kurz XP) bekannt ist, befürworten Test-Driven Development (TDD), also das Schreiben der Unit-Tests , bevor du den Code schreibst. Sie befürworten auch, dass die Tests fast jedes Mal ausgeführt werden, wenn du deine Anwendung erstellst. Und sie stellen eine gute Frage: Wenn du keinen Test hast, woher weißt du dann, dass dein Code (noch) funktioniert? Zu dieser Gruppe von Befürwortern des Unit-Tests gehören einige bekannte Persönlichkeiten, darunter Erich Gamma, bekannt für sein Buch Design Patterns, und Kent Beck, bekannt für sein Buch eXtreme Programming (beide Addison-Wesley). Ich schließe mich ihren Befürwortern von Unit-Tests auf jeden Fall an.

In der Tat hatten viele meiner Klassen einen "eingebauten" Einheitstest. Klassen, die keine eigenständigen Hauptprogramme sind, enthielten oft eine main Methode, die nur die Funktionalität der Klasse testet oder zumindest übt. Was mich überrascht hat, ist, dass ich, bevor ich XP kennenlernte, dachte, ich würde dies oft tun, aber eine tatsächliche Überprüfung von zwei Projekten zeigte, dass nur etwa ein Drittel meiner Klassen Testfälle hatte, entweder intern oder extern. Was wir brauchen, ist eine einheitliche Methodik. Diese wird von JUnit bereitgestellt.

JUnit ist eine Java-zentrierte Methodik zur Bereitstellung von Testfällen und kann kostenlos heruntergeladen werden. Es ist ein sehr einfaches, aber nützliches Testwerkzeug. Es ist einfach zu benutzen - du schreibst einfach eine Testklasse mit einer Reihe von Methoden und versiehst sie mit @Test (im älteren JUnit 3.8 mussten die Namen der Testmethoden mit test beginnen). JUnit nutzt die Introspektion (siehe Kapitel 17), um all diese Methoden zu finden und führt sie dann für dich aus. JUnit-Erweiterungen erledigen so unterschiedliche Aufgaben wie Lasttests und das Testen von Unternehmenskomponenten; die JUnit-Website enthält Links zu diesen Erweiterungen. Alle modernen IDEs bieten integrierte Unterstützung für die Erstellung und Ausführung von JUnit-Tests.

Wie kannst du mit JUnit anfangen? Alles, was du tun musst, ist, einen Test zu schreiben. Hier habe ich einen einfachen Test für meine Klasse Person geschrieben und ihn in eine Klasse namens PersonTest eingefügt (beachte das offensichtliche Namensmuster):

public class PersonTest {

    @Test
    public void testNameConcat() {
        Person p = new Person("Ian", "Darwin");
        String f = p.getFullName();
        assertEquals("Name concatenation", "Ian Darwin", f);
    }
}

JUnit 4 gibt es schon seit langem und es funktioniert gut. JUnit 5 ist erst ein paar Jahre alt und hat einige Verbesserungen. Ein einfacher Test wie diese PersonTest Klasse ist in JUnit 4 und 5 gleich (aber mit unterschiedlichen Importen). Die Verwendung zusätzlicher Funktionen, wie z. B. Setup-Methoden, die vor jedem Test ausgeführt werden, erfordert unterschiedliche Annotationen in JUnit 4 und 5.

Um dir zu zeigen, wie du PersonTest manuell ausführst, kompiliere ich den Test und rufe das Kommandozeilen-Test-Harness TestRunner auf:

$ javac PersonTest.java
$ java -classpath .:junit4.x.x.jar junit.textui.TestRunner testing.PersonTest
.
Time: 0.188

OK (1 tests)

$

In der Praxis ist es unglaublich mühsam, die Tests auf diese Weise auszuführen. Deshalb lege ich meine Tests einfach in die Standardverzeichnisstruktur (d.h. src/test/java/) mit demselben Paket wie der zu testende Code und lasse Maven laufen (sieheRezept 1.7), das alle Unit-Tests automatisch kompiliert und ausführt und den Build anhält, wenn ein Test fehlschlägt, und zwar jedes Mal, wenn du versuchst, deine Anwendung zu bauen, zu verpacken oder zu verteilen. Gradle tut das auch.

Alle modernen IDEs bieten integrierte Unterstützung für die Ausführung von JUnit-Tests; in Eclipse kannst du mit der rechten Maustaste auf ein Projekt im Package Explorer klicken und Run As→Unit Test wählen, um alle JUnit-Tests im gesamten Projekt zu finden und auszuführen. Das MoreUnit Plugin (kostenlos im Eclipse Marketplace) soll die Erstellung und Ausführung von Tests vereinfachen.

Mit den Hamcrest-Matchern kannst du aussagekräftigere Tests schreiben, allerdings kostet das einen zusätzlichen Download. Die Unterstützung dafür ist in JUnit 4 mit der statischen Methode assertThat eingebaut, aber du musst die Matcher von Hamcrest oder über das Maven-Artefakt herunterladen.

Hier ist ein Beispiel für die Verwendung der Hamcrest Matcher:

public class HamcrestDemo {

    @Test
    public void testNameConcat() {
        Person p = new Person("Ian", "Darwin");
        String f = p.getFullName();
        assertThat(f, containsString("Ian"));
        assertThat(f, equalTo("Ian Darwin"));
        assertThat(f, not(containsString("/"))); // contrived, to show syntax
    }
}

Siehe auch

JUnit bietet eine umfangreiche eigene Dokumentation, die du von der oben genannten Website herunterladen kannst.

Ein alternatives Unit-Test-Framework für Java ist TestNG. Es hat sich schon früh durchgesetzt, weil es Funktionen wie Java-Annotationen noch vor JUnit eingeführt hat, aber seit JUnit das Annotationsprogramm übernommen hat, ist es das dominierende Paket für Java-Unit-Tests geblieben.

Ein weiteres interessantes Paket istAssertJ, das ähnlich leistungsfähig zu sein scheint wie die Kombination aus JUnit und Hamcrest.

Schließlich muss man oft Ersatzobjekte für die zu testende Klasse erstellen (die Abhängigkeiten der zu testenden Klasse). Du kannst diese zwar von Hand programmieren, aber im Allgemeinen empfehle ich die Verwendung von Paketen wieMockito, die dynamisch Mock-Objekte erzeugen, diese Mocks mit festen Rückgabewerten versehen, überprüfen, ob die Abhängigkeiten korrekt aufgerufen wurden usw.

Erinnere dich: Prüfe früh und oft!

1.11 Wartung deines Codes mit kontinuierlicher Integration

Problem

Du willst sichergehen, dass dein gesamter Code kompiliert wird und regelmäßig die Tests besteht .

Lösung

Verwende einen Continuous Integration Server wie z.B. Jenkins/Hudson.

Diskussion

Wenn du noch nie mit Continuous Integration gearbeitet hast, wirst du dich fragen, wie du ohne sie ausgekommen bist. CI bedeutet, dass alle Entwickler/innen eines Projekts ihre Änderungen regelmäßigin eine einzige Master-Kopie des Projekt-Quelltextesintegrieren (z.B. committen) und dann das Projekt bauen und testen, um sicherzustellen, dass es immer noch funktioniert und die Tests besteht. Das kann ein paar Mal am Tag oder alle paar Tage sein, sollte aber nicht häufiger der Fall sein, sonst stößt die Integration wahrscheinlich auf größere Hürden, wenn mehrere Entwickler/innen dieselbe Datei geändert haben.

Aber nicht nur große Projekte profitieren von CI. Auch bei einem Ein-Personen-Projekt ist es toll, wenn du auf einen einzigen Knopf klicken kannst, um die neueste Version von allem zu prüfen, zu kompilieren, zu verlinken oder zu verpacken, alle automatisierten Tests durchzuführen und eine rote oder grüne Fehlschlaganzeige zu erhalten. Noch besser ist es, wenn dies automatisch jeden Tag oder sogar bei jedem Commit in den Master-Zweig geschieht.

Nicht nur codebasierte Projekte profitieren von CI. Wenn du mehrere kleine Websites hast, ist es ein wichtiger Schritt, sie alle unter CI-Kontrolle zu stellen, um eine automatisierte DevOps-Kultur für die Bereitstellung und Verwaltung von Websites zu entwickeln .

Wenn dir die Idee der KI neu ist, kann ich dir nur empfehlen, den aufschlussreichen Artikel von Martin Fowler ( ) zu diesem Thema zu lesen. Einer der wichtigsten Punkte ist, dass du sowohl die Verwaltung des Codes und aller anderen Artefakte, die für die Erstellung deines Projekts benötigt werden, als auch den eigentlichen Erstellungsprozess automatisieren solltest, möglicherweise mit einem der Build-Tools, die weiter oben in diesem Kapitel besprochen wurden.1

Es gibt viele CI-Server, sowohl kostenlose als auch kommerzielle. In der Open-Source-Welt gehörenCruiseControl und Jenkins/Hudson2 gehören zu den bekanntesten CI-Servern, die du selbst einsetzen kannst. Es gibt auch gehostete Lösungen wieTravis CI,TeamCity oderCircleCI. Diese gehosteten Lösungen machen die Einrichtung und den Betrieb eines eigenen CI-Servers überflüssig. In der Regel befindet sich die Konfiguration direkt in deinem Projektarchiv(travis.yml usw.), sodass der Einsatz vereinfacht wird.

Jenkins läuft als Webanwendung, entweder innerhalb eines Jakarta EE Servers oder auf einem eigenständigen Webserver. Sobald Jenkins gestartet ist, kannst du jeden Standard-Webbrowser als Benutzeroberfläche verwenden. Die Installation und der Start von Jenkins ist so einfach wie das Entpacken einer Distribution und der Aufruf wie folgt:

java -jar jenkins.war

Dadurch wird ein eigener kleiner Webserver gestartet. Wenn du das tust, musst du die Sicherheit konfigurieren, wenn dein Rechner vom Internet aus erreichbar ist!

Viele halten es für sicherer, Jenkins auf einem voll funktionsfähigen Java EE- oder Java-Webserver laufen zu lassen. Alles von Tomcat über JBoss bis hin zu WebSphere oder Weblogic eignet sich für diese Aufgabe und ermöglicht es dir, zusätzliche Sicherheitseinschränkungen vorzunehmen.

Sobald Jenkins läuft und du die Sicherheit aktiviert hast und mit einem Konto mit ausreichenden Rechten eingeloggt bist, kannst du Aufträge erstellen. Ein Auftrag entspricht in der Regel einem Projekt, sowohl in Bezug auf den Ursprung (ein Quellcode-Checkout) als auch in Bezug auf die Ergebnisse (eine .war-Datei, eine ausführbare Datei, eine Bibliothek, eine was auch immer). Um ein Projekt einzurichten, klickst du einfach auf die Schaltfläche Neuer Auftrag oben links im Dashboard, wie in Abbildung 1-6 dargestellt.

Du kannst die ersten Informationen ausfüllen: den Namen des Projekts und eine kurze Beschreibung. Beachte, dass neben jedem Eingabefeld ein Fragezeichen-Symbol steht, das dir Hinweise gibt, während du weitermachst. Scheue dich nicht, einen Blick auf diese Hinweise zu werfen! Abbildung 1-7 zeigt die ersten Schritte beim Einrichten eines neuen Auftrags.

In den nächsten Abschnitten des Formulars verwendet Jenkins dynamisches HTML, um die Eingabefelder auf der Grundlage der von dir angekreuzten Informationen anzuzeigen. Mein Demoprojekt "TooSmallToFail" startet ohne Source Code Management (SCM) Repository, aber dein echtes Projekt befindet sich wahrscheinlich bereits in Git, Subversion oder einem anderen SCM. Mach dir keine Sorgen, wenn dein Projekt nicht aufgelistet ist; es gibt Hunderte von Plug-ins, die mit fast jedem SCM arbeiten. Sobald du dich für einen SCM entschieden hast, gibst du die Parameter ein, mit denen du den Quellcode des Projekts aus diesem SCM-Repository abrufen kannst. Dazu werden Textfelder verwendet, in denen die für den jeweiligen SCM erforderlichen Angaben abgefragt werden: eine URL für Git, ein CVSROOT für CVS usw.

jcb4 0106
Abbildung 1-6. Das Dashboard in Jenkins
jcb4 0107
Abbildung 1-7. Erstellen eines neuen Auftrags in Jenkins

Außerdem musst du Jenkins mitteilen, wann und wie dein Projekt gebaut (und verpackt, getestet, bereitgestellt...) werden soll. Für das "Wann" gibt es mehrere Möglichkeiten, z. B. den Bau nach einem anderen Jenkins-Projekt, den Bau in regelmäßigen Abständen nach einem Zeitplannungsprogramm oder die Abfrage des SCM, ob sich etwas geändert hat (mit demselben Zeitplannungsprogramm). Wenn dein Projekt auf GitHub (und nicht nur auf einem lokalen Git-Server) oder in einem anderen SCM liegt, kannst du das Projekt immer dann erstellen lassen, wenn jemand Änderungen in das Repository einpflegt. Es kommt nur darauf an, die richtigen Plug-ins zu finden und der Dokumentation zu folgen.

Dann geht es um das Wie, also den Build-Prozess. Auch hier sind einige Build-Typen in Jenkins enthalten, und viele weitere sind als Plug-ins verfügbar: Ich habe Apache Maven, Gradle, das traditionelle Unix-Tool make und sogar Shell- oder Befehlszeilen verwendet. Wie zuvor erscheinen Textfelder, die für das von dir gewählte Tool spezifisch sind, sobald du das Tool auswählst. Im Beispiel TooSmallToFail verwende ich den Shell-Befehl /bin/false(der auf jedem Unix- oder Linux-System vorhanden sein sollte), um sicherzustellen, dass das Projekt tatsächlich fehlschlägt, damit du siehst, wie das aussieht.

Du kannst null oder mehr Bauschritte haben; klicke einfach weiter auf die Schaltfläche Hinzufügen und füge weitere hinzu, wie in Abbildung 1-8 gezeigt.

jcb4 0108
Abbildung 1-8. Konfiguration für SCM und Hinzufügen von Build-Schritten in Jenkins

Wenn du denkst, dass du alle notwendigen Informationen eingegeben hast, klicke unten auf der Seite auf die Schaltfläche Speichern und du gelangst zurück zur Hauptseite des Projekts. Hier kannst du auf das lustige kleine SymbolJetzt bauen ganz links klicken, um sofort einen Build zu starten. Wenn du Build-Trigger eingerichtet hast, kannst du auch warten, bis sie ausgelöst werden. Aber würdest du nicht lieber gleich wissen, ob du alles richtig gemacht hast? Abbildung 1-9 zeigt den Start des Builds.

Wenn ein Auftrag fehlschlägt, bekommst du einen roten Ball statt eines grünen. Eigentlich wird bei einem erfolgreichen Auftrag standardmäßig ein blauer Ball angezeigt (die Ampel in Japan, wo Kohsuke lebt, ist blau und nicht grün), aber die meisten Menschen außerhalb Japans bevorzugen Grün als Zeichen für Erfolg, deshalb ist das optionale Plug-in für grüne Bälle oft eines der ersten, das einer neuen Installation hinzugefügt wird.

Neben dem roten oder grünen Ball siehst du einen Wetterbericht, der von sonnig (die letzten Builds waren erfolgreich) bis wolkig, regnerisch oder stürmisch (die letzten Builds waren nicht erfolgreich) reicht.

Klicke auf den Link zu dem Projekt, das fehlgeschlagen ist, und dann auf den Link zur Konsolenausgabe und finde heraus, was falsch gelaufen ist. Der übliche Arbeitsablauf ist dann, Änderungen am Projekt vorzunehmen, sie in das Quellcode-Repository zu übertragen und den Jenkins-Build erneut auszuführen.

jcb4 0109
Abbildung 1-9. Nachdem ein neuer Auftrag in Jenkins hinzugefügt wurde

Es gibt Hunderte von optionalen Plug-ins für Jenkins. Um dir das Leben zu erleichtern, kannst du fast alle von ihnen installieren, indem du auf den Link Jenkins verwalten klickst und dann auf Plug-ins verwalten gehst. Auf der Registerkarte Verfügbar sind alle Plug-ins aufgelistet, die auf Jenkins.org verfügbar sind. Du musst nur das Kästchen neben den gewünschten Plug-ins anklicken und dann auf Übernehmen klicken. Dort findest du auch die Updates. Wenn das Hinzufügen oder Aktualisieren eines Plug-ins einen Neustart erfordert, siehst du einen gelben Ball und einen entsprechenden Hinweis; andernfalls solltest du einen grünen (oder blauen) Ball sehen, der den Erfolg des Plug-ins anzeigt. Du kannst die Liste der Plug-ins auch direkt im Internet einsehen.

Ich habe erwähnt, dass Jenkins ursprünglich unter dem Namen Hudson bekannt war. Das Hudson-Projekt existiert immer noch und wird auf der Eclipse-Website gehostet. Als ich das letzte Mal nachgesehen habe, haben beide Projekte die Kompatibilität der Plug-ins beibehalten, sodass viele oder die meisten Plug-ins des einen mit dem anderen verwendet werden können. Die beliebtesten Plug-ins sind in beiden Projekten auf der Registerkarte "Verfügbar" zu finden, und das meiste, was in diesem Rezept über Jenkins gesagt wird, gilt auch für Hudson. Wenn du ein anderes CI-System verwendest, musst du in der Dokumentation des jeweiligen Systems nachsehen, aber die Konzepte und Vorteile sind ähnlich.

1.12 Stack Traces lesbar machen

Problem

Du bekommst zur Laufzeit einen Exception Stack Trace, aber die meisten wichtigen Teile haben keine Zeilennummern.

Lösung

Vergewissere dich, dass du mit aktiviertem Debugging kompiliert hast.

Diskussion

Wenn ein Java-Programm eine Ausnahme auslöst, wandert die Ausnahme den Aufrufstapel hinauf, bis eine catch Klausel gefunden wird, die ihr entspricht. Wenn keine gefunden wird, fängt das Java-Interpreterprogramm, das deine main() Methode aufgerufen hat, die Ausnahme ab und gibt einen Stack-Traceback aus, der alle Methodenaufrufe zeigt, die vom Anfang des Programms bis zu der Stelle gelangt sind, an der die Ausnahme ausgelöst wurde. Du kannst diesen Traceback in jeder catch Klausel selbst ausgeben: Die Klasse Throwable hat mehrere Überladungen der Methode printStackTrace() .

Der Traceback enthält nur Zeilennummern, wenn sie einkompiliert wurden. Wenn du javac verwendest, ist dies die Standardeinstellung. Wenn du die Option -g hinzufügst, fügt javac auch die Namen lokaler Variablen und andere Informationen in den kompilierten Code ein, was im Falle eines Absturzes bessere Informationen zur Fehlersuche liefert.

1.13 Mehr Java-Quellcode finden

Problem

Du willst eine große Anwendung erstellen und brauchst möglichst wenig Code, um das "Not Invented Here"-Syndrom zu vermeiden.

Lösung

Nutze die Quelle, Luke. Es gibt Tausende von Java-Anwendungen, Frameworks und Bibliotheken, die als Open Source verfügbar sind.

Diskussion

Java-Quellcode gibt es überall. Wie bereits erwähnt, können alle Codebeispiele aus diesem Buch heruntergeladen werden: siehe Rezept 1.6.

Eine weitere wertvolle Ressource ist der Quellcode für die Java API. Du hast es vielleicht noch nicht bemerkt, aber der Quellcode für alle öffentlichen Teile der Java API ist in jeder Version des Java Development Kit enthalten. Du willst wissen, wie java.util.ArrayList wirklich funktioniert? Du hast den Quellcode. Hast du ein Problem, wie sich JTable verhält? Das Standard-JDK enthält den Quellcode für alle öffentlichen Klassen! Suche nach einer Datei namens src.zip oder src.jar; einige Versionen entpacken diese Datei, andere nicht.

Wenn dir das nicht reicht, kannst du den Quellcode für das gesamte JDK kostenlos über das Internet beziehen, entweder über die Mercurial-Quellcode-Bibliothek unter openjdk.java.net oder über den Git-Spiegel unter AdoptOpenJDK auf github.com. Darin enthalten sind die Quellen für die öffentlichen und nicht-öffentlichen Teile der API sowie der Compiler (in Java geschrieben) und ein großer Teil des C/C++-Codes (die Runtime selbst und die Schnittstellen zur nativen Bibliothek). java.io.Reader hat zum Beispiel eine Methode namens read() , die Datenbytes aus einer Datei oder einer Netzwerkverbindung liest. Für jedes Betriebssystem gibt es eine in C geschriebene Version dieser Methode, denn sie ruft den Systemaufruf read() für Unix, Windows, macOS oder was auch immer auf. Das JDK-Source-Kit enthält die Quellen für all diese Dinge.

1.14 Suche nach lauffähigen Java-Bibliotheken

Problem

Du willst eine veröffentlichte Bibliothek wiederverwenden, anstatt eine bekannte Lösung für dein Problem neu zu erfinden.

Lösung

Nutze das Internet, um wiederverwendbare Software zu finden.

Diskussion

Obwohl sich der größte Teil dieses Buches mit dem Schreiben von Java-Code beschäftigt, geht es in diesem Rezept nicht um das Schreiben von Code, sondern um die Verwendung von Code, der von anderen geschrieben wurde. Es gibt Hunderte von guten Frameworks, die du zu deiner Java-Anwendung hinzufügen kannst - warum den platten Reifen neu erfinden, wenn du einen perfekt runden kaufen kannst? Viele dieser Frameworks gibt es schon seit Jahren und sie sind durch das Feedback der Nutzer/innen gut abgerundet worden.

Was aber ist der Unterschied zwischen einer Bibliothek und einem Framework? Das ist manchmal etwas vage, aber im Allgemeinen ist ein Framework ein Programm mit Lücken, die du ausfüllst, während eine Bibliothek Code ist, den du aufrufst. Das ist in etwa so, als würdest du ein Auto bauen, indem du ein fast fertiges Auto ohne Motor kaufst, oder ein Auto, indem du alle Teile kaufst und sie selbst zusammenschraubst.

Wenn du den Einsatz eines Frameworks eines Drittanbieters ( ) in Erwägung ziehst, gibt es viele Möglichkeiten und Fragen zu klären. Eine davon ist die Frage nach den Kosten, die mit der Frage nach Open Source und Closed Source zusammenhängt. Die meisten Open-Source-Tools können kostenlos heruntergeladen und verwendet werden, entweder ohne Bedingungen oder mit Bedingungen, die du einhalten musst. Hier ist nicht der Platz, um diese Lizenzierungsfragen zu erörtern, daher verweise ich dich auf Understanding Open Source and Free Software Licensing (O'Reilly).

Viele Open-Source-Software ist in Form von kompilierten Bibliotheken auf Maven Central verfügbar, wie in "Maven Central" beschrieben : Mapping the World of Java Software".

Einige bekannte Sammlungen von Open-Source-Frameworks und -Bibliotheken für Java sind in Tabelle 1-5 aufgeführt. Die meisten Projekte auf diesen Seiten werden von der Community kuratiert, d. h. sie werden von ihr bewertet und für gut befunden.

Tabelle 1-5. Seriöse Open-Source-Java-Sammlungen
Organisation URL Anmerkungen

Apache Software Foundation

http://projects.apache.org

Nicht nur ein Webserver!

Eclipse Software Foundation

https://eclipse.org/projects

Heimat des IDE und der Jakarta EE

Spring Framework

http://spring.io/projects

Heimat von einem Dutzend Frameworks: Spring IOC (DI-Fabrik), Spring MVC (Web), mehr

JBoss Gemeinschaft

https://redhatofficial.github.io/

Listet ein halbes Dutzend ihrer Projekte auf, plus eine lange Liste aktueller Open-Source-Projekte, die sie nutzen und/oder unterstützen.

Codehaus

-

Siehe Fußnotea

a Codehaus selbst ging vor ein paar Jahren offline. Seit 2019 ist die Domain im Besitz der Apache Software Foundation, reagiert aber nicht mehr auf Browseranfragen. Es gibt auch einen Codehaus-Account auf Github, der einige der Projekte enthält, die früher auf Codehaus waren, manche aktiv, manche nicht. In diesem Artikel erfährst du mehr über die Geschichte von Codehaus.

Es gibt auch eine Reihe von Open-Source-Code-Repositories, die nicht kuratiert sind - jeder, der sich dort anmeldet, kann ein Projekt erstellen, unabhängig von der Größe der Community (falls vorhanden). Auf erfolgreichen Seiten wie diesen sammeln sich zu viele Projekte an, um sie auf einer einzigen Seite aufzulisten - du musst sie suchen. Die meisten sind nicht spezifisch für Java. Tabelle 1-6 zeigt einige der Open Source Code Repos.

Tabelle 1-6. Open-Source-Code-Repositories
Name URL Anmerkungen

Sourceforge.net

https://sourceforge.net/

Eine der ältesten

GitHub

http://github.com/

"Social Coding"; wahrscheinlich am meisten genutzt, jetzt im Besitz von Microsoft

Bitbucket

https://bitbucket.org/

Öffentliche und private Repos; kostenlose und kostenpflichtige Pläne

GitLab

https://gitlab.org/

Öffentliche und private Repos; kostenlose und kostenpflichtige Pläne

Maven Zentrale

https://search.maven.org/

Verfügt über ein kompiliertes Jar, ein Source-Jar und ein Javadoc-Jar für jedes Projekt

Ich will diese Repositories nicht schlecht machen - die Sammlung von Demoprogrammen für dieses Buch wird sogar auf GitHub gehostet. Ich will damit nur sagen, dass du wissen musst, wonach du suchst und ein bisschen aufpassen musst, bevor du dich für ein Framework entscheidest. Gibt es eine Community, die sich damit beschäftigt, oder ist es eine Sackgasse?

Ich betreibe eine kleine Java-Website, die vielleicht von Nutzen ist. Sie enthält eine Auflistung von Java-Ressourcen und Material zu diesem Buch.

Für die Java-Enterprise- oder Web-Ebene gibt es zwei wichtige Frameworks, die ebenfalls Dependency Injection bieten: JavaServer Faces (JSF) und CDI und das Spring Framework SpringMVC Paket. JSF und das eingebaute CDI (Contexts and Dependency Injection) bieten DI sowie einige zusätzliche Kontexte, wie z. B. einen sehr nützlichen Web Conversation-Kontext, der Objekte über mehrere Webseiteninteraktionen hinweg hält. Das Spring Framework bietet Dependency Injection und die SpringMVC Web-Tier-Helferklassen. Tabelle 1-7 zeigt einige Web-Tier-Ressourcen. Spring MVC und JSF sind bei weitem nicht die einzigen Web-Frameworks; die Liste in Tabelle 1-7enthält viele andere, die für deine Anwendung vielleicht besser geeignet sind. Du musst dich entscheiden!

Tabelle 1-7. Ressourcen der Webebene
Name URL Anmerkungen

Ians Liste der 100 Java Web Frameworks

http://darwinsys.com/jwf/

JSF

http://www.oracle.com/technetwork/java/javaee/overview/

Java EE Standardtechnologie für Webseiten

Da JSF ein komponentenbasiertes Framework ist, gibt es viele Zusatzkomponenten, die deine JSF-basierte Website viel leistungsfähiger machen (und besser aussehen) als die Standard-JSF-Komponenten. Tabelle 1-8 zeigt einige der JSF-Zusatzbibliotheken.

Tabelle 1-8. JSF Add-on Bibliotheken
Name URL Anmerkungen

BootsFaces

https://bootsfaces.net/

Kombiniert BootStrap mit JSF

ButterFaces

http://butterfaces.org/

Reichhaltige Komponentenbibliothek

ICEfaces

http://icefaces.org/

Reichhaltige Komponentenbibliothek

OpenFaces

http://openfaces.org/

Reichhaltige Komponentenbibliothek

PrimeFaces

http://primefaces.org/

Reichhaltige Komponentenbibliothek

RichFaces

http://richfaces.org/

Reichhaltige Komponenten; nicht mehr gepflegt

Apache DeltaSpike

http://deltaspike.apache.org/

Zahlreiche Code-Add-ons für JSF

JSFUnit

http://www.jboss.org/jsfunit/

JUnit-Tests für JSF

OmniFaces

http://omnifaces.org/

JSF Utilities add-on

Heutzutage gibt es Frameworks und Bibliotheken für fast alles. Wenn meine Listen dich nicht zu dem führen, was du brauchst, hilft dir wahrscheinlich eine Suche im Internet. Versuche, den platten Reifen nicht neu zu erfinden!

Wie bei jeder freien Software solltest du dich über die Auswirkungen der verschiedenen Lizenzierungssysteme informieren. Code, der unter die GPL fällt, überträgt zum Beispiel automatisch die GPL auf jeden Code, der auch nur einen kleinen Teil davon verwendet. Konsultiere einen Anwalt. Je nachdem, wie weit du gehst. Trotz dieser Vorbehalte ist der Quellcode eine unschätzbare Ressource für alle, die mehr über Java lernen wollen.

1 Wenn das Deployment oder der Build einen Schritt wie "Bring Smith dazu, Datei X auf seinem Desktop zu verarbeiten und auf den Server zu kopieren" beinhaltet, verstehst du wahrscheinlich nicht ganz, was mit automatisierten Tests gemeint ist.

2 Jenkins und Hudson begannen als Hudson, das hauptsächlich von Kohsuke Kawaguchi geschrieben wurde, als er für Sun Microsystems arbeitete. Später gab es einen kulturellen Streit, der dazu führte, dass sich Jenkins von Hudson abspaltete und ein neuer Fork des Projekts entstand. Kohsuke arbeitet an der Hälfte, die jetzt als Jenkins bekannt ist. Ich werde nur den Namen Jenkins verwenden, weil das der Name ist, den ich benutze, und weil es zu lange dauert, ständig "Jenkins/Hudson" zu sagen. Aber fast alles hier gilt auch für Hudson.

Get Java Kochbuch, 4. Auflage now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.