Shownotes & Links
- Dependency Injection und Inversion of Control
- Michaels Buch zu Spring Boot 2
- Micrometer
- Spring
- Spring Boot
- Spring Initializer
Transkript
Michael Vitz: Hallo und herzlich Willkommen zu einer neuen Folge des INNOQ-Podcasts. Ich bin Michael Vitz und unser Thema ist heute Spring und Spring Boot und dazu habe ich mir als Gast den Michael eingeladen. Hallo Michael!
Michael Simons: Hallo Michael. Mein Name ist Michael Simons. Schön, dass ich hier sein darf. Ich bin Senior Consultant bei INNOQ und ich bin Autor des Buches “Spring Boot 2: Moderne Softwareentwicklung mit dem Spring Framework“.
Michael Vitz: Also offensichtlich der ideale Gast, um mit mir hier heute über dieses spannende Thema zu sprechen.
Michael Simons: Ich hoffe es.
Michael Vitz: Wenn man sich mit Spring Boot beschäftigt, dann fällt erst mal auf, es sind zwei Wörter, “Spring” und “Boot” und ich glaube, wir sollten erst einmal klären, was denn Spring überhaupt ist. Also was ist Spring im Kern, wie würdest du jemandem Spring kurz erklären, der vielleicht gerade mit Java angefangen hat zu entwickeln. Was sind die Kerne von Spring selbst?
Michael Simons: Im Spring Framework geht es ursprünglich um die beiden Themen Dependency Injection und Inversion of Control. Zwei Themen, die insbesondere die Fragestellung nach loser Kopplung und hoher Kohäsion beantworten können, wenn man sie richtig macht. Kern vom Spring Framework ist der Container, in dem die sogenannten Beans leben. Das sind Instanzen von Java-Klassen jeglicher Art und der Spring-Container bringt diese verschiedenen Instanzen zusammen über das Thema Inversion of Control. Inversion of Control bedeutet, dass nicht der Entwickler selbstständig hingeht und Abhängigkeiten einzelner Beans untereinander auflöst, sondern dass das vom Container gesteuert wird. Das ist für mich Kernbestandteil des Spring Frameworks. Darum herum hat sich ein großes System verschiedenster Module entwickelt. Diese reichen von Spring Web MVC - dort geht es um eine Möglichkeit, sehr schnell und effektiv Webanwendungen schreiben zu können. Dazu gehören Aspekte wie Routing: Wie werden URLs auf Java-Methoden innerhalb sogenannter Controller abgebildet. Es geht aber auch darum, wie Request-Parameter oder Teile von URLs auf Parameter in Methoden abgebildet werden - bis hin zu Transaktionen im Bereich Datenbanken zum Thema Logging und auch Security. Dabei ist Spring Security ein eigenes größeres Projekt und nicht nur ein Modul innerhalb des Spring Frameworks.
Michael Vitz: Genau. Ich würde das auch so beschreiben: Spring hat diesen IoC-Container als Hauptbestandteil und dann gibt es noch eine Menge Module, die teilweise mit im Kern sind und manchmal ein bisschen außen drum herum liegen. Ich glaube, jetzt alle Module zu erwähnen, dann ist die halbe Stunde um und wir haben sonst noch nichts getan.
Michael Simons: Richtig.
Michael Vitz: Und der zweite Bestandteil ist halt dieses Boot, das heißt, was bringt mir denn jetzt Spring Boot? Ist das etwas ganz anderes oder ist das Framework dann noch irgendwie mit dabei oder was ist denn jetzt dieses Spring Boot als nächster Ansatz?
Michael Simons: Ich habe Spring Boot vor einiger Zeit mal ganz ketzerisch als eigenen Application-Server tituliert und habe mir dafür ganz schnell ein bisschen verbale Prügel eingefangen. Also Spring Boot ist kein eigener Application-Server. Es ist aber auch kein eigenes Framework. Spring Boot hat sich 2014 auf die Fahnen geschrieben, den Anfang jeder Entwicklung mit dem Spring Framework stark vereinfachen zu wollen. Darüber haben wir ja gerade schon gesprochen, dass das Spring Framework ein sehr großes Framework ist und im Kern natürlich eine sehr genau beschreibbare Aufgabe hat. Aber durch die Vielzahl an Modulen, die es gibt, gibt es auch sehr viele Funktionen, die konfiguriert und verwaltet werden müssen bzw. können. Und genau daran setzt Spring Boot an: Das Spring Boot basiert vollständig auf dem Spring Framework und dem Ökosystem. Und ich habe in meinem Buch vier Säulen davon benannt, von Spring Boot:
Die erste Säule ist die Verwaltung von Abhängigkeiten. Spring Boot stellt für die Build-Werkzeuge Maven und Gradle einen sehr ausgefeilten Mechanismus bereit, um zueinander passende Versionen von Bibliotheken und Modulen bereitzustellen.
Die nächste Säule ist die automatische Konfiguration. Damit meine ich all die Dinge, die Spring Boot macht, um verschiedene Module des Spring Frameworks für den Endentwickler zu konfigurieren. Sei es das Spring Web MVC Modul, dass automatisch der Web MVC Kontext hochgefahren wird. Für diejenigen, die Web MVC nicht kennen, das ist das Web-Modul des Spring Frameworks. MVC steht für Model View Controller und beschreibt so ein bisschen das Programmierparadigma dieses Moduls. Oder es wird zum Beispiel das JDBC Modul automatisch konfiguriert.
Dann gibt es die Säule der Starter. Ein Starter innerhalb von Spring Boot kapselt die Abhängigkeiten eines bestimmten Themas zusammen mit der automatischen Konfiguration für dieses Thema. Da gibt es dann zum Beispiel den Spring Boot Starter Web MVC für das bereits genannte Web MVC Modul. Die Abhängigkeiten dieses Starters sind all die Dinge, die benötigt werden, um Web MVC zu benutzen. Dazu gehören natürlich die Beans-Module aus dem Spring Framework und das Kernmodul, aber noch ein paar andere Libraries und dazu Konfiguration auf Java-Ebene, die feststellt, okay, alle Klassen, die ich benötige, sind auf dem Klassenpfad. In Spring Boot ist es so, dass - wenn ich diesen Starter benutze - ein eingebetteter Application-Container mitkommt, in dem das Web MVC Modul ablauffähig ist. Das ist entweder Tomcat, Jetty oder Undertow und auch das wird dann automatisch für mich konfiguriert.
Und die vierte Säule ist die Möglichkeit, Dinge extern zu konfigurieren. Extern kann sein über Umgebungsvariablen, über Startup-Parameter oder über Profile.
Michael Vitz: Und die Idee davon ist dann, nehme ich mal an, für den Anwendungsentwickler, der innen auf irgendwelche Konfigurationswerte zugreifen muss, nicht mehr zu wissen, wie die von außen gesetzt wurden, also ob die über Umgebungsvariablen, JNDI oder wo auch immer herkommen. Richtig?
Michael Simons: Genau. Intern steht eine völlig opake Schicht von Konfigurationen zur Verfügung, der nicht ansehbar ist, woher sie denn kommt, schlussendlich.
Michael Vitz: Und ich nehme mal an, diese Konfigurationen überschreiben sich auch mit einer vordefinierten Reihenfolge.
Michael Simons: Natürlich. Es gibt eine dokumentierte, vordefinierte Reihenfolge. Ich glaube, es sind mittlerweile 12 bis 14 unterschiedliche Aspekte, aus denen Konfigurationen herkommen können, und die Reihenfolge ist selbstverständlich definiert und dokumentiert.
Michael Vitz: Genau. Und ich merke mir das immer so ein bisschen mit: Die spezifischste Angabe gewinnt, sozusagen. Also sehr generisch ist irgendwo so ein Default und sehr spezifisch ist es, als Argument übergeben zu werden.
Michael Simons: Ja, genau, das ist eine gute Eselsbrücke.
Michael Vitz: Und man kann dann dazwischen darüber streiten, wo es aufhört.
Michael Simons: Genau.
Michael Vitz: Kommen wir noch mal einen Schritt zurück: Du hast am Anfang gesagt, einer der großen Vorteile von Spring Boot ist es, Abhängigkeiten zu managen. Das heißt also, ich kenne das noch aus Spring-2.5-Zeiten, da hat man sich so ein JAR heruntergeladen und darin waren irgendwelche Bibliotheken und dann hat man die irgendwie händisch zusammengesteckt. Das heißt, das Problem sollte damit gelöst sein?
Michael Simons: Das Problem ist damit gelöst. Ich kann mich auch noch dumpf daran erinnern, dass ich irgendwann mal dieses Über-JAR und irgendwann mal ein Über-POM-File heruntergeladen habe, in dem eine Vielzahl an Modulen steckten, von denen mir damals nicht so ganz genau klar war, was die eigentlich alle machen und wofür ich sie brauche und ich habe es dann einfach immer stumpf mitgeschleppt.
Michael Vitz: Okay.
Michael Simons: Also heute ist es eher so, dass es den Spring Initializer gibt - das ist eine Webseite, die man aufrufen kann - unter start.spring.io und man kann dort die Themen einfach auswählen, die einen interessieren und für jedes dieser Themen - sei es, wie du es erwähntest, Spring Web MVC oder JPA oder nicht-relationale Datenbanken - wird ein Starter in die Liste der Abhängigkeiten für das jeweilige Build-System eingetragen. Und mehr muss man eigentlich nicht an Cargo-Kult betreiben, um Spring und Spring Boot mit den jeweiligen Techniken von Interesse zu benutzen.
Michael Vitz: Das heißt dann aber auch, dieses Abhängigkeitsmanagment managt nicht nur, dass ich kompatible Versionen der Spring-Bestandteile habe, sondern auch tatsächlich externe Bibliotheken, also so etwas wie Hibernate oder was auch immer.
Michael Simons: Genau richtig. Da greifst du jetzt vielleicht sogar schon ein Thema vor, zu dem wir gleich noch kommen werden: Was man beachten muss, wenn man seine Spring Boot-Anwendung aktualisiert, wo es denn vielleicht mal weh tun könnte und wo nicht.
Michael Vitz: Okay. Ist das also doch noch nicht alles komplett magisch gelöst?
Michael Simons: Nein, noch ist nicht alles komplett magisch gelöst. Schön wäre das.
Michael Vitz: Und dann hattest du gesagt… Also dann haben wir ganz viel über Konfiguration gesprochen und ich kenne das auch noch so aus den alten Spring-Zeiten, da musste man am Anfang eine große XML-Datei hinlegen, in der man alle möglichen Beans definiert hat. Das klang jetzt auch so, als wäre das einfacher geworden, kannst du dazu vielleicht noch mal ein bisschen was sagen?
Michael Simons: Die Konfiguration von Spring ist vielleicht nicht unbedingt einfacher geworden ohne Spring Boot. Sie ist auf jeden Fall vielfältiger geworden seit den Zeiten der XML-Dateien. Man kann eine Spring Anwendung immer noch mit XML konfigurieren, wenn man das möchte, man kann aber auch Component-Scanning benutzen. Das ist eine sehr implizierte Form der Konfiguration einer Spring Anwendung. Dort geht man hin und annotiert seine Service Klassen oder seine Klassen, die einen Service repräsentieren oder einen Web-Controller oder einfach nur eine generische Komponente mit verschiedenen Annotationen, sogenannten Stereotypen, und der Spring-Container findet diese Klassen automatisch und instanziiert sie jeweils als Singleton für einen. Das ist die zweite Möglichkeit. Die dritte Möglichkeit ist eine Mischung aus diesem impliziten Mechanismus und einem expliziten Mechanismus per Java-Konfiguration. Dort kann man dann hingehen und Klassen mit dem Stereotyp @Configuration
annotieren und die Methoden dieser Klasse mit @Bean
und diese @Bean
-Methoden liefern dann explizite Instanzen der eigentlichen Service, Controller und was auch immer für Klassen.
Michael Vitz: Das heißt im Grunde kann ich auch heute noch alle diese drei Methoden benutzen?
Michael Simons: Genau!
Michael Vitz: Aber ich muss, wenn ich dich richtig verstanden habe, ja für eine Spring Boot Applikation überhaupt gar nicht mehr so viele Beans selber definieren, weil es da diesen Mechanismus gibt, der das irgendwie für mich automatisch tut?
Michael Simons: Genau, es gibt diesen Mechanismus – du hast es eben auch schon als Magie beschrieben – der von vielen Menschen als magisch bezeichnet wird. In der Regel konfiguriert Spring Boot alle Infrastruktur-Beans für dich. Also du musst nicht hingehen und die Request-Handler konfigurieren. Request-Handler bilden beispielsweise URLs auf Methoden von Klassen ab. Das musst du alles nicht selber konfigurieren. Das macht Spring Boot für dich. Spring Boot richtet auch eine Datenbankverbindung für dich ein, wenn du den entsprechenden JDBC-Starter benutzt. Spring Boot richtet auch einen Hibernate EntityManager für dich ein, wenn du nicht den JDBC-Starter benutzt, sondern den JPA-Starter. Deine eigenen Klassen jedoch, also Controller oder Services, musst du immer noch in irgendeiner Art und Weise konfigurieren.
Michael Vitz: Und diese Starter, wie erkennen die jetzt plötzlich, dass ich doch JDBC benutze? Also was sind so die Mechanismen, dass es da funktioniert?
Michael Simons: Starter wirken magisch, sind es aber nicht. Es gibt so etwas wie das in Java eingebaute Service-Loader-SPI. Ein Service-Provider-Interface. Das wird über einen Schlüssel-Werte-Mechanismus in einer Datei festgelegt. Diese Datei befindet sich im Starter in einem speziellen Verzeichnis, im META-INF
-Ordner eines JAR-Files. Und dort steht unter dem Schlüssel EnableAutoConfiguration
der vollständig qualifizierte Name einer Java-Konfiguration. Und innerhalb dieser Java-Konfiguration stellen die Entwickler des Spring-Frameworks bzw. der Spring Boot Module fest, ob bestimmte Klassen aus Libraries auf dem Klassen-Pfad sind, ob bestimmte externe Bedingungen erfüllt sind, ob Properties gesetzt sind oder nicht und konfigurieren dann die entsprechenden Infrastuktur-Beans.
Michael Vitz: Okay, das heißt ich habe eine ganze Menge an Mechanismen, um zu erkennen, ob ich etwas automatisch tun soll. Und ich nehme mal an, als Entwickler hat man dann theoretisch auch die Möglichkeit, an vielen Stellen sich einfach einzuhängen und es zu ändern oder sogar zu verhindern, dass etwas passiert.
Michael Simons: Genau! Man kann in zwei Richtungen gehen. Dieser Mechanismus zu erkennen, ob Abhängigkeiten erfüllt sind, den können wir natürlich auch nutzen. Wir können eigene Starter für eigene Themen schreiben, das geht natürlich. Und umgekehrt sind diese Mechanismen so widerstandsfähig, dass sie erkennen, wenn ich als Endentwickler automatische Konfiguration überschreiben will. Wenn ich in eine Situation komme, in der es zum Beispiel keine Properties gibt, über die ich von Außen eingreifen kann, sprich es gibt natürlich eine Property, mit der ich eine Datenbankverbindung konfigurieren kann. Und es gibt Properties für die Abbildung von bestimmten Basispfaden auf URLs oder für Übersetzungsdateien. Das kann ich alles über Properties machen. Aber vielleicht gibt es doch die eine oder andere Situation, wo ich etwas im Code machen möchte und wenn ich dann eine Infrastruktur-Bean in den Application-Kontext einbringe, durch einen der Mechanismen, dann wird diese Bean in der Regel ausgewertet, bevor die ganzen Starter ausgewertet werden. Das ist ein ganz wichtiger Aspekt zum Thema Widerstandsfähigkeit von Startern. Zuerst werden alle Beans des Endentwicklers gesucht und dann die Starter halt darauf los gelassen.
Michael Vitz: Also im Grunde derselbe Mechanismus wie bei den Properties. Erst gewinnen die spezifischen, sehr nah definierten von mir, und dann werden sie sozusagen als Fallback eingefügt, wenn die denn gemerged werden.
Michael Simons: Spezifität heißt in dem Fall: Das, was der Endentwickler in den Kontext hineinträgt, hat Vorrang.
Michael Vitz: Dann hast du eben schon diese ganzen Application-Server erwähnt, das kann ich mir jetzt wie vorstellen? Also, ich habe jetzt meine Spring-Boot-Anwendung, sage, ich möchte etwas im Web machen und wie funktioniert das? Dann kommt der Tomcat mit und entpackt sich automatisch, oder wie funktioniert das?
Michael Simons: Guter Punkt! Ja, es kommt ein Tomcat mit oder je nachdem, wenn du lieber Undertow bevorzugst oder Jetty, kannst du Tomcat aus dem Abhängigkeitsmanagement ausschließen und Jetty oder Undertow als Abhängigkeit deklarieren. Das kommt dann mit. Aber du musst es nicht explizit entpacken. Das sind jeweils eingebettete Embedded-Varianten des Application-Container. Wenn ich das richtig in Erinnerung habe braucht Tomcat ein temporäres Verzeichnis, aber das macht Spring Boot bzw. der Embedded-Tomcat automatisch für dich. Und dieser Container wird automatisch so konfiguriert, dass er den Spring-Kontext auf dem Root-Pfad laufen lässt und dass du ihn eigentlich gar nicht wahrnimmst.
Michael Vitz: Okay, das heißt: Meine Spring Boot Applikation hat dann nachher eine ganz normale Main-Methode?
Michael Simons: Genau.
Michael Vitz: Und fährt dann unten drunter diesen Embedded-Server hoch und dann lauscht der halt auf einem Port und nimmt Anfragen entgegen?
Michael Simons: Genau. Du musst noch ein bisschen Zeremonie ausführen, in deiner Main-Methode bzw. in deiner Java-Main-Klasse. Du benötigst zwingend eine Annotation für eine Spring-Boot-Anwendung. Und das ist @SpringBootApplikation
. @SpringBootApplikation
schaltet quasi diese magische Funktion der Autokonfiguration ein, die magische Suche nach Komponenten unterhalb des Packages, in dem sich die Main-Klasse/Main-Methode befindet. Und es gibt noch eine spezielle Run-Application-Methode, die zwingend aufgerufen werden muss, um diesen Mechanismus loszutreten.
Michael Vitz: Ah, okay.
Michael Simons: Ich würde aber gerne noch ein Wort zu den Embedded-Containern sagen.
Michael Vitz: Ja, klar.
Michael Simons: Die Embedded-Container sind vielleicht einer der Gründe, warum Spring Boot oftmals als Microservices-Framework wahrgenommen wird. Es macht es sehr leicht, relativ kleine und kompakte Anwendungen zu schreiben, die irgendetwas im Web machen. Vielleicht eine REST-Schnittstelle zur Verfügung stellen. Es gab mal eine Zeit, da war es ganz en vogue, einen Tweet rauszuschicken mit einer Spring-Boot-Anwendung, die in einen Tweet passt und einen REST-Controller zur Verfügung stellt. Und dann ist man geistig relativ schnell bei Microservices. Aber es ist nicht unbedingt Kernkompetenz von Spring Boot. Es ist etwas, das man sehr gut mit Spring Boot schreiben kann – einen Microservice – aber Spring Boot eignet sich auch genauso gut, um größere, monolithische Anwendungen zu schreiben. Also generell würde ich sogar so weit gehen, dass ich – Stand Heute – keine Spring Anwendung mehr schreiben würde, ohne Spring Boot zu benutzen. Also weder eine Web-Anwendung, noch eine Batch-Anwendung oder auch kein Kommandozeilen-Interface.
Michael Vitz: Ich kann das ganz gut nachvollziehen, weil ich mich noch an die Zeiten von 2.5 XML erinnere. Da hatte man unwahrscheinlich viel Arbeit, um überhaupt die Applikation in dieses minimale Gerüst zu bekommen, damit sie etwas tut. Und das ist mit Spring Boot deutlich eleganter. Also man kann sehr schnell anfangen, sich um den Code Gedanken zu machen, der wirklich Wert schafft und nicht erst einmal drei Tage für Infrastruktur, Bootstrapping vorsehen.
Michael Simons: Absolut richtig.
Michael Vitz: Dann hast du das zwar nicht bei den vier Säulen genannt, aber ich vermute mal, das mir Spring Boot irgendwie auch noch beim Testing hilft?
Michael Simons: Das ist ein schönes Thema. Was, glaube ich, gar nicht so im Bewusstsein ist, ist, dass das Spring Framework auch, damals wie vor 15 Jahren, in Hinblick auf Testing entwickelt worden ist. Und zwar nicht nur auf Testing von Spring-Code selbst, sondern auch auf Testbarkeit von Anwendungscode. Vielleicht war das damals sogar noch offensichtlicher, dass man Anwendungscode frei von Spring-Infrastuktur schreiben kann, weil man ja eh alle Beans mit XML von außen konfiguriert hat. Die Konfiguration von Dingen mit Annotationen, die geht sehr schnell und leicht von der Hand. Aber diese Schnelligkeit und Leichtfüßigkeit erkauft man sich natürlich mit ein paar Sachen. Wie zum Beispiel, indem ich Dependency Injection über Getter und Setter nutze oder halt über Reflection. Oder ich spare es mir, halt einfach Getter und Setter hinzuschreiben, und schreibe @Autowired
oder @Inject
und hänge meine Attribute daran. Dann habe ich nachher natürlich einen Anwendungscode, den ich überhaupt nicht mehr gut testen kann, da ich dann in der Situation bin, dass ich meinen IoC-Container brauche, um das ganze Zeug sinnvoll zu verdrahten.
Wenn ich aber einfach hingehe und nach Best-Practices meinen Anwendungscode schreibe, das heißt, in der Regel frei von Spring-Annotationen Dependencies über Konstruktorparameter injecte, dann rede ich erst einmal gar nicht von Spring, wenn ich von Testbarkeit rede. Dann kann ich meinen Anwendungscode unit-testen. Wenn ich irgendwann dann doch in einen Bereich komme, der ohne Spring nicht mehr gut funktioniert, sprich zum Beispiel den Weblayer, dann bin ich so nahe an der Infrastruktur dran, dass ich halt in der Regel schon annotationsbasierte Mechanismen im Spring-Framework nutze, um URLs auf Methoden abzubilden, weil es einfach komfortabler ist. Dass ich dort halt auch das Framework benötige, um sinnvoll testen zu können. Aber dann rede ich eher von einem Integrationstest gegen das Spring-Framework und da stellt Spring Boot mir auch Hilfsmittel zur Verfügung. Ein Hilfsmittel ist, dass ich für den Test in der Regel keine andere Konfiguration durchführen muss. Wenn ich meine zu testenden Klassen im selben Package wie die Anwendung habe, werden die Tests genauso hochgefahren wie die Anwendung selbst.
Michael Vitz: Okay, das ist schonmal gut, weil ich dann keinen Fehler machen kann, wenn ich die Konfiguration duplizieren müsste. Dann weiß ich nachher nicht mehr, ob die Testkonfiguration …
Michael Simons: Das ist ja immer ein ganz beliebter Fehler, dass der Test sich deutlich anders verhält als die Anwendung selbst, wenn man so etwas macht.
Michael Vitz: Ja.
Michael Simons: Und in einer größeren Spring-Boot-Anwendung kann das natürlich auch schonmal etwas dauern, bis so ein Kontext hochgefahren wird, vor allem wenn es halt der komplette Kontext in allen Schichten ist. Sprich, von der Datenbank über die Services bis hin ins Web, und dort gibt es etwas, das nennt sich Test Slices, die die horizontalen Schichten meiner Anwendung explizit testen können. Zum Beispiel den Web-Layer oder auch den Datenbank-Layer, um von beiden Seiten zu kommen.
Michael Vitz: Das heißt, wenn ich Spring brauche, zum Beispiel, um Integrationstests zu machen, dann kann ich so einen Spring-Application-Kontext sehr bequem in den Tests hochfahren.
Michael Simons: Genau.
Michael Vitz: Und um schneller zu werden, kann ich mir sozusagen so einen Teil-Kontext hochfahren, der dann weiß, was alles zum JDBC oder zur Datenbank gehört, und der fährt dann nur Beans hoch, die mit Datenbanken in Verbindung stehen.
Michael Simons: Genau, so ist es.
Michael Vitz: Ah, okay.
Michael Simons: Und in einem Test auf höherer Ebene kannst du dann natürlich all die Dinge mocken – mit Mockito oder ähnlichem. Mockito wird out of the box unterstützt, sodass du halt Services in deinen Web-Layer reininjecten kannst, ohne dass sie tatsächlich vorhanden sein müssen.
Michael Vitz: Okay. Und das letzte, was mir immer noch ins Auge springt, wenn man in die Dokumentation guckt, ist dieses “Production-ready“, was sie, glaube ich, auch sehr groß in der Dokumentation stehen haben. Was verbirgt sich denn dahinter?
Michael Simons: Unter Production-ready steht in der Dokumentation insbesondere das Spring Boot Actuator. Spring Boot Actuator ist ein Spring-Boot-Modul – offensichtlich – kein Spring-Framework-Modul, dass eine Spring-Boot-Anwendung um verschiedene Stellschrauben bereichert. Zum einen gehören dazu die Actuator Endpoints, das sind Management Web-Endpunkte oder JMX-Endpunkte, die dazu dienen, verschiedene Dinge aus der Anwendung heraus zu lesen. Zum Beispiel: Welche Beans sind vorhanden? Welche Konfiguration wurde gezogen? Wir haben eben über Spezifitäten gesprochen, dort kann man auslesen, warum welche Konfiguration jetzt gezogen wurde oder nicht. Aber sie ermöglichen auch einen Eingriff in eine Spring-Boot-Anwendung. Zum Beispiel setzen des Logging-Levels und dergleichen mehr.
Michael Vitz: Okay, das heißt, im Grunde ist alles - in Anführungszeichen - was sich darunter versteht, Monitoring- und Konfigurationsmöglichkeiten zur Laufzeit.
Michael Simons: Genau. Zum Monitoring gehört auch noch so etwas wie Metriken dazu. Das stellt Spring Boot Actuator auch zur Verfügung.
Michael Vitz: Ah, okay. Das heißt, das ist einfach so ein bisschen der Gegenpol zu diesen ganzen Management-Dingen, die ein Application-Server auch mitgeliefert hat. Plus diese Erweiterung um das Web so ein bisschen auch, oder?
Michael Simons: Ich glaube, das könnte man so sagen, ja.
Michael Vitz: Ich bin immer etwas unsauber, was das angeht. Ich hoffe die Hörerinnen und Hörer wissen, was ich meine. Und nicht, was ich gesagt habe, wie es ein guter Kollege immer auszudrücken pflegt. Du hast gesagt, es gibt dieses start.spring.io, dann haben wir jetzt ein fertiges - nein, nicht ein fertiges - dann haben wir gesagt, wir wollen eine Spring-Boot-Anwendung haben und haben vielleicht noch ein, zwei Starter hinzugeklickt. Und dann haben wir unseren eigenen Code entwickelt. Und wie deployen wir denn jetzt so eine Spring-Boot-Anwendung, wenn wir keinen Application-Server brauchen?
Michael Simons: Also nachdem wir die Anwendung auf dem Spring Initializer zusammengeklickt haben, können wir uns noch entscheiden, ob wir Maven oder Gradle als Build-Tool benutzen und beide Build-Werkzeuge sind so konfiguriert bzw. benutzbar, dass ich mit beiden ein Executable- oder fat-JAR generieren kann. Dieses Executable-JAR beinhaltet einen speziellen Boot Mechanismus, der die Hauptanwendungsklasse kennt. Das ist die Klasse, die mit @SpringBootApplication
annotiert ist und sowohl die Main-Methode enthält, als auch den Library-Pfad. Dieser Library-Pfad steckt in dem Jar-File mit drin. Das heißt, die Anwendung wird nicht als ein kleines JAR-File ausgeliefert, sondern als ein JAR-File, das weitere JAR-Files enthält und dementsprechend groß werden kann, wenn halt viele Libraries und Starter zusammengeklickt worden sind. Und dieser Boot-Loader sorgt dafür, dass der Klassen-Pfad entsprechend aufgebaut wird und die Anwendung so startbar ist.
Michael Vitz: Das heißt es ist so ein bisschen ähnlich, wie man das in Maven zum Beispiel mit diesem Shade Plugin gemacht hat, wo man einfach alle Klassen entpackt. Das tun die aber nicht, sondern sie entscheiden sich dafür, die Fremd-Bibliotheken einfach, wie sie sind, mit zu paketieren und schreiben halt einen eigenen Class-Loader.
Michael Simons: Genau. Du kannst halt so ein JAR-File auch mal aufmachen und reinschauen und dort findest du in dem Ordner, ich glaube ROOT-INF/lib
, alle benutzten Libraries.
Michael Vitz: Das heißt, am Ende habe ich in der Regel ein relativ großes Artefakt, das dafür dann aber stand alone fähig startbar ist, indem ich einfach java -jar meinJarName
eingebe.
Michael Simons: Genau. Das ist der Default-Weg. Es gibt natürlich weiterhin die Möglichkeit, eine Spring-Boot Anwendung auch als WAR-File zu deployen. Auch die Möglichkeit kann man bereits auswählen im Spring Initializer und dieses WAR-File kann dann in einem Tomcat oder in einem anderen Application-Container wie eine ältere Spring-Anwendung deployed werden.
Michael Vitz: Das heißt auch für Benutzer, die noch einen klassischen Betrieb haben, der ihnen Tomcat zur Verfügung stellt ist Spring Boot eine Alternative. Dann muss man da halt einfach nur anders paketieren.
Michael Simons: Genau, man muss es ein bisschen anders paketieren und es gibt noch ein zwei Sachen, die man berücksichtigen muss, damit der Lebenszyklus des Spring-Frameworks entsprechend berücksichtigt wird.
Michael Vitz: Genau, weil er ja offensichtlich auch nicht die gleiche Main-Methode benutzt?
Michael Simons: Genau, weil nicht die gleiche Main-Methode genutzt wird. Da muss man dann etwas machen. Aber das sind drei Zeilen, die man noch reinbringen muss.
Michael Vitz: Ja cool! Jetzt hast du am Anfang ja mal dein Buch erwähnt und das heißt ja Spring Boot 2 Buch oder eigentlich heißt es, glaube ich, Spring Boot 2.
Michael Simons: Ja.
Michael Vitz: Ich sage Buch immer noch dazu, da es nunmal ein Buch ist. Das heißt, es muss auch eine Welt vor ‘2’ gegeben haben. Kannst du vielleicht mal kurz sagen, bei welcher Version wir jetzt heute etwa sind, und was die größten Unterschiede sind, die es von der vorherigen Version zu dieser zweiten Version gibt?
Michael Simons: Na klar. Also wir sind ganz konkret – Stand heute am 28. Mai – bei Spring Boot 2.0.2. Seit Spring Boot 2.0.1. ist Spring Boot mit Java 10 kompatibel. Und seit Spring Boot 2 – wann ist es rausgekommen? 30. März?
Michael Vitz: Ja, das könnte hinkommen. Kurz nach Java 9 wäre das dann gewesen.
Michael Simons: Genau. Seit Spring Boot 2 ist Spring-Framework 5 Grundlage von Spring Boot. Damit kamen etliche größere Neuerungen. Eine der größten Neuerungen ist zum Beispiel, dass Spring Boot 2 Java 8 zwingend voraus setzt. Also falls Ihr oder du noch Anwendungen habt – Entschuldigung, Laufzeitumgebungen - in denen nur Java 6 oder 7 verfügbar ist, dann kannst du nicht auf Spring Boot 2 aktualisieren. Du musst mindestens Java 8 im Einsatz haben. Aber mit Java 8 konnten halt einige Dinge im Spring-Framework selbst vereinfacht werden. Zum Beispiel konnte die ganze Logik entfernt werden, die dafür sorgt, dass Dinge sowohl mit Java 8, als auch mit älteren Versionen laufen. Die Spring-Entwickler können jetzt Java 8 Features im Framework selber benutzen. Und die größte Neuerung in Spring 5 ist wohl diese ganze reaktive Story. Dort geht es um das Thema Reactive Programming. Das wird im Spring Framework mit Project Reactor per Default realisiert.
Michael Vitz: Und da geht es, also in der Endausbaustufe sozusagen, auch noch so um non-blocking I/O und einfach dafür zu sorgen, dass Daten wie so ein Fluss durch meine Anwendung gehen, und dass ich möglichst nicht blockiere.
Michael Simons: Genau. Das hört natürlich nicht in der Web-Schnittstelle auf, sondern geht im idealsten Fall bis zur Persistenz hinunter.
Michael Vitz: Und ich kann auch kurz etwas dazu sagen: Also mit einer der Neuerungen, die durch das Java 8 basierte hineingekommen ist, ist dass an manchen Stellen sich auf die aus Spring bekannte Vererbungshierarchie eine Ebene sparen kann. Also, häufig hat man das in Spring, glaube ich, so gehabt, dass man ein Interface hatte und da hat man einen Adapter, der alle Interface-Methoden schonmal leer implementiert hat. Und an vielen Stellen machen sie das jetzt über die Default-Methoden, die mit Java 8 dazu gekommen sind.
Michael Simons: Genau.
Michael Vitz: Aber jetzt hat sich bestimmt nicht nur die Spring-Version erhöht, sondern wahrscheinlich hat Spring Boot ja auch ein bisschen selbst gemacht. Haben die auch noch größere Dinge, die du für erwähnenswert hältst, bei dem Weg auf Spring Boot 2 umgesetzt?
Michael Simons: Es wurde in meinen Augen ganz viel Housekeeping betrieben. Wir haben gerade gesagt, dass das Thema reaktive Programmierung nicht im Web aufhört, aber an der Webschnittstelle fängt es zumindest einmal sehr sichtbar an. Es gab verschiedene Dinge in Spring Boot, die sehr explizit auf Servlet-Umgebungen ausgerichtet waren. Und dort musste eigentlich zwangsweise Housekeeping betrieben werden, um das Servlet-basierte Programmierparadigma weiter zu unterstützen; parallel zum reaktiven Programmierparadigma, was nicht Servlet-basiert ist. Dort wurden sehr viele Packages intern neu benannt, umstrukturiert und dergleichen mehr.
Michael Vitz: Wir hatten ja über Actuator gesprochen. Ich glaube, da hat sich dann bei ‘2’ auch nochmal eine ganze Menge getan. Weil das ist ja auch so, das ist das größte Spring-Boot-Kernmodul, wo noch viel Logik drin ist außerhalb von Konfigurationen und Default-Properties, richtig?
Michael Simons: Das ist richtig. Erstmal haben sich Namen geändert. Es haben jetzt einige Endpunkte bessere Namen bekommen. Der Trace
-Endpunkt heißt jetzt HTTP-Trace
. AutoConfig
ist ja irgendwie Conditions
geworden. Es gibt einen neuen Basis-Pfad. Also, vorher befanden sich diese Endpunkte alle unter dieser Root-URL, jetzt befinden die sich unter /actuator
. Genau, und, was deutlich wichtiger ist, ist die Tatsache, dass Actuator jetzt technologieunabhängig ist. Habe ich den Spring Boot Actuator vorher benutzt, habe ich auch immer zwangsweise Spring Web MVC mitbenutzen müssen bzw. zumindest auf dem Klassenpfad gehabt, auch wenn ich eigentlich vielleicht meine Web-Schnittstelle zum Beispiel mit JAX-RS realisiert habe, kam dann on-top Web MVC. Bzw. ich hatte Web MVC dabei, auch wenn ich vielleicht gar keine Web-Anwendung gebaut habe.
Michael Vitz: Ah, okay.
Michael Simons: Dort gibt es jetzt eine Abstraktion, die es ermöglicht, dass ich Actuator sowohl auf JAX-RS laufen lassen kann, in einem reaktiven Umfeld, weiterhin natürlich auf Spring Web MVC und auch im JMX Umfeld. Davon merkt man in der Regel nichts, solange man nicht eigene Actuator-Endpunkte geschrieben hat. Wenn man das getan hat, muss man die jetzt migrieren.
Michael Vitz: Ja, ok. Ich meine, ein bisschen Migration ist immer, glaube ich, und ich meine auch gesehen zu haben, dass die Migrationsbeschreibungen zumindest da ganz gut sind. Die sagen einem eigentlich relativ gut, was man tun muss.
Michael Simons: Das ist richtig. Was in Actuator sonst noch hinzukommt, ist das Thema Security und das ist eine ganz gute Überleitung zu Updates von Libraries. Aber zuerst einmal: Actuator Security, da wurde vorher relativ viel Aufwand und Magic betrieben, um diese Endpunkte abzusichern. Sprich: Da war Security-in-place, damit sensitive Informationen nicht an die Außenwelt gelangen. Das gibt es in dieser Art und Weise nicht mehr. Wenn ich jetzt Spring Actuator auf dem Klassenpfad habe, gibt es dafür keinen Mechanismus, der dafür sorgt, dass die abgesichert werden. Den muss ich mir extra reinholen durch das Spring-Security-Modul. Die Spring Boot Actuator haben jetzt das Konzept von enabled und exposed. Da sind jetzt alle Actuator-Endpunkte, bis auf den Shutdown-Endpunkt enabled per default und nur Info und Health sind exposed per default. Exposed auf Webseite und auf JMX-Seite. Und wenn ich die anderen sichtbar machen möchte im Web, kann ich das einzeln tun oder alle auf einmal. Aber ich muss es bewusst tun, sodass ich mich hinstellen muss und sage, okay, ich möchte jetzt den Beans-Endpunkt nach außen verfügbar machen, da kann dann halt auch jeder reingucken, solange ich mich nicht selbst um Security kümmere.
Michael Vitz: Das finde ich gut. Ich habe in 1.5er-Applikationen häufig immer erst einmal alles ausgestellt, um es danach wieder selektiv anzustellen, weil man dann doch nicht so genau weiß, was da alles an ist.
Michael Simons: Ja.
Michael Vitz: Da ist manchmal tatsächlich ja Whitelisting etwas sicherer, wenn es um Security-Themen geht.
Michael Simons: ich bin auch ein Freund von Whitelisting, by the way.
Michael Vitz: Und was bei mir dann immer noch häufig im Kopf herumgeschwirrt ist, weil dafür aus dem Spring-Umfeld, glaube ich, auch viel Werbung gemacht wurde, war dieses Micrometer, das immer mit Spring Boot 2 erwähnt wurde. Was ist das?
Michael Simons: Micrometer ist ein neues Projekt, das auch von Pivotal gesponsert wird. In Micrometer geht es um multidimensionale Metriken. Der Spring Boot Actuator-Starter hat schon immer Metriken über die Anwendung ausgegeben. Sowohl Systemmetriken als auch Anwendungsmetriken, aber hat das hierarchisch getan. Sprich, ich habe alle Metriken zu einem bestimmten Request, HTTP-Request zum Beispiel, gesehen und das unter einem Hierarchie-Counter. …
Michael Vitz: So etwas wie Status Codes, irgendwie 200, 400.
Michael Simons: Status Codes, Endpoint usw.
Michael Vitz: Ah, ok.
Michael Simons: Das ist eine hierarchische Metrik, eine sogenannte Taxonomie, wenn man so möchte, und diesen Begriff aus der Biologie benutzen will. Der skaliert aber nicht, wenn ich mich in einer Microservices-Welt befinde. Wenn ich zu diesem Counter von HTTP-Requests zum Beispiel noch die Instanz hinzufügen möchte in meiner Anwendung oder vielleicht die Region, in der diese Instanz läuft. Dann habe ich nachher eine sehr längliche Taxonomie, die ich vielleicht nicht unbedingt in meinem Monitor-Dashboard pflegen möchte. Und da setzen multidimensionale Metriken an. Da spreche ich dann nicht von einem einzelnen Request-Counter, sondern von einem Counter über alle HTTP-Requests und versehe diese dann mit einem Tag. Und dieser Tag kann dann zum Beispiel die URL, aber auch die Anwendungsinstanz, die Region und dergleichen sein. Das ist ein Aspekt von Micrometer.
Der andere Aspekt ist, dass ein Mechanismus geschaffen worden ist, mit dem man sehr viel leichter als in Spring Boot 1 seine eigenen, Domain-spezifischen Metriken in die Anwendung hereinholen kann. Zum Beispiel, wie viele Produkte habe ich in der letzten Stunde verkauft? Oder wie viele Kunden sind kurz vor Schluss beim Bestellprozess abgesprungen oder dergleichen. Da hat Micrometer viele Ideen von Dropwizard Metrics aufgegriffen und sie in einer Form bereitgestellt, dass sie sehr schön innerhalb einer Spring-Boot-Anwendung nutzbar sind, aber auch stand alone. Sprich, wenn ich das machen möchte, binde ich mich in meiner Domain-Logik auch wiederum nicht an den Spring-Kontext, sondern bleibe in Isolation und kann weiterhin in Isolation testen.
Michael Vitz: Das heißt, Micrometer ist erst einmal eigentlich von Spring Boot unabhängig, weitestgehend und auch irgendwie herstellerneutral, was das dahinter angeht. Also ein bisschen so etwas wie dieses Simple Logging Facade, ist da so ein bisschen die Idee von Micrometers?
Michael Simons: Genau. Es ist also nicht nur Spring-unabhängig, sondern auch Monitoring-System-unabhängig. Man kann es für Monitoringsysteme wie Prometheus, für Netflix Atlas nutzen und dergleichen. Es ist ebenso Grundlage für die Metrics-Endpunkte im Actuator. Auch dort setzt es einen Exportmechanismus in Gange, aber das merke ich nicht als Benutzer dieses Systems.
Michael Vitz: Das ist ja schon ganz cool. Das ist wieder eine Stelle, wo man sich weniger direkt an einen sehr speziellen Hersteller koppelt; man koppelt sich jetzt natürlich an dieses Micrometer-Produkt.
Michael Simons: Genau richtig.
Michael Vitz: Aber das ist ja auch Open Source.
Michael Simons: Ja, aber da gilt das Gleiche wie an vielen anderen Stellen: Solange ich mich nicht dafür entscheide, wirklich alles selber zu machen, muss ich mich an irgendetwas binden.
Michael Vitz: Ja, klar. Und dann bin ich ja häufig auch noch mit Themen auf Sprachebene unterwegs. Jetzt weiß ich nicht, Kotlin ist total im kommen, wir haben jetzt Java 9, wir haben auch schon Java 10, im September kommt Java 11. Was ist da so ein bisschen die Idee? Oder gibt es da Einflüsse, die Spring Boot betreffen?
Michael Simons: Ich kann dir die Frage nach Einflüssen jetzt gerade so aus dem Stegreif nicht beantworten. Was meinst du damit?
Michael Vitz: Ich meinte eher, ob Spring Boot diese Dinge so ein bisschen aufgreift. Also gibt es etwas, was mir speziell hilft, wenn ich Kotlin mache, oder benutze ich dann Spring wie ich jede andere Java-Abhängigkeit auch aus Kotlin benutzen würde?
Michael Simons: Okay. Gut. Für Kotlin gibt es spezielle Erweiterungen im Spring Framework, um Beans zu deklarieren. Das heißt, wir haben mindestens die vierte Variante, um einen Application-Kontext mit Inhalt zu befüllen. Dort gibt es eine domain-specific language, eine eigene DSL, um Beans ohne Annotationen zu erzeugen und zu referenzieren. Es gibt Module, um Jackson weiter zu benutzen mit Data Classes und dergleichen. Und wenn wir im Bereich Java bleiben, kann ich dir sagen, dass Spring Boot 2-Anwendungen mit Java 9 kompatibel sind, Spring Boot 2 auch gegen Java 9 getestet wird und seit Spring Boot 2.0.1 ist das ganze System auch mit Java 10 kompatibel, auf dem Klassenpfad wohlgemerkt.
Michael Vitz: Okay. Das heißt, auch da hat man jetzt die Chance, diese regelmäßigen Java-Zyklen mitzunehmen, weil die Leute das bei Spring und bei Spring Boot auf dem Schirm haben und sich zeitnah darum kümmern, dass das alles funktioniert.
Michael Simons: Genau. Aber es wird in Zukunft deutlich schwieriger werden zu sagen, so wie wir jetzt die Situation haben: Spring 4.3 ist für Java 8 und früher geeignet, Spring 5 brauche ich mindestens Java 8 für. Das wird in Zukunft deutlich fließender sein, als es jetzt ist.
Michael Vitz: Ja, klar. Ich meine, das ist einfach der Einfluss, den die schnelleren Java-Releases haben und das ist bestimmt auch eine Menge Arbeit für die Maintainer von den ganzen Spring-Projekten.
Michael Simons: Aber können wir vielleicht noch mal auf das Thema Updates kommen?
Michael Vitz: Ja, klar. Wenn es da etwas Interessantes gibt, dann heraus damit.
Michael Simons: Ja, genau. Wir haben eben das Stichwort Security schon angesprochen und ganz am Anfang haben wir über das Thema Verwaltung von Abhängigkeiten gesprochen. In den letzten zwei Monaten habe ich weniger Probleme gehabt, Spring-Boot-Anwendungen von 1 auf 2 zu aktualisieren, weil sich in Spring Boot Dinge geändert hätten, sondern ich habe eher immer Probleme mit den Abhängigkeiten gehabt. Wenn ich einem Framework oder einem Projekt vertraue, Abhängigkeiten für mich zu verwalten, muss ich auch damit leben, dass irgendwann mal auch Abhängigkeiten hochgezogen werden und das ist mit Spring Boot 2, beispielsweise mit Spring Security, der Fall. Dort gibt es auch ein Upgrade von 4 auf 5. Dort hat sich einiges geändert, zum Beispiel der Password-Storage-Mechanismus wurde aktualisiert.
Michael Vitz: Stimmt, ich erinnere mich.
Michael Simons: Und das sind dann Updates, wo man in der Regel auch aktiv tätig werden muss. Die Default-JPA-Implementierung mit Spring Boot 2 ist Hibernate 5.2. Auch dort muss man gegebenenfalls etwas tun. Das ist ein Aspekt, den man im Auge behalten sollte, wenn man sich auf das Abhängigkeitsmanagement von Spring Boot verlässt.
Michael Vitz: Das heißt, das lohnt sich dann auf jeden Fall, den Migration Guide zu lesen und da auch ein bisschen Zeit einzuplanen? Also das ist wahrscheinlich nicht komplett so, man zählt nur die Versionsnummer hoch und alles funktioniert, sondern man braucht einfach einen kleinen, aber gewissen Arbeitsanteil?
Michael Simons: Genau. Also bei Major Upgrades wie bei 1 auf 2 ist das auf jeden Fall eine Maßnahme, die man tun sollte, ich würde das aber auch bei Minor Updates in der Regel mal durchschauen. Bei diesem Major Upgrade gibt es ansonsten einige Sachen bezüglich Konfiguration zu beachten. Dort haben sich Namen von Properties geändert. Aber dort gibt es den Properties Migrator. Das ist ein Modul, das man während der Migration auf dem Klassenpfad haben kann, das automatisch intern diese Property-Namen, sofern möglich, migriert, aber Warnungen dafür ausloggt. Und dann sieht man relativ schnell: Muss ich dort tätig werden, habe ich dort noch Lücken? Und das Schöne an diesem Modul ist, dass es einem genau sagt, aus welcher Quelle diese Properties kommen. Das heißt, es schaut nicht nur auf irgendwelche Dateien, die vielleicht Teil des Artefaktes sind, sondern schaut die Situation an, wie sie beim Start der Anwendung ist. Sprich, es berücksichtigt Konfigurationsdateien, die Teil des Artefaktes sind, das gestartet wird, Teile der Konfiguration, die vielleicht von dem Konfigurations-Server kommt, aber auch Dinge aus der Kommandozeile und aus Umgebungsvariablen und sagt dann genau, aus welcher Ecke vielleicht jetzt genau die nicht mehr unterstützte Eigenschaft kommt.
Michael Vitz: Das ist natürlich echt cool, weil es einem viel Arbeit nachher erspart, herauszusuchen, wer da jetzt doch noch den alten Property-Namen setzt.
Michael Simons: Genau.
Michael Vitz: Gut. Dann möchte ich mit der simpelsten Frage des Tages enden. Wir haben ja vorhin schon so ein bisschen besprochen - und zwar die Frage: Wieviel Spring muss man denn jetzt deiner Meinung nach können oder kennen, um Spring Boot benutzen zu können? Weil beides ja irgendwie ineinander übergreift, und wahrscheinlich kann man da jetzt auch unterschiedlicher Meinung sein, aber es geht einfach nur mal darum, was so deine Meinung dazu ist.
Michael Simons: Man kann den Spring Initializer benutzen, um sehr schnell skalierbare “Hello World”-Anwendungen zu schreiben. Also, man ist sehr schnell an einer Stelle, an der man eine reaktive, nicht blockierende Anwendung hat, die aus einem Data Store, der halt auch Non-Blocking adressierbar ist, wie zum Beispiel Mongo, irgendetwas ausliest und als REST-Schnittstelle zur Verfügung stellt. Dafür muss ich kaum Spring können, dazu muss ich nicht wissen, wie der IoC-Container funktioniert. Ich muss auch nicht unbedingt eine Ahnung von Dependency Injection haben. Ich kann also auch auf dieser Basis weitergehen und meinen Anwendungscode schreiben und versuchen, ihn irgendwie in meine Anwendung hineinzubringen. Ich glaube, man kommt da sogar ziemlich weit mit, endet aber relativ schnell an einer Stelle, wo man Spring vielleicht nicht so benutzt, wie man es in einer modernen Spring-Anwendung tun sollte.
Ich mag Spring sehr gerne; würde ich das nicht tun, wäre es irgendwie eine dumme Idee gewesen, mich über ein Jahr mit einem Buch damit zu beschäftigen, aber ich möchte es in meinen Projekten eigentlich gar nicht sehen. Ich möchte irgendwo ein Package, ein Java-Package oder ein Kotlin-Package haben, in dem ich meine Konfiguration aufschreibe, in der Regel mittlerweile sehr explizit, und ansonsten möchte ich mich von Spring in meiner Domäne eigentlich befreien.
Michael Vitz: Klar.
Michael Simons: Und um das zu können, muss ich eine gewisse Vorstellung davon haben, wie Dinge ineinander greifen. Ich muss eine Vorstellung davon haben, dass es in der Regel Properties gibt, mit denen ich Dinge so konfigurieren kann, dass sie sich so verhalten, wie ich es mir wünsche. Und wenn es das nicht gibt, gibt es in der Regel immer einen offiziellen Weg, Dinge zu überschreiben. Sobald ich aber an eine Stelle komme, an der ich gegen das Framework arbeiten muss, sei es, indem ich wahllos Infrastrukturklassen überschreibe und eine Vielzahl von Annotationen an meine Domain schreiben muss, damit irgendwie irgendetwas passiert, arbeite ich gegen das Framework. Und so weit würde ich es gar nicht erst kommen lassen. Das ist der Moment, in dem ich sage: Beschäftigt euch ein bisschen damit, wie Spring im Inneren funktioniert, lest die Dokumentation von Spring Boot oder auch mein Buch. Ich würde noch nicht einmal unbedingt so sehr auf die Guides schauen. Die sind sehr praktisch, um einzelne Themen zugänglich zu machen, aber sie helfen in der Regel nicht, um zu verstehen, was passiert. Dort würde ich tatsächlich auf die Dokumentation schauen.
Michael Vitz: Das heißt, es ist ein bisschen - jetzt kommt so eine Phrase - wie bei ganz vielen Themen: Es bietet eine Abstraktion mit der man sehr gut arbeiten kann, mit der man sehr weit kommt und man muss vielleicht irgendwie erahnen können, wann der Punkt kommt, an dem man in diese Abstraktion eine gewisse Tiefe hineinschauen muss.
Michael Simons: Genau.
Michael Vitz: Ich glaube, das ist ganz gut, darauf können - wir beide zumindest - uns ganz gut einigen.
Michael Simons: Absolut.
Michael Vitz: Super. Haben wir noch etwas vergessen, was du gerne sagen möchtest, was hier noch hineinpasst?
Michael Simons: Ich glaube, wir haben uns jetzt eine ganze Zeit lang über eine große Bandbreite an Themen unterhalten. Ich habe von meiner Stelle aus alles gesagt, was ich sagen wollte. Ich möchte mich ganz herzlich für die Zeit bedanken, die ich hier verbringen durfte.
Michael Vitz: Genau das wollte ich sagen, ich wollte mich bei dir bedanken, dass du dich so freiwillig gemeldet hast, hier mit mir dieses Thema zu beackern. Ich hoffe, auch euch hat es gefallen und ihr schaltet dann bei der nächsten Episode wieder ein, wenn es ums nächste Thema im INNOQ-Podcast geht. Danke fürs Zuhören.