Spring Boot 2 - Michael Simons - E-Book

Spring Boot 2 E-Book

Michael Simons

0,0

Beschreibung

Spring Boot hat seit 2014 das Spring-Ökosystem revolutioniert und verdrängt in zunehmendem Maße "klassische" Spring-Anwendungen. Spring Boot ist kein neues Framework, sondern basiert auf Spring und dem Spring-Ökosystem. Es vereinfacht die Verwaltung von Abhängigkeiten und die Konfiguration des Spring- Frameworks. Spring Boot löst dabei Probleme, die einer effektiven und effizienten Produktivsetzung im Weg stehen, und bietet vielfältige Möglichkeiten, testgetrieben zu entwickeln. Spring Boot sollte die erste Wahl sein, Springbasierte Anwendungen zu entwickeln, unabhängig davon, ob es sich um Microservices handelt oder nicht. Dieses Buch bietet eine umfassende Einführung in die von Spring Boot unterstützten Spring-Module und -Technologien: - Webanwendungen - Reaktive Anwendungen - Security - Datenbanktechnologien - Caching - Tests und DokumentationDarüber hinaus stellt es verschiedene Möglichkeiten vor, Spring-Boot-Anwendungen zu deployen, sowohl in klassischen als auch in Cloud- Szenarien. Hinweise auf Best Practices sowie eine Übersicht der zahlreichen Änderungen von Spring Boot 1 auf Version 2 runden das Buch ab.

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern

Seitenzahl: 508

Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:

Android
iOS
Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Michael Simons ist zweifacher Vater, Ehemann, Geek und leidenschaftlicher Fahrradfahrer. Er entwickelt seit über 15 Jahren Software im Java-Umfeld, davon seit sieben Jahren mit Spring. Michael ist Mitglied des NetBeans Dream Team und Gründer der Euregio JUG. Er schreibt in seinem Blog info.michael-simons.eu über Java, Spring und Softwarearchitektur. Michael arbeitet als Senior Consultant bei innoQ Deutschland.

Zu diesem Buch – sowie zu vielen weiteren dpunkt.büchern – können Sie auch das entsprechende E-Book im PDF-Format herunterladen. Werden Sie dazu einfach Mitglied bei dpunkt.plus+:

www.dpunkt.plus

Michael Simons

Spring Boot 2

Moderne Softwareentwicklung mit Spring 5

Michael Simons

Lektorat: René Schönfeldt

Copy-Editing: Annette Schwarz

Satz: Da-TeX

Herstellung: Susanne Bröckelmann

Umschlaggestaltung: Helmut Kraus, www.exclam.de

Druck und Bindung: M.P. Media-Print Informationstechnologie GmbH, 33100 Paderborn

Bibliografische Information der Deutschen Nationalbibliothek

Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.

ISBN:

Print     978-3-86490-525-4

PDF      978-3-96088-388-3

ePub    978-3-96088-389-0

mobi    978-3-96088-390-6

1. Auflage 2018

Copyright © 2018 dpunkt.verlag GmbH

Wieblinger Weg 17

69123 Heidelberg

Die vorliegende Publikation ist urheberrechtlich geschützt. Alle Rechte vorbehalten. Die Verwendung der Texte und Abbildungen, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und daher strafbar. Dies gilt insbesondere für die Vervielfältigung, Übersetzung oder die Verwendung in elektronischen Systemen.

Es wird darauf hingewiesen, dass die im Buch verwendeten Soft- und Hardware-Bezeichnungen sowie Markennamen und Produktbezeichnungen der jeweiligen Firmen im Allgemeinen warenzeichen-, marken- oder patentrechtlichem Schutz unterliegen.

Alle Angaben und Programme in diesem Buch wurden mit größter Sorgfalt kontrolliert. Weder Autor noch Verlag können jedoch für Schäden haftbar gemacht werden, die in Zusammenhang mit der Verwendung dieses Buches stehen.

5 4 3 2 1 0

Inhaltsverzeichnis

Geleitwort

Vorwort

Wege durch das Buch

IEinleitung

1Hallo, Spring Boot

1.1Projektdefinition oder »Project Object Model«

1.2Abhängigkeiten definieren

1.3Hallo, Welt!

1.4Liefern

1.5Fehler erkennen

IISpring Boot

2Projektstruktur

2.1Build-Management-Tools

2.1.1Maven

2.1.2Gradle

2.2Pakete und Klassen strukturieren

2.3Spring Initializr

2.4IDE-Unterstützung

2.4.1Spring Tool Suite

2.4.2NetBeans IDE

2.4.3IntelliJ IDEA

2.4.4Die Qual der Wahl

3Spring-Framework-Grundlagen

3.1Dependency Injection

3.1.1Der Spring-Container

3.1.2Inversion of Control

3.1.3Ausblick

3.2Aspektorientierte Programmierung

3.2.1Einführung

3.2.2Spring und AOP

4Konfiguration

4.1Externe Konfiguration

4.1.1Konfigurationsdateien

4.1.2Zugriff auf Konfiguration

4.2Interne Konfiguration

4.2.1Profile

4.2.2Konfigurationsklassen

4.2.3Automatische Konfiguration

5Die Magie hinter Spring Boot

5.1Grundlagen

5.1.1Namensgebung

5.1.2Factories Loader

5.2Konfiguration, nur unter Bedingung

5.2.1Auf Anwesenheit von Klassen hin testen

5.2.2Auf Anwesenheit von Beans hin testen

5.2.3Die Konfiguration auswerten

5.2.4Weitere Bedingungen nutzen

5.2.5Bedingungen logisch verknüpfen

5.2.6Metadaten bereitstellen

5.2.7Ihren Starter deployen

5.3Fazit

6Logging

6.1Gemeinsame Konfiguration

6.2Erweiterte Konfiguration

6.2.1Logback

6.2.2Log4j 2

6.2.3Java Util Logging (JUL)

6.3Zugriffslogs

6.3.1Tomcat

6.3.2Undertow

6.4Remote-Konfiguration

6.4.1HTTP-Endpunkt

6.4.2JMX

6.5Remote-Logging

7Beschleunigter Entwicklungsprozess mit den devtools

7.1Automatische Neustarts

7.2Automatisches Neuladen von Inhalten

IIIDas Spring-Ökosystem

8Webanwendungen

8.1Spring Web MVC

8.1.1Die Grundlagen verstehen

8.1.2Funktionen kennenlernen

8.1.3Spring Web MVC automatisch konfigurieren

8.1.4Eingebetteten Webcontainer nutzen

8.1.5Statische Inhalte ausliefern

8.1.6JSON-Serialisierung und -Deserialisierung steuern

8.1.7Hochgeladene Dateien verarbeiten

8.1.8Zusätzliche Scopes beherrschen

8.2Template Engines

8.2.1Thymeleaf-Templates nutzen

8.2.2Groovy-Templates verwenden

8.2.3Ausblick

8.3Über WebSockets kommunizieren

8.4JAX-RS nutzen

9Security

9.1Minimale Autokonfiguration

9.2Die Grundlagen verstehen

9.2.1Authentifizierung

9.2.2Autorisierung

9.2.3Spring Security und Spring Web MVC

9.2.4Methodensicherheit

9.2.5Sicherheit auf HTTP-Header-Ebene

9.3Anwendungsbeispiele

9.3.1Die Standardkonfiguration nutzen

9.3.2Methodensicherheit aktivieren

9.3.3Gesicherte URLs und Methoden testen

9.3.4Eine eigene Benutzerverwaltung anbinden

9.3.5Passwörter sicher speichern

9.3.6HTTP-Sicherheit anpassen

9.3.7Form-Login und Webintegration nutzen

9.3.8Spring Data Repositorys absichern

9.3.9OAuth 2 nutzen

9.4Ausblick

10Persistenz

10.1Spring Data

10.2Relationale Datenbanken

10.2.1Datasources

10.2.2Datenbankinitialisierung und -migration

10.2.3Transaktionen

10.2.4Datenbankzugriff

10.3NoSQL-Technologien

10.3.1Spring Data MongoDB

10.3.2Weitere Spring-Data-Module

10.4Fazit

11Caching

11.1Aspekte eines Cache

11.2Deklaratives Caching

11.2.1Caching aktivieren

11.3Caching mit Spring Boot

11.4Beispiele und Sonderfälle

11.4.1Cachen von 3rd-Party-Abhängigkeiten

11.4.2Synchrones Caching

11.4.3Caching von Web-Controller-Methoden

12Messaging

12.1Über JMS kommunzieren

12.1.1JMS-Grundlagen kennen

12.1.2Einen JMS-Broker konfigurieren

12.1.3JmsTemplate und Listener verstehen

12.2AMQP nutzen

12.3Redis als Messaging-System verwenden

12.4Apache Kafka anbinden

12.5Ausblick: Spring Cloud Stream

13E-Mail

13.1Mit Spring Boot E-Mails verschicken

14Reaktive Programmierung

14.1Reactive Streams und Project Reactor

14.2WebFlux-Modul

14.2.1Klassische Annotationen verwenden

14.2.2Datenquellen

14.2.3Funktionales Programmiermodell

14.2.4Reaktive Methoden testen

14.2.5Reaktive Views benutzen

14.2.6Spring Security mit WebFlux verwenden

14.3Ausblick: Spring Cloud Function

15Tests und Dokumentation

15.1Spring-Boot-Starter-Test

15.2Unit-Tests

15.3Integrationstests

15.3.1Grundlage: Das Frameworkmodul »spring-test«

15.3.2Spring-Boot-Anwendungen testen

15.3.3Automatische Mock-Objekte

15.3.4Explizite Tests technischer Schichten

15.3.5Erweiterte Testkonfiguration

15.3.6Hilfsmittel

15.3.7Fazit

16Dynamische JVM-Sprachen und polyglotte Programmierung

16.1Groovy

16.1.1Das Spring-Boot-Commandline-Interface

16.2Kotlin

IVProduktivsetzung

17Actuator

17.1Bereitstellen des Spring Boot Actuator

17.2Übersicht

17.2.1Security

17.2.2Konfiguration der HTTP-Endpunkte

17.2.3Konfiguration der JMX-Endpunkte

17.3Allgemeine Informationen

17.4Health-Status

17.5Metriken mit Micrometer aufzeichnen

17.5.1Verfügbare Metriken

17.5.2Eigene Metriken erfassen

17.5.3Den Metrics-Endpunkt benutzen

17.5.4Metriken exportieren und auswerten

17.6Eigene Endpunkte

18Verteilung

18.1Artefakte

18.2Klassische Installation

18.2.1Als Unix/Linux Service

18.2.2Als Windows-Dienst

18.3Servlet-Container

18.3.1War-Deployment

18.3.2Klassische Spring-Anwendungen migrieren

18.4Verteilung in die Cloud

18.4.1Cloud Foundry

18.4.2Andere Plattformen und Anbieter

VMicroservices mit Spring Cloud: ein Einstieg

19Einführung und Übersicht

19.1Was ist eine Microservice-Architektur?

19.2Was gehört alles zu Spring Cloud?

19.2.1Spring Cloud in Ihr Projekt einbinden

19.3Kontexthierarchien

19.3.1Der Bootstrap-Kontext

19.4Der Wochenplaner: ein verteiltes Beispiel

20Konfiguration in verteilter Umgebung

20.1Den Konfigurationsserver starten

20.2Clients anbinden

21Service Discovery mit Netflix Eureka

21.1Einen Eureka-Server betreiben

21.2Services am Eureka-Server anmelden

21.3Services aus Eureka benutzen

22Circuit Breaker

22.1Spring Cloud Hystrix nutzen

23Weitere Aufgaben lösen

ALebenszyklus von Spring-Anwendungen und Beans

A.1Auf Ereignisse im Lebenszyklus einer Anwendung reagieren

A.2Den Lebenszyklus von Beans verstehen

BErweiterte Konfiguration von Datasources

CUpgrade von Spring Boot 1 auf 2

C.1Spring 5

C.1.1Neue Voraussetzungen: Spring 5 und Java 8

C.1.2Neue Funktionen und Verbesserungen

C.2Änderungen in Spring Boot 2

Glossar

Abkürzungen

Index

Geleitwort

15 Jahre Spring

Die Wurzeln von Spring liegen in einer Sammlung von Framework-Ideen im Buch »J2EE Design and Development« aus dem Jahre 2002 und deren Konkretisierung im Nachfolgebuch »J2EE without EJB« aus dem Jahre 2004. Bücher spielten immer schon eine wichtige Rolle für Spring, sowohl die Titel von meinem Mitgründer Rod Johnson und mir als auch jene aus der Community.

In den 15 Jahren seiner Geschichte entwickelte sich das Spring Framework konsequent weiter, wobei es im Kern des Frameworks nie zu einem radikalen Bruch kam, sondern immer zu einer Evolution im Rahmen des breiteren Java-Ökosystems. Natürlich musste sich das Framework einige Male im sprichwörtlichen Sinne neu erfinden, baute dabei aber jedes Mal wieder auf seinen Kernideen auf und erlaubte das schrittweise Upgrade von Bestandsanwendungen.

Einer der größten Meilensteine in diesen 15 Jahren war sicherlich die Einführung von Spring Boot im Jahre 2014. Ursprünglich gedacht als bequeme Konfigurationsvariante, entwickelte sich Boot schnell zum Standard-Einstiegspunkt ins Spring-Ökosystem und zum beliebtesten Framework für Microservice-Architekturen im Java-Umfeld. Dabei bietet Spring Boot nicht nur einen einfachen Einstieg für Entwickler, sondern auch viele Laufzeit-Features für den Betrieb.

Nach den Feature-Releases 1.1 bis 1.5 bringt Spring Boot 2.0 nun die erste große Überarbeitung, aufbauend auf Spring Framework 5.0. Die Schwerpunktthemen sind dabei breit gefächert: von reaktiver Programmierung bis hin zu Kotlin als neuer Programmiersprache auf der JVM, und nicht zu vergessen natürlich die neuen JDK-Releases der Generation 9+, die uns ab nun zwei Mal im Jahr bevorstehen. Spring Framework 5 und Spring Boot 2 stehen hierfür bereit.

Erfreulicherweise setzt sich auch die Tradition der begleitenden Bücher fort: Michael Simons liefert mit dem vorliegenden Titel nicht nur perfektes Timing, sondern vor allem einen umfassenden Einblick in viele aktuelle Bereiche des Spring-Ökosystems. Dieses Buch deckt alle Facetten der Entwicklung mit Spring Boot ab und bietet einen praktischen Leitfaden für moderne Java-Webanwendungen, der bereits jetzt auf die Herausforderungen der kommenden Jahre ausgerichtet ist.

Viel Spaß bei der Lektüre,

Jürgen HöllerMitbegründer und Entwicklungsleiter des Spring Framework

Vorwort

Das Spring-Framework

Das Spring-Framework wurde 2002 erstmals als Idee vorgestellt und ein Jahr später unter dem Namen Spring-Framework als quelloffenes Projekt veröffentlicht. Das Ziel – damals wie heute – ist, die Entwicklung mit Java zu vereinfachen und gute Programmierpraktiken zu fördern.

Infrastruktur auf Anwendungsebene ist eines der Schlüsselelemente von Spring. Springs Fokus liegt ganz klar auf Bereitstellung und Konfiguration nichtfunktionaler Anforderungen, so dass Entwickler von Anwendungen sich auf ihre eigentliche Aufgabe, Implementierung der Geschäftslogik, konzentrieren können.

Kernfunktionen von Spring sind dabei:

Dependency Injection

MVC-basierte Webanwendungen und RESTful Webservices

Grundlagen für JDBC, JPA und vieles mehr

aspektorientierte Programmierung und deklarative Behandlung von Transaktionen

Der Umfang an Funktionalität ist seit 2003 kontinuierlich gewachsen, die Möglichkeiten, eine Spring-basierte Anwendung zu konfigurieren und in Betrieb zu nehmen, ebenso.

Spring Boot ist in diesem Kontext kein neues Framework, sondern eine Sicht auf die Spring-Platform, die es ermöglicht, eigenständige und produktionsreife Anwendungen auf Basis des beschriebenen Spring-Frameworks zu bauen, die unter anderem folgende Eigenschaften haben:

eigenständige Anwendungen, die keine externen Laufzeitabhängigkeiten mehr haben

eingebettete Container (zum Beispiel Tomcat, Jetty oder Undertow), so dass keine War-Dateien verteilt werden müssen

automatische Konfiguration soweit möglich

Bereitstellung von nicht funktionalen Eigenschaften, die zur Produktion in der Regel benötigt werden: Metriken, Health Checks und externe Konfiguration

keinerlei Generierung von Code oder Konfiguration

Warum Spring Boot?

Spring Boot basiert vollständig auf dem Spring-Framework. Es wurde mit dem Ziel erschaffen, die Entwicklung eigenständig lauffähiger Anwendungen mit dem Spring-Framework drastisch zu erleichtern. Convention over configuration sowie wenige, bekannte Annotationen reichen aus, um Artefakte zu erzeugen, die alle benötigten Abhängigkeiten mitbringen und extern konfigurierbar sind. Die Schwelle, mehr als eines dieser Artefakte zu erzeugen und zu verteilen, ist deutlich geringer und Grundlage erfolgreicher Verteilung von Microservices.

Schneller Start

Mit sogenannten »Startern« ist es möglich, die Konfiguration des Builds erheblich zu vereinfachen. Durch Deklaration einer einzigen Abhängigkeit wird zum Beispiel die Unterstützung einer Template-Sprache bereitgestellt, inklusive benötigter Abhängigkeiten und Konfiguration.

Testdriven

Spring Boot bietet herausragende Möglichkeiten, die technischen Schichten einer Anwendung, zum Beispiel Persistenz- und Webschicht, getrennt voneinander zu testen und die Ergebnisse dieser Tests anschließend zu Dokumentationszwecken zu nutzen. Ein nicht unerheblicher Gewinn, um sauberen Code zu schreiben.

Spring Boot liebt Microservices.

Darüber hinaus hat sich um Spring Boot, insbesondere durch die Firma Netflix, ein weiteres Ökosystem an Komponenten aufgetan, das insbesondere auf die Entwicklung verteilter, widerstandsfähiger (»resilient«) Microservices zielt. Machen Sie aber bitte nicht den Fehler und betrachten Spring Boot als »Microservice«-Framework. Sie können mit Spring Boot Teile von Anwendungssystemen auf Basis einer Microservice-Architektur bauen, aber Spring Boot ist deutlich mehr als ein »Microservice«-Framework.

Spring Boot und Cloud-native Java

Im Umfeld von Spring Boot hören Sie oft die Begriffe Cloud-native und 12-Factor-App. Die Firma Pivotal erklärt den Begriff Cloud-native-Anwendungen als Anwendungen, die speziell mit dem Cloud-Modell im Hintergrund entworfen wurden und von kleinen Teams mit Fokus auf einzelnen Features entwickelt, deployt und betrieben werden. Skalierbare Infrastruktur, flexible Zielplattformen, Entwickler, die sich auf Features anstelle von Boilerplate-Code konzentrieren können, und ein Betrieb, der sich am Geschäftsbedarf orientiert, sind heute noch Wettbewerbsvorteile, in naher Zukunft wohl eher Standard. Die folgenden Themen beschreiben Kernaspekte einer Cloud-native-Anwendung:

Entwicklung und Betrieb arbeiten Hand in Hand zusammen, so dass Builds, Tests und Releases oft und zuverlässig durchgeführt werden (»DevOps«),

Continuous Delivery, um einzelne Aspekte freigeben und veröffentlichen zu können, wenn sie fertig sind,

Microservices als architektonischer Ansatz, um Anwendungen als Sammlung kleiner Dienste zu strukturieren, die unabhängig voneinander verteilt, aktualisiert und skaliert werden können, und

Container als Laufzeitumgebung, die ähnlich schnell wie ein Microservice gestartet, skaliert und gestoppt werden können

Die 12-Factor-App als Methode beschreibt Anwendungen, mit denen die Vorteile einer Cloud-native-Umgebung ausgenutzt werden können, und wurde als Manifest unter 12factor.net von Entwicklern der Heroku-Plattform (https://www.heroku.com) in mehreren Sprachen veröffentlicht. Ihr Ziel war es, ideale Praktiken für die Entwicklung von Anwendungen zu schaffen, die wiederkehrende Probleme im Hinblick auf Konfiguration, Portierbarkeit, Verteilung und Skalierung von verteilten Anwendungen verhindern.

Viele Konzepte sind in die Gestaltung von Spring Boot eingeflossen und helfen dabei, Spring Boot zu einer idealen Plattform von Cloud-native-Anwendungen zu machen. Nach der Lektüre des Kapitels können Sie einige der Designentscheidungen Spring Boots besser nachvollziehen. Die Kenntnis der Idee der 12-Factor-Anwendung hilft Ihnen, einige Defaults von Spring Boot besser zu verstehen und sie – falls notwendig – bewusst anders zu konfigurieren.

Einige der Faktoren, die Sie ziemlich klar in Spring Boot wiederfinden, sind:

Explizite und vollständige Deklaration von Abhängigkeiten. Spring Boot macht dies zu großen Teilen über das Konzept sogenannter »Starter«, denen Sie im Folgenden sehr häufig begegnen werden.

Die externe Konfiguration einer Anwendung erfolgt nicht über Code, sondern der »reinen Lehre« nach nur über Umgebungsvariablen. Spring Boot geht einen Schritt weiter: Spring-Boot-Anwendungen können sehr leicht über Umgebungsvariablen konfiguriert werden, aber ähnlich effektiv auch durch Profile. Profile bündeln verschiedene, zusammengehörende Einstellungen für ein Ziel-Deployment (zum Beispiel

staging

,

test

,

prod

und andere). Die konkreten Parameter der Profile sind dabei Teil des Artefakts, die Profile selber werden üblicherweise über die Umgebung aktiviert. Wichtig ist jedoch, dass es niemals notwendig sein sollte, eine Anwendung für ein einzelnes Ziel auf spezielle Art und Weise zu bauen. Die durch Spring Boot geschaffenen Möglichkeiten externer Konfiguration, die in

Kapitel 4

besprochen werden, sind immens wichtig, um Anwendungen zu erstellen, die genau diesen Anspruch erfüllen. Gleiches gilt für intelligente »Magie«, die es in vielen Fällen erlaubt, komplett auf explizite Konfiguration zu verzichten und nur anhand der Umgebung zu entscheiden, welche Konfiguration sinnvoll ist oder nicht (

Kapitel 5

).

Unterstützende Dienste wie Datenbanken und dergleichen sollen als »angehängte« Ressourcen betrachtet werden: Der Code einer 12-Factor-Anwendung macht keinen Unterschied zwischen lokalen Diensten oder den Diensten Dritter. Diese Aspekte werden Sie in

Kapitel 18

wiederfinden.

Zum Thema »Logging« wird folgende Aussage gemacht: Eine 12-Factor-Anwendung betrachtet Logs als Strom von Ereignissen. Das Ziel dieser Ereignisse ist irrelevant für eine 12-Factor-Anwendung. Sie schreibt ihre Logging-Ereignisse in der Regel nach

stdout

. In

Kapitel 6 »Logging«

wird ganz klar dieser Einfluss auf Spring Boot deutlich: Es gibt sehr einfache und schöne Möglichkeiten, das Format und die Detailtiefe (Level) der einzelnen Logs zu konfigurieren, das Ziel ist aber in der Regel die Standardausgabe.

Eine 12-Factor-App ist noch lange keine »perfekte« Anwendung, und die 12 Faktoren machen erst recht keine Aussage über ein Anwendungssystem, sind aber ein wesentlicher Bestandteil von Cloud-native-Anwendungen. Sie helfen, sowohl die Anwendung selber als auch die Entwicklung ohne wesentliche Änderungen im Tooling und der Architektur zu skalieren, maximale Portierbarkeit zwischen verschiedenen Ausführungsumgebungen zu erreichen und die Kluft zwischen Entwicklung und Produktion zu minimieren.

Warum dieses Buch?

Die Referenzdokumentation von Spring Boot ist ebenso wie die des Spring-Frameworks selber ausgesprochen gut, und es gibt eine Vielzahl von Einführungen für unterschiedliche Themen. Warum also noch ein Buch?

Dieses Buch soll interessierte Entwickler aus dem Java-EE-Bereich ebenso wie Spring-Entwickler ansprechen und ihnen ein »Rezept« an die Hand geben, immer wiederkehrende Aufgaben aus dem fachlichen Alltag elegant und ohne Ablenkung mit Spring Boot zu nutzen.

Spring Boot bringt eine Menge automatischer Konfigurationen für fast alle Aspekte des Spring-Frameworks. Das Buch erklärt diese Magie und hilft dabei, sie für die eigenen Zwecke zu nutzen.

Warum legt das Spring-Boot-Team so viel Wert auf externe Konfiguration? Welchen Vorteil bietet ein Fat Jar? Wie funktionieren die Spring-Boot-Starter? Auch diese Fragen werden beantwortet.

Für wen ist dieses Buch?

Sie sollten grundlegende Kenntnisse der objektorientierten Programmierung besitzen und die Programmiersprache Java einschließlich der Sprachfeatures von Version 8 sowie die funktionalen Erweiterungen verstehen, um diesem Buch folgen zu können.

Spring Boot kann genutzt werden, ohne alle Module des Spring-Frameworks im Detail zu kennen oder vollständig zu verstehen. Ich habe versucht, für dieses Buch einen ähnlichen Kompromiss zu finden: Auch ohne Detailkenntnisse des Spring-Frameworks kennen Sie nach der Lektüre die Philosophie hinter Spring Boot und können damit Anwendungen erstellen. An vielen Stellen bin ich zusätzlich auf grundlegende Konzepte und Ideen des Spring-Frameworks eingegangen, insbesondere im Hinblick auf den Spring-Container, das Web-MVC-Framework und die Datenmodule.

Erfahrene Spring-Entwickler, die bisher noch nicht in Kontakt mit einer Spring-Boot-Anwendung gekommen sind, die unter modernen Gesichtspunkten entworfen wurde, werden überrascht sein, wie leichtfüßig die Entwicklung einer neuen Anwendung mittlerweile vonstatten geht.

Falls Sie bereits eine Vorstellung von Spring Boot und der grundlegenden Konfiguration haben, können Sie mit Kapitel 5 starten. Dort erfahren Sie, wie die automatische Konfiguration funktioniert. In Teil III erfahren Sie, wie Spring Boot bekannte Spring-Funktionen zur Verfügung stellt und wie diese Ihren Zwecken angepasst werden können.

Sie sollten die im Abschnitt »Werkzeuge« auf Seite 10 genannten Tools zur Hand haben, den Umgang mit Maven kennen und die IDE Ihrer Wahl beherrschen.

Autor

Michael Simons ist zweifacher Vater, Ehemann, Geek und leidenschaftlicher Fahrradfahrer. Er entwickelt seit über 15 Jahren Software im Java-Umfeld, seit sieben Jahren mit Spring. Michael ist Mitglied des NetBeans Dream Team und Gründer der Euregio JUG. Er schreibt in seinem Blog info.michael-simons.eu über Java, Spring und Softwarearchitektur. Michael arbeitet als Senior Consultant bei innoQ Deutschland.

Danksagungen

Mein Dank geht sowohl an alle engagierten Probeleser als auch an alle Menschen, die mich moralisch unterstützt haben. Es war mir eine Ehre, mit euch an diesem Buch zu arbeiten:

Andy Wilkinson (@ankinson), Christina Simons (@tinasimons), Eberhard Wolff (@ewolff), Franz van Betteraey (@FrVaBe), Friedel Herten, Dr. Gernot Starke (@gernotstarke), Jörn Hameister (@hameiste), Jürgen Höller (@springjuergen), Lukas Eder (@lukaseder), Mark Paluch (@mp911de), Martin Steinberg (@SbgMartin), Niko Köbler (@dasniko), Rainer Barluschke, Ralf D. Müller (@RalfDMueller), René Schönfeldt, Silke Böhler, Stéphane Nicoll (@snicoll), Tim Riemer (@zordan_f), Yann Cébron (@yanncebron).

Weiterhin konnte ich in dieses Buch die Antworten auf einige Fragen einfließen lassen, die ich auf Twitter, im Slack oder auf Stack Overflow beantwortet habe.

Insbesondere gebührt der ENERKO INFORMATIK in Aachen mein Dank für fantastische 15 Jahre, in denen ich nicht nur interessante Aufgaben hatte, sondern jederzeit Unterstützung erfahren habe, sowohl für alle erdenklichen Projekte als auch in privater Hinsicht.

Dieses Buch jedoch wäre – wie viele andere Dinge in meinem Leben – ohne den Rückhalt meiner Frau Christina unmöglich.

Wege durch das Buch

Sollten Sie zu den Menschen gehören, die jedes Buch von der ersten bis zur letzten Seite lesen, dann betrachten Sie bitte die folgenden Punkte als Hinweis, was ich mir bei der Einteilung des Buches gedacht habe. Ansonsten können sie Ihnen als kleiner Wegweiser durch dieses Buch und das Spring-Ökosystem dienen.

Einsteiger beginnen mit

Teil I

. Dieser Teil stellt testgetrieben die Entwicklung eines einfachen HTTP-Endpunktes mit Spring Boot vor und veranschaulicht wesentliche Konzepte einer Spring-Boot-Anwendung. Dieser Teil ist gleichermaßen geeignet für Menschen, die nur wenig Erfahrung mit Build-Management-Tools im Java-Umfeld haben oder noch niemals Spring-Code genutzt haben.

In

Teil II

werden die wesentlichen Säulen von Spring Boot und auch notwendige Spring-Grundlagen thematisiert. Er kann damit sowohl von Entwicklern gelesen werden, die Spring bereits kennen und nun wissen möchten, was Spring Boot für sie tun kann, als auch von Entwicklern, die aus einem anderen Bereich, wie zum Beispiel Java EE, kommen. Erfahrene Spring-Boot-Entwickler springen direkt in das

Kapitel 5

. Dort erfahren sie, wie die »Magie« von Spring Boot funktioniert.

Teil III

ist dem Spring-Ökosystem gewidmet. Laut eigener Aussage soll Spring Boot das Spring-Framework, dessen Module und unterstützte Technologien Dritter wann immer möglich automatisch konfigurieren.

Teil III

greift einige der wichtigsten Module heraus und zeigt Spring-Boots Unterstützung für sie. Entwickler, die sich bereits mit Spring Boot auskennen und wissen, wie Funktionen intern und extern konfiguriert werden, erfahren hier mehr über die Entwicklung von Webanwendungen, Datenbankanbindung, Springs reaktive Story und vieles mehr. Zum Spring-Ökosystem gehört auch die Unterstützung unterschiedlicher JVM-Sprachen und einige Tools zur Benutzung auf der Kommandozeile, die das Leben mit Spring Boot vereinfachen. Auch das erfahren Sie in

Teil III

.

Ist Ihre Spring-Boot-Anwendung bereits fertig und soll in Produktion gebracht werden, können Sie direkt in

Teil IV

springen. Haben Sie daran gedacht, Health-Informationen und Metriken bereitzustellen? Wenn nicht, erfahren Sie in

Teil IV

unter anderem, was ein Actuator ist und wie Spring Boot Ihnen mit nicht funktionalen Aspekten einer Anwendung unter die Arme greift. Ebenso erfahren Sie hier, welche Möglichkeiten Sie haben, Ihre Anwendung auszuführen. Sollten Sie klassische Spring-Anwendungen migrieren wollen, so erfahren Sie einige Möglichkeiten in

Unterabschnitt 18.3.2

.

Teil V

gibt schlussendlich einen High-Level-Überblick über den Spring-Cloud-Stack und eine mögliche Microservice-Architektur.

Werkzeuge

Auf Ihrem Weg durch das Buch benötigen Sie mindestens folgende Werkzeuge:

einen guten Texteditor oder eine Java IDE

eine aktuelle Version des JDK 8

das Build-Werkzeug

Maven

in Version 3.5 (für einige wenige Beispiele wird

Gradle

eingesetzt)

Git

, um die Beispiele von GitHub zu klonen

Die drei großen Java-IDEs – Eclipse, NetBeans und IntelliJ IDEA – sind gleichermaßen für die Entwicklung von Spring-Boot-Anwendungen geeignet. Die Beispielprojekte können in allen genannten IDEs geöffnet und bearbeitet werden. Die Unterstützung frameworkspezifischer Funktionen, zum Beispiel die automatische Vervollständigung von Konfigurationseigenschaften, der Support des Spring Boot Initializer start.spring.io und anderer Komfortfunktionen ist teilweise abhängig von der jeweiligen Edition. Folgende Varianten unterstützen die Entwicklung mit Spring Boot sehr gut:

Spring Tool Suite™

, eine auf Eclipse basierende IDE, erweitert und angepasst speziell zur Entwicklung von Spring-Anwendungen

NetBeans IDE

, die freie und quelltextoffene, offizielle IDE für eine aktuelle Version des JDK, zusammen mit dem

NB-SpringBoot-Plugin

JetBrains

IntelliJ IDEA

(spezielle Features für Spring- und Spring-Boot-Projekte stehen allerdings teilweise nur in der kostenpflichtigen

Ultimate

-Ausgabe zur Verfügung)

Alle genannten IDEs bringen sowohl integrierte Unterstützung für das Versionsverwaltungswerkzeug git als auch die Build-Tools maven und gradle mit.

Die Beispiele sind in der Regel Maven-Projekte, die den Maven Wrapper beinhalten. Der Maven Wrapper ermöglicht es, Projekte ohne konkrete Maven-Installation sowohl unter einem unixartigen Betriebssystem als auch unter Windows zu bauen: ./mvnw clean install beziehungsweise ./mvnw.cmd clean install. Maven ist ein sehr mächtiges Build-Werkzeug, das in der Vergangenheit mehrfach Kritik für sein komplexes Objektmodell hat einstecken müssen. Sie sollten sich davon allerdings nicht abschrecken lassen: Mit Bedacht eingesetzt, erledigt es die Aufgaben »Dependency Management«, »Bauen von Anwendungen« und »Verteilen von Anwendungen« gut und zum Großteil auch leichtfüßig und fehlerfrei.

Docker

Einige Beispiele dieses Buches setzen Dienste wie Datenbanken, Caches oder Ähnliches voraus. Natürlich kann man die Beispiele nur lesen, es macht aber mehr Spaß, sie auszuprobieren. Docker ist eine Plattform, um Software in sogenannten Containern laufen zu lassen. Viele Produkte, wie MongoDB oder Redis, gibt es in sogenannten Images, die sich nach kurzem Download in einem Container starten lassen.

In den Maven Buildfiles der Beispiele dieses Buches wurden falls nötig diese Images deklariert und zusammen mit der jeweiligen Anwendung so konfiguriert, dass ein ./mvnw docker:run im jeweiligen Projekt ausreicht, um alle externen Dienste passend zum Beispiel zu starten.

Einzige Voraussetzung: Passend für die Plattform der Leser muss Docker installiert und konfiguriert sein. Docker steht unter www.docker.com/products/overview sowohl für Linux, Windows als auch macOS zum kostenfreien Download bereit.

Was ist mit Java 9?

Zum Zeitpunkt der Entstehung dieses Buches und auch von Spring 5 und Spring Boot 2 war Java 9 noch nicht final veröffentlicht. Java 9, beziehungsweise ab März 2018 Java 10, bringt einige tiefgreifende Änderungen mit sich. Es ist die erste modularisierbare Java-Version und schränkt im Zuge dessen den Zugriff auf viele Java-interne Klassen ein. Module ermöglichen eine hohe Kapselung von Code und gehen viel weiter als Accessmodifier von Klassen. Die finalen Versionen von Spring 5 und Spring Boot 2 sind gegen JDK 9 gebaut und getestet. Generell wurde Spring 5 defensiv weiterentwickelt: Aufrufe von deprecated JDK-Klassen wurden vermieden, JDK-Klassen nur beschränkt über Reflection genutzt. Sie werden also grundsätzlich Ihre Spring-Boot-2-Anwendung auf Basis des JDK 9 entwickeln können. Bedenken Sie aber bitte, dass für eine vollständige Kompatibilität einer Anwendung mit Java 9 auch alle Abhängigkeiten Dritter kompatibel sein müssen.

Konventionen

Das vorliegende Buch versucht – genau wie Spring Boot –, Überraschungen zu vermeiden, und befolgt darum einige Konventionen. Alle Beispiele dieses Projektes stehen auf GitHub unter https://github.com/springbootbuch zur Verfügung und können unter der Apache-Lizenz, Version 2.0 genutzt werden.

Innerhalb des vorliegenden Buches werden in den Listings Import-Statements in der Regel weggelassen, sofern die Beispiele auch ohne diese verständlich sind.

Java-8-Features

Die Beispiele machen in der Regel intensiv Gebrauch von Java-8-Features. Dazu gehören nicht nur die Java-8-Stream-API, sondern auch Default-Methoden auf Interfaces, neue Datentypen und insbesondere die Erweiterungen der Reflection-API im Hinblick auf die Ermittlung der Namen von Konstruktor- und Methodenparameter. Die Projekte werden mit dem Javac-8-Flag -parameters übersetzt. Damit stehen die im Code verwendeten Namen für Parameter von Konstruktoren und Methoden über Reflection zur Verfügung. Sie können dadurch von Spring verwendet werden, zum Beispiel innerhalb von Ausdrücken in Form der Spring Expression Language (SpEL). Damit können Sie unter anderem Caching und Methodensicherheit steuern. Spring-Data-Repositorys sind mit den Namen der Parameter in der Lage, Platzhalter in Abfragen zu füllen. Maven-Projekte, die nach den im Buch erklärten Prinzipien erstellt werden, werden automatisch mit diesen Einstellungen kompiliert.

Die Beispiele sind in der Regel so entworfen, dass sie leicht verständlich und leicht zu ändern sind. Sie legen den Fokus auf das behandelte Thema. Komplexe, aufeinander aufbauende Beispiele oder gar ein Beispiel, das alle möglichen Aspekte in einem vereint, sind gerade für Neulinge schwierig nachzuvollziehen und lenken mit aufwendigeren Konfigurationen vom Wesentlichen ab. Spielen Sie ruhig ein wenig mit den Beispielen herum. Beachten Sie, dass Spring Boot zwar ein »opinionated« Framework ist, das heißt, eine starke Meinung zu Dingen hat, aber dennoch schnell aus dem Weg geht: Erkennt es, dass Sie selber Aspekte des Frameworks oder eines Starters konfigurieren oder ersetzen (zum Beispiel eine Datenbankverbindung, Security oder Teile des Web-MVC-Frameworks), wird die automatische Konfiguration abgeschaltet. Die Beispiele haben in der Regel einige Unit-Tests, die das gewünschte Verhalten sicherstellen: Im Zweifelsfall schlagen diese Tests dann fehl.

Welche Versionen von Spring Boot und Abhängigkeiten wurden genutzt?

Alle im Buch gezeigten Beispiele wurden mit Milestone und Release-Candidate-Versionen von Spring Boot 2 entwickelt und schließlich mit der finalen Version getestet. Einige Beispiele nutzen explizit neue Funktionen von Spring Boot 2 und werden nicht mit älteren Versionen funktionieren. Alle weiteren Abhängigkeiten werden in den Versionen genutzt, die die Spring Boot Bill Of Materials (BOM, siehe Abschnitt 1.1) vorgibt. Solange Sie also in Ihren eigenen Beispielen explizit andere Versionen für Abhängigkeiten angeben, sollten die Beispiele auch für Ihre Projekte funktionieren.

Die Spring-Boot-Referenz unter https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/reference ist gut zu lesen und zusammen mit der tiefergehenden Spring-Framework-Referenz unter https://docs.spring.io/spring/docs/5.0.4.RELEASE/spring-framework-reference wichtig für eine erfolgreiche Arbeit mit Spring Boot.

Teil I

Einleitung

1Hallo, Spring Boot

Für den Einstieg in die Entwicklung mit Spring Boot eignet sich wie in vielen anderen Fällen auch eine einfache Hallo, Welt!-Anwendung. Diese Anwendung wird ausreichen, etliche Schlüsselfeatures von Spring Boot zu erklären. Das Ziel der einfachen Anwendung ist, einen Endpunkt zu entwickeln, der über HTTP veröffentlicht wird und per GET aufgerufen werden kann. Dieser Endpunkt soll Hello, ${name} zurückgeben, wobei name einem übergebenen Parameter entspricht.

1.1Projektdefinition oder »Project Object Model«

Quelltext

helloworld steht auf GitHub zur Verfügung: https://github.com/springbootbuch/helloworld. Wie alle Beispielprojekte in diesem Buch stellt der Inhalt des Repositorys den »Endzustand« des Projektes nach dem entsprechenden Kapitel dar, der Text führt Sie also quasi durch die Entstehung des Projektes.

Viele der in diesem Buch genutzten Beispiele beinhalten unterschiedliche Profile (siehe Unterabschnitt 4.2.1). Unterschiedliche Profile ermöglichen es, Ihnen mehrere Alternativen zur Lösung einer Aufgabe nebeneinander in einem Projekt vorzustellen und durch Wahl des entsprechenden Profils beim Start einer Anwendung auszuführen. In »echten« Projekten sollten Sie einige der Kombinationen sicherlich vermeiden und sich für eine der Alternativen entscheiden.

Wie im Abschnitt »Werkzeuge« auf Seite 10 erläutert, werden Java und Maven vorausgesetzt. Jetzt ist der richtige Zeitpunkt gekommen, zu prüfen, ob beide verfügbar sind:

java -version

mvn -v

Listing 1–1Java- und Maven-Installation prüfen

Beide Befehle sollten Informationen über Java und Maven ausgeben. Spring Boot 2.0 setzt mindestens Java 8 voraus, und Maven sollte in der Version 3+ genutzt werden.

Maven-Projekte werden über das sogenannte POM, das »Project Object Model«, in der Datei pom.xml definiert:

<?xml version="1.0" encoding="UTF-8"?>

<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>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.0.0.RELEASE</version>

</parent>

<groupId>de.springbootbuch</groupId>

<artifactId>helloworld</artifactId>

<version>0.0.1-SNAPSHOT</version>

</project>

Listing 1–2pom.xml

Dieses POM resultiert bereits in einem funktionierenden Build, das entstehende JAR ist allerdings leer. Bekannt sind an dieser Stelle nur die »Koordinaten« des Projektes (geschrieben als "groupId:artifactId" lauten sie "de.springbootbuch:helloworld") und ein »Parent«-POM:

Das POM des Beispiels folgt der offiziellen Empfehlung, vom POM spring-boot-starter-parent zu erben. Dieses Maven-Projekt hat den Typ pom und beschreibt damit eine Projektstruktur, von der andere Projekte erben können.

Vererbungsstrukturen in Maven-Projekten erlauben viele nützliche Dinge, von denen die Verwaltung von Abhängigkeiten, das sogenannte Dependency Management1, sicherlich am nützlichsten ist. Jedes Spring Boot Release stellt eine Menge kuratierter Abhängigkeiten zur Verfügung. Die Abhängigkeiten beinhalten sowohl alle Spring-Module, die offiziell mit Spring Boot nutzbar sind, als auch eine Menge an Bibliotheken von Drittherstellern. Die Abhängigkeiten auf dieser »Bill of Materials« (BOM) sind in dieser Konstellation getestet worden und funktionieren miteinander.

Für Abhängigkeiten, die Teil der BOM sind, müssen also keine Versionsangaben getätigt werden.

spring-boot-starter-parent bringt folgende zusätzliche Defaults in das Projekt:

Java 1.8 als Default Compiler Level

UTF-8-Kodierung der Quellen

aktiviertes Filtern der Ressourcen

application.properties

und

application.yml

, inklusive profilspezifischer Einstellungen (Achtung, in einem Spring-Boot-Maven-Projekt werden

@...@

als Platzhalter anstelle der üblichen

${...}

genutzt, da die letztgenannte Syntax mit Ausdrücken der Spring Expression Language kollidieren würde)

Diese Einstellungen – wie auch die Versionen der Abhängigkeiten – können mit Propertys überschrieben werden. Spring Boot 2 setzt allerdings Java 8 voraus, Java 6 und 7 werden nicht mehr unterstützt. Sofern Sie Java 6 oder 7 benutzen müssen, können Sie nur Spring Boot <= 1.5.x einsetzen.

1.2Abhängigkeiten definieren

Die Abhängigkeiten eines Maven-Projektes können ohne IDE mit mvn dependency:tree aufgelistet werden:

[INFO] Scanning for projects...

[INFO]

[INFO] -----------------------------------------------------

[INFO] Building helloworld 0.0.1-SNAPSHOT

[INFO] -----------------------------------------------------

[INFO]

[INFO] --- maven-dependency-plugin:2.10:tree (default-cli)

@helloworld ---

[INFO] de.springbootbuch:helloworld:jar:0.0.1-SNAPSHOT

[INFO] -----------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] -----------------------------------------------------

[INFO] Total time: 3.303 s

[INFO] Finished at: 2018-03-15T16:23:18+01:00

[INFO] Final Memory: 17M/309M

[INFO] -----------------------------------------------------

Listing 1–3spring-boot-starter-parent selber hat keine Abhängigkeiten.

Es werden nun zwei Abhängigkeiten deklariert: org.springframework.boot:spring-boot-starter-test und org.springframework.boot:spring-boot-starter-web, der erstgenannte im Scope test:

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

</dependencies>

Listing 1–4Abhängigkeiten fürs Testen und Entwickeln

spring-boot-starter-parent nutzt Mavens Dependency Management. Dabei werden in einem zentralen POM Abhängigkeiten und ihre Versionen gepflegt, ohne sie tatsächlich als solche zu deklarieren. Werden die Abhängigkeiten dann in Projekten, die von diesem Parent-POM erben, konkretisiert, kann auf die Angabe von Versionsnummern verzichtet werden. Würden diese Versionsnummern im <version />-Element der Abhängigkeit angegeben, so würde eine entsprechende Warnung im Log erscheinen. Sollen Versionen überschrieben werden, so muss dies mit Propertys geschehen.

org.springframework.boot:spring-boot-starter-web hängt ab vom Starter spring-boot-starter-tomcat und mit diesem unter anderem von org.apache.tomcat.embed:tomcat-embed-core: Die Anwendung, die hier erstellt wird, beinhaltet also bereits einen eingebetteten Webcontainer, der vollständig konfiguriert ist und per Default auf Port 8080 horcht. Es muss also kein dedizierter Container aufgesetzt werden, um eine Spring-Boot-Anwendung zu verteilen, und die Anwendung kann direkt gestartet werden. In Unterabschnitt 8.1.4 wird beschrieben, wie der eingebettete Container konfiguriert, angepasst oder ein anderer Container als Apache Tomcat genutzt werden kann.

1.3Hallo, Welt!

Zu diesem Zeitpunkt ist das Projekt immer noch leer. Die Deklaration von org.springframework.boot:spring-boot-starter-test hat unter anderem transitive Abhängigkeiten zum Testsupport von Spring Boot und Spring sowie natürlich zu JUnit 42. Abschnitt 15.1 geht im Detail auf diese Abhängigkeiten ein.

Hallo, Welt kann damit also vollständig testgetrieben entwickelt werden. Testgetrieben heißt, dass Sie zuerst Code schreiben, der das erwartete Ergebnis überprüft, und erst dann das eigentliche Programm. Es wird ein erster Test im Verzeichnis src/test/java angelegt. src/test/java ist das Standardverzeichnis von Maven für Testklassen:

@RunWith(SpringRunner.class)

@WebMvcTest

public classApplicationTest{

@Autowired

private MockMvc mockMvc;

@Test

publicvoidhelloWorldShouldWork()throws Exception {

this.mockMvc

.perform(

get("/hello").param("name","World"))

.andExpect(status().isOk())

.andExpect(

content().string("Hello, World\n"));

}

}

Listing 1–5ApplicationTest.java

Details dieses Tests werden ausführlich im Kapitel 15 »Tests und Dokumentation« besprochen. Durch @RunWith(SpringRunner.class) wird festgelegt, dass ein spezialisierter JUnit Runner zur Ausführung des Tests genutzt wird. @WebMvcTest legt fest, dass ausschließlich Komponenten getestet werden, die in den Bereich Spring MVC fallen. Mit der Instanzvariable mockMvc können schließlich URLs dieser Komponenten getestet werden. Im Beispiel heißt das konkret: »Der Aufruf der URL ’/hello’ mit Request-Parameter name=World soll den HTTP Status 200 haben und den Inhalt ’Hello, World’ zurückgeben.«. Dabei ist der sogenannte Test-Slice @WebMvcTest »intelligent« genug, nicht den vollständigen, eingebetteten Servlet-Container zu starten und stattdessen eine »Mock«-Umgebung zu nutzen.

Der Test wird ausgeführt mit mvn test und schlägt leider fehl. Der korrekte Rootcause lautet: »Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=…) with your test«.

Der Test kann keinen Spring-Kontext finden und konfigurieren, es gibt ihn aktuell nicht. Ein gültiger Spring-Kontext wird durch die Klasse Application.java in Listing 1–6 definiert. In wenigen Zeilen Code passieren bereits etliche interessante und wichtige Dinge:

packagede.springbootbuch.helloworld;

importorg.springframework.boot.SpringApplication;

import

org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

public classApplication{

public staticvoidmain(String... args) {

SpringApplication.run(Application.class, args);

}

}

Listing 1–6Application.java

Meta- oder Composed-Annotationen

Im Spring-Sprachgebrauch werden Meta- und Composed-Annotationen unterschieden. Als Meta-Annotation wird eine Annotation, die auf einer weiteren Annotation verwendet wird, bezeichnet. Eine Meta-Annotation erweitert die ursprüngliche Annotation um zusätzliche, beschreibende Eigenschaften. Die daraus entstandene Composed-Annotation kann wie eine reguläre Annotation auf entsprechende Ziele (Klasse, Methoden, Parameter etc.) angewandt werden.

Auslöser ist die zusammengesetzte (composed) Annotation @SpringBoot-Application, die folgende Annotationen kombiniert:

@SpringBootConfigurationZentrale Konfiguration einer Spring-Boot-Anwendung. Spring-Boot-Anwendungen sollten maximal eine @SpringBootConfiguration-Annotation beinhalten. Sie ist eine Spezialisierung der @Configuration des Spring-Frameworks selber, die zentraler Bestandteil der Java-basierten Konfiguration ist.

@EnableAutoConfigurationEbenfalls eine Annotation aus Spring Boot. Sie schaltet die automatische Konfiguration ein, die anhand der deklarierten Abhängigkeiten Vermutungen anstellt, welche Beans genutzt werden sollen, und diese entsprechend konfiguriert. Im Beispiel wäre das unter anderem der eingebettete Servlet-Container org.apache.tomcat.embed:tomcat-embed-core, für den automatisch eine TomcatServletWebServerFactory erzeugt würde.

@ComponentScanDiese Annotation ist schlussendlich Bestandteil des Spring-Frameworks selber. Sie schaltet – sofern kein Wert durch das Attribut basePackages konfiguriert ist – die Suche nach »@-Komponenten« ausgehend vom Package der annotierten Klasse ein. @-Komponenten sind unter anderem @Service, @Controller, @RestController und andere.

Warnung

@SpringBootApplication beziehungsweise @ComponentScan sollte niemals auf eine Klasse innerhalb des Default-Package angewandt werden. Die Suche nach Komponenten würde dann auf alle Klassen, einschließlich denen der JVM und der deklarierten Abhängigkeiten ausgedehnt werden.

Die Main-Methode der Klasse Application startet schlussendlich mit Hilfe der Utility-Klasse SpringApplication die eigentliche Anwendung. Durch run werden folgende Schritte automatisch durchgeführt:

Auswahl und Erstellung eines passenden

ApplicationContext

Registrierung einer

CommandLinePropertySource

, die jegliche Argumente der Anwendung als Eigenschaften in der Spring-Umgebung veröffentlicht

Aktualisierung des Kontextes mit Laden aller gefundenen »@-Komponenten« im Gültigkeitsbereich »singleton«

Ausführung aller Beans vom Typ

CommandLineRunner

Sie könnten nun bereits Ihre Anwendung über die Main-Methode starten, ein weiterer Versuch des Testens mit mvn test schlägt allerdings immer noch fehl. Der Test ist zwar in der Lage, den Kontext zu laden und zu initialisieren, da er das Vorhandensein der mit @SpringBootApplication annotierten Klasse erkennt. Nur entspricht das jetzige Verhalten der Anwendung noch nicht dem erklärten Testziel:

Status expected:<200> but was:<404>

[..]

de.springbootbuch.helloworld.ApplicationTest.

helloWorldShouldWork(ApplicationTest.java:26)

Listing 1–7Der Test schlägt immer noch fehl …

Der Test erwartet eine gültige Antwort mit HTTP-Status 200 hinter der URL /hello. Stattdessen bekommt er Status 404 »Not found« zur Antwort. Sie müssen also eine Funktionalität ergänzen, die diese URL bereitstellt:

@RestController

public static classHelloWorldController{

@GetMapping("/hello")

public String helloWorld(

@RequestParamfinal String name) {

return"Hello, "+ name +"\n";

}

}

Listing 1–8HelloWorldController

Hier wird ein @RestController als statische, innere Klasse deklariert. Dieser befindet sich unterhalb des Package, in dem der Komponentenscan abläuft, und wird als Singleton Bean im ApplicationContext registriert. Die genutzten Annotationen @RestController, @GetMapping und @RequestParam sind nicht spezifische Bestandteile von Spring Boot, sondern Teil des Spring-Web-MVC-Moduls, das Sie in Kapitel 8 im Detail kennenlernen werden.

Ein weiterer Testlauf endet nun erfolgreich. Da der Empfehlung gefolgt wurde, spring-boot-starter-parent als Grundlage des POM zu benutzen, kann die Anwendung nun mit mvn spring-boot:run gestartet werden. Ein Aufruf der URL zum Beispiel mit cURL liefert folgendes Ergebnis:

curl -X "GET" "http://localhost:8080/hello?name=World"

Hello, World

Listing 1–9Aufruf der Anwendung mit cURL

1.4Liefern

Die Hallo, Welt-Anwendung soll als ausführbares Jar ausgeliefert werden und alle für die Anwendung notwendigen Bibliotheken, Klassen und Konfigurationsdateien enthalten. Gerade im Hinblick auf die Verteilung von Microservices haben sich »self-contained« Artefakte bewährt.

Aktuell gibt es keine standardisierte Möglichkeit, ausführbare »fat jars« mit Java-Bordmitteln zu erzeugen. Während einige Projekte »Über-Jars« bevorzugen, in denen alle Abhängigkeiten entpackt und in einem Modul ausgeliefert werden, geht das Spring-Boot-Projekt einen anderen Ansatz, da es im Falle eines Über-Jars unter anderem nicht mehr möglich ist, zu sehen, welche Bibliotheken benutzt wurden.

Spring Boot führt sowohl für Maven- als auch Gradle-Projekte den spring-boot-loader ein, der die Erstellung eines ausführbaren Jar Archive inklusive verschachtelter Bibliotheken erlaubt. Die Benutzung innerhalb des obigen Maven-Projektes ist unter Verwendung des Spring-Boot-Maven-Plugins denkbar einfach. Im POM wird wie folgt ergänzt:

<build>

<finalName>${project.artifactId}</finalName>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

Listing 1–10Ergänzung des Spring-Boot-Maven-Plugin

Ein mvn package erstellt nun im target-Verzeichnis des Builds ein ausführbares Jar-Archiv, das mit der aktuellen Spring-Boot-Version rund 14 MB groß ist:

$ ls -lisa target/*.jar*

14203008 6 Jan 10:39 target/helloworld.jar

3595 6 Jan 10:39 target/helloworld.jar.original

Listing 1–11Fertiges Artefakt

Die Anwendung kann nun mit java -jar target/helloworld.jar gestartet und in nahezu beliebigen Varianten ausgeliefert werden.

1.5Fehler erkennen

Es gibt regelmäßig Fehlerfälle, die den Start der kompletten Anwendung verhindern. Wird »klassisches« Spring verwendet, passiert es oft, dass der Grund für den Fehlstart, der in einigen Fällen trivial ist, in einem langem Stacktrace verschwindet.

Spring Boot bietet zu diesem Zweck die automatisch aktiven FailureAnalyzers. FailureAnalyzers fangen Exceptions während des Starts einer Anwendung ab und erstellen eine lesbare Fehlermeldung zusammen mit Hinweisen, warum der Fehler auftritt und wie er beseitigt werden kann.

Wird das helloworld zum Beispiel zweimal gestartet, so schlägt der zweite Start fehl, da Port 8080 bereits belegt ist:

***************************

APPLICATION FAILED TO START

***************************

Description:

The Tomcat connector configured to listen on port 8080

failed to start. The port may already be in use

or the connector may be misconfigured.

Action:

Verify the connector’s configuration, identify and stop any

process that’s listening on port 8080, or configure

this application to listen on another port

Listing 1–12Beispiel für einen FailureAnalyzer

Listing 4–11 im Abschnitt 4.1 »Externe Konfiguration« zeigt die Ausgabe des FailureAnalyzer für JSR-303-Validierungen. Probleme im Kontext der Dependency Injection für Fälle, in denen keine, zu viele oder Beans vom falschen Typ zur Verfügung stehen, werden ebenso analysiert wie fehlerhaft konfigurierte Datenbankverbindungen. Der Stacktrace steht dabei weiterhin zur Verfügung. Ebenso kann mit dem Parameter --debug zusätzlich eine ausführliche Analyse der automatischen Konfiguration ausgegeben werden.

Falls das nicht ausreicht, können eigene Klassen unter dem Interface org.springframework.boot.diagnostics.FailureAnalyzer implementiert werden. Eigene FailureAnalyzer werden in der Textdatei META-INF/spring.factories unter dem Schlüssel org.springframework.boot.diagnostics.FailureAnalyze als kommagetrennte Liste von vollständig qualifizierten Klassennamen registriert:

org.springframework.boot.diagnostics.FailureAnalyzer\

de.springbootbuch.CustomConstraintViolationFailureAnalyzer

Listing 1–13Registrierung eigener FailureAnalyzer

Teil II

Spring Boot

Dieser Teil stellt die Säulen von Spring Boot vor. Dazu gehören insbesondere die Verwaltung von Abhängigkeiten (Dependency Management), die automatische Konfiguration und die Starter, die beides zusammenfassen. Die einfache, codefreie externe Konfiguration ist eine weitere wichtige Säule. Grundlage des Systems ist das Spring-Framework selber.

Abb. 1–1Spring Boots Säulen

Der zweite Teil baut auf dem Beispiel der Einleitung auf und erklärt sowohl das Spring Boot Dependency Management mit Maven und Gradle und wie der Spring Initializr genutzt werden kann, um Projekte und deren Abhängigkeiten zu generieren. Da Sie die Spring-Framework-Grundlagen kennen müssen, bevor ich zeige, wie Spring Boot funktioniert, werden wir diese zuerst behandeln, bevor Sie lernen, wie eine Spring-Boot-Anwendung konfiguriert wird. Das direkt anschließende Kapitel zeigt die »Magie« hinter der automatischen Konfiguration und erklärt, wie sie zu eigenen Zwecken, für eigene Funktionen nutzbar gemacht werden kann.

Ebenfalls Kernbestandteil von Spring Boot selber sind Entscheidungen hinsichtlich Logging, daher wird auch dieses Thema hier aufgegriffen.

Im abschließenden Kapitel möchte ich Ihnen die Spring Boot devtools vorstellen. Diese Werkzeuge können Ihren Entwicklungsprozess zusätzlich beschleunigen.

2Projektstruktur

Spring Boot möchte übliche funktionale und nicht funktionale Probleme, die einer schnellen Produktivsetzung im Weg stehen, effektiv und effizient lösen, und zwar in einer konsistenten Art und Weise. Dazu gehört nicht nur ein vereinheitlichter Konfigurationsmechanismus, sondern auch eine Projektstruktur, die in gleicher Art und Weise in unterschiedlichen Projekten benutzt wird.

Letzten Endes ist Spring Boot »nur« eine Java-Bibliothek, die als Abhängigkeit eingebunden und benutzt wird – allerdings vereinfachen die folgenden Empfehlungen nicht nur den Entwicklungsprozess, sondern auch die Verteilung der fertigen Anwendungen und Pflege derselben.

2.1Build-Management-Tools

Eine Anwendung, die Spring Boot benutzt, kann sowohl mit Maven oder Gradle problemlos kompiliert und verteilt werden. Beide Buildsysteme unterstützen die zentrale Verwaltung von Abhängigkeiten. Es ist prinzipiell möglich, eine Spring-Boot-Anwendung mit Ant oder anderen Systemen zu bauen, aber nicht empfehlenswert, da Sie viele der für Maven und Gradle verfügbaren Hilfsmittel nachbauen müssten.

Besonders hervorzuheben ist die kuratierte Liste von Abhängigkeiten innerhalb eines Spring-Boot-Projektes. Jedes Spring-Boot-Release wird begleitet von einer Liste von Abhängigkeiten und expliziten Versionen, gegen die Spring Boot sowie das Spring-Framework getestet wurden und von denen bekannt ist, dass sie mit Spring Boot funktionieren. Die Versionen dieser Abhängigkeiten müssen nicht angegeben werden, können aber durch Setzen von Eigenschaften überschrieben werden. Die Versionen der Abhängigkeiten sind im Anhang F der Spring-Boot-Referenz dokumentiert, und in der Regel können die zu setzenden Eigenschaften aus der ID des Artefakts abgelesen werden. Falls das nicht möglich ist, sind sie gleichermaßen für Maven- und Gradle-Projekte im dem POM des Moduls spring-boot-dependencies1 sichtbar.

Während Versionen von Bibliotheken Dritter teilweise gefahrlos überschrieben werden können, wird dringend davon abgeraten, die Version des Spring-Frameworks selber zu überschreiben, da jedes Spring-Boot-Release auf genau einer bestimmten Version des Spring-Frameworks aufbaut.

2.1.1Maven

Maven: Sammler des Wissens

Der Begriff Maven entstammt dem Jiddischen und bedeutet in etwa soviel wie »Der, der versteht«, Connoisseur, Experte oder auch Sammler des Wissens: Maven ist ein Build-Management-Tool, das vom Gedanken der »Konvention vor Konfiguration« getrieben wird. Maven geht von einem Zyklus der Softwareerstellung aus, der häufig durchlaufen wird: Validierung, Kompilierung, Testen, Paketieren, Integrationstests, Verifizierung, Installation und Verteilung.

Die notwendigen Informationen zum Bau eines Maven-Projektes, die sich nicht aus Konventionen ableiten lassen, werden in einem Project Object Model, dem POM, gespeichert. Das POM wird in der Regel in einer XML-Datei namens pom.xml abgespeichert.

POMs können voneinander erben. Damit werden zentrale Definitionen und Konfigurationen ermöglicht, die an Teilprojekte weitergegeben werden können.

Eine wichtige Aufgabe von Maven ist die Auflösung von Abhängigkeiten, die ein Softwareprojekt hat. Dies kann aus lokalen Quellen oder Quellen im Intranet oder Internet geschehen. Beide Quellen heißen Repositorys.

Maven kann darüber hinaus zentrale Eigenschaften (»properties«) eines Projektes verwalten, Quelltexte und andere Ressourcen während des Bauens filtern und vieles mehr.

Maven hat eine modulare Architektur, die über Plugins erweitert werden kann. Mit dem Spring-Boot-Maven-Plugin steht Ihnen ein Plugin zur Verfügung, das Ihnen unter anderem beim Bau ausführbarer Artefakte hilft.

Neu generierte Spring-Boot-Projekte setzen Maven 3.5 ein.

Erben …

In Abschnitt 1.1 wurde in Listing 1–2 gezeigt, wie ein Maven-Projekt aufgebaut werden muss, so dass es von spring-boot-starter-parent erbt und in den Genuss der zentralen »Bill of Materials« kommt.

spring-boot-starter-parent konfiguriert weiterhin, welche Kodierung die Quelltexte haben (per Default UTF-8), die Java-Version und einiges mehr: Spring-Boot-Projekte sind damit sehr konsistent untereinander.

Von einiger Wichtigkeit für zentrale Module des Spring-Ökosystems ist Java-8s Möglichkeit, die Namen von Konstruktor- und Methodenparameter aus den Class-Files zu ermitteln. Diese Namen können zum Beispiel in SpEL-Ausdrücken, in benannten SQL-Abfragen im Spring-Data-Modul oder als Namen von Pfadparametern wie im Spring-Web-MVC-Modul genutzt werden. Vor Java 8 waren diese Namen über Javas Reflection-API nur dann ableitbar, wenn die Quelltexte mit der Option -debug übersetzt wurden. Der Java 8 Compiler stellt -parameter zur Verfügung. Der spring-boot-starter-parent konfiguriert diesen Schalter per Default. Falls Sie dies nicht wünschen, müssen Sie in Ihrem POM das Compiler-Plugin explizit konfigurieren. Umgekehrt gilt das Gleiche: Wenn Sie das Parent-POM nicht nutzen und trotzdem diese Funktion haben möchten, konfigurieren Sie das Compiler-Plugin entsprechend:

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-compiler-plugin</artifactId>

<configuration>

<compilerArgs>

<arg>-parameters</arg>

</compilerArgs>

</configuration>

</plugin>

Listing 2–1Konfiguration des Compiler-Plugins, wenn das Parent-POM nicht genutzt wird

Quelltexte

override_versions auf GitHub: https://github.com/springbootbuch/override_versions

override_versions_with_imports auf GitHub: https://github.com/springbootbuch/override_versions_with_imports

Die geerbten Informationen aus dem spring-boot-starter-parent-POM sind nicht in Stein gemeißelt. Ergänzend zum Beispiel aus 1–2 zeigt das Projekt override_versions, wie die Version einer transitiven Abhängigkeit, nämlich die des eingebetteten Tomcats, durch Setzen von einer Property überschrieben werden kann, ohne manuell Abhängigkeiten auszuschließen oder selber konsistent Versionen verwalten zu müssen:

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.0.0.RELEASE</version>

</parent>

<properties>

<!-- Use a certain tomcat version -->

<tomcat.version>8.5.9</tomcat.version>

</properties>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

</dependencies>

Listing 2–2Erben von »spring-boot-starter-parent« und Überschreiben einzelner Versionen

... oder importieren

Falls bereits ein firmenweites Standard-POM vorliegt, von dem abgeleitet werden muss, oder es sonstige Gründe gibt, das Parent-POM nicht zu nutzen, kann die Verwaltung von Abhängigkeiten durch die Spring »Bill of Materials« (BOM) mit Einschränkungen dennoch genutzt werden. Sie kann über den Maven-Gültigkeitsbereich »import« importiert werden, wie Listing 2–3 zeigt:

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>

spring-boot-dependencies

</artifactId>

<version>2.0.0.RELEASE</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

Listing 2–3»Manuelles« Importieren der Spring Boot BOM

Durch den Import der BOM kommt Ihr Projekt zwar in den Genuss der kuratierten Abhängigkeiten, kann aber nicht von den weiteren Einstellungen des Parent-POM wie dem oben erwähnten Compiler-Plugin profitieren. Darüber hinaus ist das Überschreiben von Versionen deutlich weniger komfortabel und fehleranfälliger: In der »Bill of Materials« werden durchgängig Propertys für Versionen genutzt. Erben Sie vom Parent-POM, können Sie mit dem Setzen einer Property korrekt die Versionen aller notwendigen Abhängigkeiten ebenfalls setzen. Wenn Sie die BOM wie in Listing 2–3 importieren, können Sie die Abhängigkeiten im Dependency Management nur wie in Listing 2–4 gezeigt überschreiben, das Setzen einer Property wie in Listing 2–2 reicht nicht:

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.apache.tomcat.embed</groupId>

<artifactId>tomcat-embed-core</artifactId>

<version>8.5.9</version>

</dependency>

<dependency>

<groupId>org.apache.tomcat.embed</groupId>

<artifactId>tomcat-embed-el</artifactId>

<version>8.5.9</version>

</dependency>

<dependency>

<groupId>org.apache.tomcat.embed</groupId>

<artifactId>

tomcat-embed-websocket

</artifactId>

<version>8.5.9</version>

</dependency>

</dependencies>

</dependencyManagement>

Listing 2–4Überschreiben von Abhängigkeiten im Dependency Management ohne Parent-POM

Während Sie mit dem Parent-POM auch von verwalteten Plugin-Versionen profitieren, ist dies ohne Parent-POM nicht möglich. Zu guter Letzt müssen Sie beim reinen Import der Bill of Materials explizit die Java-Version angeben. Seit Spring Boot 2.0 ist Java 8 der Default, Java 6 und 7 werden nicht mehr unterstützt:

<properties>

<maven.compiler.source>1.8</maven.compiler.source>

<maven.compiler.target>1.8</maven.compiler.target>

</properties>

Listing 2–5Die Java-Version muss beim Import der BOM explizit angegeben werden.

Zusätzliche Werkzeuge

Spring Boot bietet Ihnen zusätzliche Werkzeuge für Maven und Gradle. Zu den Hauptfunktionen zählt die Paketierung der Anwendungen als ausführbares Fat Jar beziehungsweise als ausführbare War-Datei.

Für Maven ist dies das Spring-Boot-Maven-Plugin, das mit eingebunden wird. Auf die Angabe einer Versionsnummer kann bei Verwendung des Parent-POM verzichtet werden.

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>

spring-boot-maven-plugin

</artifactId>

</plugin>

</plugins>

</build>

Listing 2–6Ergänzung des Spring-Boot-Maven-Plugins

Wird das Plugin wie oben gezeigt eingebunden, führt ein mvn package zu zwei Jar- beziehungsweise War-Dateien: artefakt.jar sowie artefakt.jar.original, da das Goal spring-boot:repackage automatisch während der Maven-Package-Phase aufgerufen wird. Die ursprüngliche Datei beinhaltet dabei nur die Klassen und Ressourcen, die sich aus der Anwendung ergeben, die neu paketierte Jar-Datei hingegen liegt im Executable Jar-Format vor.

In Abschnitt Artefakte wird detailliert beschrieben, wie die Neupaketierung der Anwendung gesteuert werden kann, insbesondere wie Artefakte wie die devtools vom Fat Jar ausgeschlossen werden können.

Filterung von Ressourcen

Das Spring-Boot-Maven-Plugin hat noch eine wichtige Funktion: die Konfiguration der Filterung von Ressourcen (Quelltexte, Propertys und mehr). Maven kann Platzhalter in beliebigen Dateien durch Maven-Propertys, System-Propertys oder Umgebungsvariablen ersetzen. Normalerweise werden diese Platzhalter in ${...}-Platzhaltern eingefasst. Dieser Platzhalter wird aber ebenfalls für Spring-eigene Eigenschaften beziehungsweise innerhalb der SpEL genutzt. Daher wird dieser Platzhalter umdefiniert und ist in Spring-Boot-Projekten @...@ (die Maven-Property resource.delimiter dient zum Setzen des Platzhalters). Standardmäßig werden alle Konfigurationsdateien (unter anderem application.properties, application.yml) sowie deren profilspezifische Abkömmlinge gefiltert.

Build-Informationen in der Anwendung

Oftmals werden Sie die Anforderung bekommen, Informationen über den Build in der Anwendung anzuzeigen. Das Spring-Boot-Maven-Plugin stellt zu diesem Zweck das Goal build-info zur Verfügung, das Sie allerdings manuell konfigurieren müssen:

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

<executions>

<execution>

<goals>

<goal>build-info</goal>

</goals>

</execution>

</executions>

</plugin>

Listing 2–7Ausführung des Goals build-info vor der Paketierung

2.1.2Gradle

Gradle: Erwarte das Unerwartete

Gradle ist ein auf Groovy basierendes Build-Management-Tool. Im Gegensatz zu Maven-Projektdefinitionen sind Gradle-Skripte direkt ausführbarer Code.

Gradle versucht, das Prinzip »Konvention vor Konfiguration« aus Maven-Projekten mit der Flexibilität anderer Build-Management-Tools wie ant zusammenzubringen.

Da Gradle für Builds von Softwaresystemen mit einer Vielzahl von Teilprojekten entworfen wurde, unterstützt Gradle insbesondere inkrementell und parallel ablaufende Build-Prozesse.

Viele Standardlebenszyklen wurden aus Maven übernommen. Ein Java-Projekt, das sich an diese Konventionen hält, kann zum Beispiel alleine mit apply plugin: 'java' gebaut werden.

Verschiedene Abschnitte des Builds werden in Gradle »Tasks«, Aufgaben, genannt. Sie können beliebig komplexe Aufgaben erledigen und auch nahezu beliebig voneinander abhängen: Erwarte das Unerwartete.

Die Definition eines Projektes wird in der Datei build.gradle hinterlegt.

Projekte auf Basis von Spring Boot 2 benötigen mindestens Gradle in Version 4, damit alle Plugins korrekt funktionieren.

Das Build-Management-Tool Gradle kann auf die gleichen Repositorys wie Maven zugreifen und beinhaltet im Kern ein System zur Verwaltung von Abhängigkeiten. Allerdings müssen Sie das zentrale Dependency Management, bei dem Versionen in einer zentralen Stelle vorgegeben werden, über ein Plugin, dem Spring-Boot-Gradle-Plugin, nachrüsten. Es kann nach Deklaration im Gradle-buildscript-Block in der Datei build.gradle, dem Pendant zur pom.xml, mittels apply genutzt werden:

buildscript {

ext {

springBootVersion '2.0.0.RELEASE'

}

dependencies {

classpath("org.springframework.boot:spring-boot-gradle-

plugin:${springBootVersion}")

}

}

apply plugin:'org.springframework.boot'

apply plugin:'io.spring.dependency-management'

Listing 2–8Nutzung des Spring-Boot-Gradle-Plugins

Ein vollständiges Beispiel steht in Abschnitt 16.1 im Listing 16–1 zur Verfügung. Im dependencies-Block können nun – wie auch mit Maven – die Versionsnummern weggelassen werden:

dependencies {

compile "org.codehaus.groovy:groovy"

compile "org.springframework.boot:spring-boot-starter-web"

testCompile "org.springframework.boot:spring-boot-starter-test"

}

Listing 2–9Nutzung von Dependency Management mit Gradle

Das Spring-Boot-Plugin konfiguriert den Build-Prozess automatisch so, dass ausführbare Jar-Dateien erzeugt werden. Darüber hinaus sind die zur Verfügung stehenden neuen Gradle-Aufgaben ähnlich den Maven-Zielen, wie Tabelle 2–1 zeigt.

Name

Funktion

gradle bootRun

Führt die Anwendung aus dem aktuellen Verzeichnis heraus aus; über das Attribut addSources kann definiert werden, ob statische Ressourcen automatisch neugeladen werden, wenn die Entwicklungswerkzeuge im Klassenpfad sind

gradle bootJar

Erzeugt eine ausführbare Jar-Datei oder War-Datei

gradle bootWar

Erzeugt eine ausführbare War-Datei

Tab. 2–1Aufgaben des Spring-Boot-Gradle-Plugins

Um die Datei build-info.properties mit den Metainformationen des aktuellen Builds zu erzeugen, muss der Spring-Boot-Task ähnlich wie im Maven-Pendant angepasst werden:

springBoot {

buildInfo()

}

Listing 2–10Erzeugung der Build--Metainformationen mit Gradle

2.2Pakete und Klassen strukturieren

Eine Spring-Boot-Anwendung kann auf vielfältige Art strukturiert werden, und es bestehen keine harten technischen Einschränkungen bezüglich der Package-Struktur. Eine Einschränkung, die generell für Java-Programme gemacht wird, gilt für eine Spring-Boot-Anwendung in besonderem Maße: Von der Verwendung des Default-Package wird abgeraten! Alle Klassen, die keine explizite Package-Deklaration haben, sind Teil des Default-Package.

In der Regel wird genau eine Klasse einer Spring-Boot-Anwendung mit @SpringBootApplication wie in Kapitel 1 in Listing 1–6 gezeigt ausgezeichnet. Diese Annotation ist eine zusammengesetzte Annotation oder Meta-Annotation, die unter anderem die Spring-Framework-Annotation @ComponentScan beinhaltet. @ComponentScan löst die Suche nach Stereotypen aus. Stereotypen sind alle Klassen, die mit der Framework-Annotation @Component beziehungsweise mit zusammengesetzten Annotationen, die selber mit @Component versehen wurden, annotiert sind. Dazu gehören unter anderem @Configuration, @Service, @Controller und @Repository. Über das Attribut basePackages kann eingeschränkt werden, in welchen Packages gesucht wird; über die Attribute excludeFilters beziehungsweise includeFilters kann angegeben werden, nach welchen Klassen, Stereotypen oder Mustern gesucht wird oder welche ignoriert werden. Die @SpringBootApplication schränkt die Packages per Default nicht ein.

Es wird empfohlen, jede Spring-Boot-Anwendung beziehungsweise jeden auf Spring Boot basierenden Microservice unter einem separaten Root-Package anzulegen. Im folgenden Beispiel wird eine fachliche Schichtung der darunterliegenden Packages und keine technische empfohlen:

.

`-- de

`-- bootifultodos

|-- Application.java

|-- feiertage

| `-- FeiertagApiController.java

|-- todos

| |-- TodoApiController.java

| |-- TodoEntity.java

| `-- TodoRepository.java

`-- wochenplaner

`-- WochenplanService.java

Listing 2–11Typische und empfohlene Projektstruktur

Die Klasse Application stellt dabei den Einstiegspunkt in den Service dar, beinhaltet die Main-Methode und ist mit @SpringBootApplication annotiert.

Natürlich können die Packages auch technisch geschichtet werden, zum Beispiel als »Domain«, »Service« und »Web«. Die Erfahrung aus zahlreichen Projekten lehrt aber, dass eine fachliche Schichtung zu saubererem Code und besserer Architektur führen kann. Die mit Java 8 mögliche Strukturierung von Packages, Klassen und deren Sichtbarkeit untereinander erlaubt nur eingeschränkt, dass unterschiedliche Fachlichkeiten innerhalb eines technischen Package sich nicht gegenseitig sehen dürfen. Die Sichtbarkeit package private kann innerhalb einer technischen Schichtung nicht angewandt werden, da höhere Ebenen keinen Zugriff auf untere Ebenen hätten.

Im Beispiel Listing 2–11 ist das TodoRepository nur im Package todo sichtbar. Diese Einschränkung könnte mit Standard-Java-Mitteln bei einer technischen Schichtung nicht vorgenommen werden, und das Repository wäre unnötigerweise global verfügbar.

Eine fachliche Schichtung hingegen ermöglicht zusammen mit Javas Modifiern package, private und protected eine sauberere Schichtung Ihrer Anwendung. Diese einfache Lösung innerhalb der Sprachmittel ist oft einer technischen Lösung mittels Buildsystemen vorzuziehen.

In Hinblick auf Microservices hat eine Schichtung dieser Art noch einen weiteren Vorteil: Es ist leicht erkennbar, welche Fachlichkeiten als eigener Service implementiert werden können.

2.3Spring Initializr

Unter http://start.spring.io steht der Spring Initializr als Webanwendung zur Verfügung. Der Spring Initializr ist eine ebenfalls mit Spring Boot entwickelte Anwendung, die Projekte nach oben beschriebener Struktur als »Schnellstart«-Projekte generiert.

Projektgenerator

Der Spring Initializr erlaubt in einer komfortablen Oberfläche nach Auswahl des Projekttyp (Maven oder Gradle), der JVM-Sprache (Java, Kotlin oder Groovy), der Spring-Boot-Version sowie der Eingabe der Projektkoordinaten eine einfache Auswahl der benötigten und gewünschten Abhängigkeiten. Die Abhängigkeiten können dabei entweder in einem Suchfeld angegeben oder in einer erweiterten Ansicht per Checkbox ausgewählt werden. Die erweiterte Ansicht hat dabei den Vorteil, einen Überblick auf die Vielzahl unterstützter Spring-Module sowie Third-Party-Bibliotheken zu geben. Nahezu jede Checkbox beziehungsweise jegliche Auswahl im Suchfeld Dependencies entspricht dabei einem Starter.

Java Sprachversion

Bis einschließlich Spring Boot 1.5 unterstützte Spring Boot genau wie das Spring-Framework bis inklusive Version 4.3 alle Java-Versionen ab 1.6. Die minimale Sprachversion für Spring Boot 2 ist Java 8.

Das Ergebnis der Aktion Generate Project ist ein Archiv, das neben dem Buildfile des ausgewählten Build-Tools die passende Projektstruktur sowie die mit @SpringBootApplication annotierte Hauptanwendungsklasse enthält. Wenn Sie ein Betriebssystem nutzen, auf dem cURL und tar zur Verfügung stehen, so können Sie mit zwei Befehlen eine Spring-Boot-Anwendung herunterladen und starten:

curl https://start.spring.io/starter.tgz \

-d nameHalloWelt \

-d dependenciesweb | tar -xzf - \

&& ./mvnw spring-boot:run

Listing 2–12Verwendung des Spring Initializr in der Kommandozeile und Start der Anwendung

Die Hauptklasse trägt den Namen des erzeugten Projektes. Ihr Inhalt ist weitestgehend identisch mit der Klasse Application.java aus Kapitel 1 in Listing 1–6. Zusätzlich generiert werden ein Integrationstest (Listing 2–13), eine leere Konfigurationsdatei (application.properties) sowie leere Ordner zur Aufnahme von Templates wie in Abschnitt 8.2 beschrieben.

packagecom.example.demo;

importorg.junit.Test;

importorg.junit.runner.RunWith;

importorg.springframework.boot.test.context.SpringBootTest;

importorg.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)

@SpringBootTest

public classHalloWeltApplicationTests{

@Test

publicvoidcontextLoads() {

}

}

Listing 2–13Generierter Test

Sie können nicht nur den Namen des Projektes wie in Listing 2–12 gezeigt über Parameter anpassen, sondern natürlich auch weitere Informationen wie groupId, artifactId, version, description und package-Name.

Der Spring Initializr steht nicht nur als Webanwendung zur Verfügung. Sie können ihn programmatisch über eine REST-Schnittstelle ansprechen. Er beschreibt seine Fähigkeiten in einer HAL-konformen Schnittstelle. Ein Aufruf der Form curl -H 'Accept: application/json' https://start.spring.io gibt ein JSON-Dokument zurück, das die API detailliert beschreibt.

Diese API ist Basis der Projektgeneratoren der in Abschnitt 2.4 beschriebenen IDEs. Sie kann natürlich auch für eigene Skripte und automatische Abläufe genutzt werden. Die wichtigsten Parameter sind in Tabelle 2–2 aufgelistet.

Der Quelltext des Spring Initializr steht auf GitHub2 zur Verfügung. Die Anwendung ist nicht nur nützlich, um schnell und bequem Spring-Boot-Projekte mit den offiziell unterstützten Abhängigkeiten zu generieren, sondern kann auch in eigenen Szenarien eingesetzt werden, um beispielsweise eigene Projektformate oder Projekte mit speziellen Abhängigkeiten zu generieren.

Name

Funktion

groupId, artifactId, version, name, description und packageName

Grundlegende Projektparameter. Hervorzuheben sind name und artifactId. name bestimmt sowohl den Namen der Anwendung als auch den der Hauptklasse, artifactId bestimmt sowohl den Namen des Moduls als auch den Namen des generierten Archivs.

dependencies bzw. style

Die Bezeichnungen der Abhängigkeiten des Projektes. Achtung: Dies sind keine Maven-Koordinaten, sondern Bezeichner, die über die Metadaten des Initializr abgefragt werden können.

type

Die Art des Projektes

javaVersion

Die Sprachversion des Projektes

bootVersion

Die Spring-Boot-Version

language

Die zu verwendende JVM-Sprache (java, groovy oder kotlin)

packaging

Das Format des Artefaktes (jar oder war)

applicationName

Name der Anwendung

Tab. 2–2Optionen der start.spring.io API

2.4IDE-Unterstützung

Da Spring-Boot-Projekte in der Regel einen eingebetteten Application-Container wie Tomcat, Undertow oder Jetty beinhalten und sich ansonsten wie »normale« Java-Projekte verhalten, ist die Wahl einer IDE sehr offen. Solange die Anwendung als Fat Jar ausgeliefert wird, braucht man sich über die Kompatibilität einer IDE oder die Konfiguration eines Servers innerhalb derselben keine Gedanken machen.

Die im Folgenden vorgestellten IDEs eignen sich gleichermaßen gut, um mit Java 8 zu programmieren. Sie unterscheiden sich unter anderem im Preis, Kostenfaktor oder Komfort. Die in diesem Buch genannten Beispiele können in allen IDEs geöffnet, kompiliert und verteilt werden.

2.4.1Spring Tool Suite

Die Spring Tool Suite™ oder kurz STS ist eine speziell für die Entwicklung von Spring-basierten Anwendungen angepasste Entwicklungsumgebung, die auf Eclipse3 basiert. Sie ist kostenlos und ohne Zeitbeschränkung für Entwicklungszwecke und interne geschäftliche Anwendung nutzbar.

Die Suite beinhaltet weiterhin Pivotal tc Server, eine von Pivotal gepflegte kommerzielle Variante des Apache Tomcat Application Containers. Pivotal tc Server bietet erweiterte, speziell auf Spring-Anwendungen zugeschnittene Metriken sowie kommerziellen Support. Für die Entwicklung einer Spring-Boot-Anwendung wird er nicht benötigt.

Installation

Spring Tool Suite™ steht für Microsoft Windows und Linux als 32-Bit- und 64-Bit-Version, für Apple macOS nur als 64-Bit-Version unter https://spring.io/tools/sts/all als Download zur Verfügung, sie kann aber auch über den Eclipse Marketplace oder eine Update-Seite in eine normale Eclipse-Distribution installiert werden. Die Spring Tool Suite™ beinhaltet alle Werkzeuge, die benötigt werden, um mit Git verwaltete Maven- oder Gradle-basierte Projekte zu bearbeiten. Zusätzliche Plugins werden nicht benötigt.

Getting Started Guides

Die »Getting Started Guides« des Spring-Frameworks selber, von Spring Boot und den anderen Projekten des Spring-Ökosystems sind nützliche Projekte, um einzelne Funktionen und Paradigmen in Isolation kennenzulernen. Sie sind einerseits unter https://spring.io/guides verfügbar, können andererseits in der Spring Tool Suite™ über einen Dialog ausgewählt und importiert werden, wie Abb. 2–1 zeigt.

Das Menü File > New > Import Spring Getting Started Content beinhaltet alle verfügbaren Getting Started Guides für Spring und Spring Boot und erspart ein manuelles Klonen der Repositorys. Das Projekt steht nach Abschluss des Dialoges im Arbeitsbereich bereit: sowohl in einer initialen Version als auch in der vollständigen Version nach Abschluss aller Schritte des Guides.

Import vorhandener Projekte

Die Spring Tool Suite™ hat eine gute Unterstützung für Maven- und Gradle-Projekte. Vorhandene Projekte können sowohl über File > Import ... als auch über die SVN- und Git-Repository-Browser importiert werden.

Spring-Starter-Projekte

Über das Menü File > New > Spring Starter Project wird die API des Spring Initializr angesprochen, es wird ein neues Projekt wie in