Suche
Java-Entwicklung mit Spring – ganz einfach

Spring Boot – was ist das, was kann das?

Eberhard Wolff

©Shutterstock.com/Kichigin

Das Spring-Framework ist angetreten, um die Entwicklung von Enterprise-Java-Anwendungen deutlich zu vereinfachen. Spring Boot ist eine neue Etappe auf diesem Weg – und integriert außerdem Groovy und eingebettete Server in dieses Angebot. So bleibt das Spring-Ökosystem auch in Zukunft interessant.

Listing 1 ist das schon fast klassische Beispiel für die kürzeste Spring-Boot-Anwendung. Auch wenn es nicht so aussieht: Das ist Groovy-Code, und die Klasse ist auch tatsächlich vollständig. Es fehlen also auch keine import-Statements. Die Klasse ist als @RestController deklariert und reagiert dann wegen des @RequestMappings auf den URL „/“. Sie gibt dann als Inhalt der HTTP-Response den String „hallo“ zurück.

Was muss man nun üblicherweise tun, um diese Klasse auch tatsächlich auszuführen? Nun, man benötigt verschiedene abhängige Bibliotheken, wie beispielsweise das Spring-Framework. Und dann natürlich einen Web-Server, in dem die Anwendung auch deployt werden muss. Voraussetzung ist meistens, dass die Anwendung als WAR-Datei vorliegt. Außerdem benötigt man typischerweise auch ein Build-System, das die WAR-Datei erstellt.

Nicht so mit Spring Boot: Es reicht einfach der Aufruf spring run Example.groovy, um die Anwendung laufen zu lassen. Wie ist das möglich? Nun, Spring Boot untersucht zunächst die Groovy-Klasse und stellt fest, welche Elemente genutzt werden. Im Beispiel sind dies die Annotationen @RestController und @RequestMapping – es handelt sich also offensichtlich um eine Web-Anwendung. Nun erzeugt Spring Boot die dafür notwendige Umgebung:

  • Die imports für die Annotationen werden von Spring Boot ergänzt.
  • Ebenso werden die notwendigen Bibliotheken – in diesem Fall also beispielsweise Spring – geladen.
  • Schließlich wird ein Servlet-Container gestartet, in dem die Anwendung ablaufen kann.

Spring Boot macht sich zunutze, dass Groovy eine dynamische Sprache ist. So können beispielsweise imports ergänzt werden. Durch Spring Boot wird es also wesentlich einfacher, eine Groovy-Anwendung, die das Spring-Framework nutzt, zu entwickeln und laufen zu lassen. Neben Web-Anwendungen unterstützt Spring Boot auch zahlreiche andere Arten von Applikationen – beispielsweise RabbitMQ- oder JMS-Anwendungen. Unter [1] finden sich die Beispiele in Groovy für die verschiedenen Technologien. Nach der Installation von Spring Boot kann man also gleich loslegen. Diese Installation ist recht einfach – sie wird unter [2] näher beschrieben.

@RestController
public class Example {

@RequestMapping(„/“)
public String hallo() {
return „hallo“;
}

}

Und was ist mit Java?

Bei Java ist die Nutzung von Spring Boot grundlegend anders: Es gibt ein recht einfaches pom.xml für das Maven-Build-System, das Abhängigkeiten zu Spring Boot und vor allem den Spring Boot Startern enthält (siehe Listing 2). Alternativ können natürlich auch moderne Build-Systeme – also Gradle –  verwendet werden [3]. Die Abhängigkeiten zu Spring Boot ziehen nun alle benötigten Libraries und auch einen eingebetteten Tomcat-Server nach und stellen so eine vollständige Laufzeitumgebung zur Verfügung. Der Controller aus Listing 1 ist zwar eigentlich für die Groovy-Version von Spring Boot gedacht – aber da der Code auch valides Java ist, kann er ebenso in der Java-Variante laufen. Die import-Statements sind dann natürlich zu ergänzen. Dennoch gibt es ein Problem: Wie startet man den Controller? Das spring-Kommando funktioniert leider nur für Groovy-Skripte.

Lesen Sie auch: Eine frühlingshafte Lösung für Microservices: Spring Boot

Dazu ist Java-Code der Code in Listing 3 notwendig – dieses Mal sind im Listing die eigentlich notwendigen import-Statements nicht dargestellt worden. Die Klasse ist im Wesentlichen eine Spring-Konfiguration – gekennzeichnet durch die Spring-Annotation @Configuration. Dank @ComponentScan werden für  alle Klassen, die Spring-Annotationen haben, Spring Beans erzeugt – wenn sie in einem Subpackage dieser Klasse definiert sind. Also müsste der Controller aus Listing 1 in einem Subpackage unterhalb der Konfiguration aus Listing 3 definiert werden, so dass die @Controller-Annotation aus Listing 1 ausgewertet wird. Die einzige Spring-Boot-spezifische Annotation in der Konfiguration ist @EnableAutoConfiguration. In der main-Methode wird nun mithilfe der Spring-Boot-Klasse SpringApplication eine Anwendung mit dieser Konfiguration gestartet.

Nun setzt Spring Boot wegen der @EnableAutoConfiguration-Annotation Mechanismen in Gange, die abhängig von der Umgebung bestimmte Spring Beans erzeugen. Beispielsweise gibt es eine transitive Abhängigkeit von dem spring-boot-starter-web-Modul aus dem pom.xml zu einem eingebetteten Tomcat-Server. Dieser Server wird dann durch die Annotation gestartet– und zwar durch das Spring-Framework, schließlich wird er ja auch mit Spring-Mechanismen konfiguriert. Ähnlich werden dann die notwendigen Komponenten aus dem Spring-Framework instanziiert und konfiguriert – also die komplette Spring-Web-Infrastruktur.

Dieser Ansatz entspricht dem Paradigma „Convention over Configuration“. Wenn bestimmte Klassen im Pfad enthalten sind – also beispielsweise die Klassen des Tomcat-Servers – so werden die passenden Spring Beans erzeugt, also eben beispielsweise der Tomcat-Server. Gibt es die passenden Beans aber wegen einer manuellen Konfiguration schon, so werden sie nicht erzeugt. Dadurch kann der Nutzer entweder die von Spring Boot vorgegebene Konfiguration nutzen oder eine eigene zur Verfügung stellen. Genutzt werden dazu die neuen Spring-Annotationen aus 4.0 wie @ConditionalOnClass und @ConditionalOnMissingBean, mit denen es möglich ist, Spring-Beans nur dann erzeugen zu lassen, wenn bestimmte Klassen vorhanden und bestimmte Beans noch nicht definiert worden sind.

<project ...>
  <modelVersion>4.0.0</modelVersion>
    <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-samples</artifactId>
      <version>0.5.0.M4</version>
    </parent>
    <artifactId>myapp</artifactId>
<packaging>jar</packaging>
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
</dependencies>
<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
   </plugins>
 </build>
<!-- repositories und plugInRepositories entfernt -->
</project>
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Main {

public static void main(String[] args) throws Exception {
SpringApplication.run(Main.class, args);
}
}

 

Für die Entwicklung wird so der Web- oder Application Server obsolet: Der Entwickler startet einfach ein Java-Programm. Kein Einpacken in eine WAR-Datei, kein erneutes Deployen, und auch beispielsweise das Debugging ist sehr einfach möglich. Nun stellt sich als nächstes die Frage, wie Java-Spring-Boot-Anwendungen ausgeliefert und auf Servern betrieben werden können. Maven hilft: Ein Aufruf von mvn package erzeugt eine JAR-Datei. Diese enthält alles, was für die Anwendung notwendig ist – also das Spring-Framework genauso wie den Tomcat-Server. Man spricht von einem eingebetteten Server. Das vereinfacht das Deployment der Anwendung in Produktion radikal: Es ist nur eine Java-Laufzeitumgebung notwendig. Den Rest bringt die Anwendung in der JAR-Datei selber mit. Damit ist auch gewährleistet, dass die Ablaufumgebung immer zur Anwendung passt – also beispielsweise die richtigen Version des Servers genutzt wird.

Die nächste Frage ist nun, wie die Anwendung konfiguriert werden kann. Auch hier hilft Spring Boot weiter: Die meisten Einstellungen können in Properties-Dateien festgelegt werden – also beispielsweise für den Tomcat-Server server.port oder server.sessionTimeout. Analoge Möglichkeiten gibt es auch für andere Bestandteile einer Spring-Boot-Anwendung. Diese Einstellungen können in einer Datei application.properties im Klassenpfad oder im aktuellen Verzeichnis festgelegt werden. So ist es also auch möglich, auf unterschiedlichen Rechnern unterschiedliche Konfigurationen vorzuhalten, indem entsprechend unterschiedliche application.properties-Dateien auf den Servern hinterlegt werden. Es gibt noch weitere Möglichkeiten, beispielsweise eine Datei mit einem anderen Namen zu laden oder die Konfiguration in YAML festzulegen. Falls dennoch eine Auslieferung der Anwendung als klassische WAR-Datei angestrebt wird, ist das auch möglich. Dann kann die Anwendung ganz klassisch auf einem Application Server installiert werden.

Bis jetzt haben wir nur die Features des Moduls spring-boot-starter-web betrachtet, das in der pom.xml in Listing 1 eingetragen worden ist. Es sorgt durch die Abhängigkeiten dafür, dass die passenden Klassen in Klassenpfad sind, so dass die entsprechenden Konfigurationen zum Leben erweckt werden. Es gibt jetzt schon breite Auswahl von Modulen, die jeweils unterschiedliche Features aus dem Spring-Stack aktivieren: Mit spring-boot-starter-data-jpa wird beispielsweise Spring Data JPA aktiviert, so dass sehr einfach Repositories implementiert werden können. Ebenso gibt es ein Modul für das Aktivieren von Spring Integration, WebSocket, Logging, Batch oder AOP. Besonders interessant ist das Modul spring-boot-starter-jetty, mit dem der sonst genutzte Tomcat-Server gegen einen Jetty-Server ausgetauscht wird. Ebenfalls recht spannend ist spring-boot-starter-actuator. Damit wird die Anwendung um einige Elemente ergänzt, mit denen der Betrieb in Produktion signifikant vereinfacht wird. Das fängt damit an, dass unter dem URL /health ein einfaches ok zurückgegeben wird, wenn die Anwendung zufriedenstellend läuft. /beans ergibt eine Auflistung aller Spring Beans in der Anwendung, /dump gibt alle Threads in der Anwendung aus, und mit /metrics werden Informationen über den Zustand der Anwendung ausgegeben. So kann recht einfach ein Monitoring in die Anwendung integriert werden, und mit den restlichen Features wird nicht nur dem Betrieb das Leben vereinfacht, sondern auch die Suche nach Fehlern in der Anwendung.

Die Schritte, um weitere Technologien zu unterstützen oder andere Erweiterungen zu schreiben, sind nicht sonderlich komplex. Ein Beitrag beispielsweise beschreibt, wie die Unterstützung für JMS in Spring Boot integriert werden kann. Weil das Schreiben von Erweiterungen so einfach ist, wird es wohl sehr schnell viele Erweiterungen geben, die nicht unbedingt von den ursprünglichen Entwicklern kommen müssen, sondern durchaus auch aus der Community kommen können.

Wer sich selber einarbeiten möchte, wird auch unterstützt: Auf der Spring-IO-Website finden sich zwei Guides, die schrittweise in Spring Boot einführen und auch die Implementierung eines REST-Web-Services darstellen. Ebenso gibt es zahlreiche Beispiele in Java, die typische Szenarien in der Spring-Entwicklung betrachten.

Fazit

Auf den ersten Blick scheint Spring Boot nur ein Ansatz zu sein, um die Entwicklung mit Spring zu vereinfachen – und das ist auch sicher richtig. Auf den zweiten Blick werden aber weitere Punkte offensichtlich: Spring Boot ist eine gute Basis für die Implementierung von Groovy-Anwendungen, könnte viele Spring-Anwender also genau dazu verführen. Gleichzeitig macht es Spring Boot nahezu trivial, auch Web-Anwendungen direkt als JAR-Dateien auszuliefern, in denen die gesamte Infrastruktur einschließlich eines Web-Servers enthalten sind. Dieser Ansatz der Embedded-Server ist sehr spannend, weil dadurch die Installation und der Betrieb von Java-Anwendungen viel einfacher werden. Einziger Wermutstropfen: Spring Boot ist zur Zeit noch in einer frühen Version (0.5.0.M5, das Beiispiel dieses Artikels ist mit M4 gebaut) und basiert auf der neuen Version 4.0 des Spring-Frameworks, die ebenfalls noch nicht final ist. Von daher gehört einiges an Mut dazu, mit diesem Ansatz jetzt schon produktiv zu entwickeln – aber die Konzepte sind auf jeden Fall vielversprechend. Wer sich praktisch weiter mit Spring Boot beschäftigen will, dem seien die Guides ans Herz gelegt.

Geschrieben von
Eberhard Wolff
Eberhard Wolff
Eberhard Wolff ist Fellow bei innoQ und arbeitet seit mehr als fünfzehn Jahren als Architekt und Berater, oft an der Schnittstelle zwischen Business und Technologie. Er ist Autor zahlreicher Artikel und Bücher, u.a. zu Continuous Delivery und Microservices und trägt regelmäßig als Sprecher auf internationalen Konferenz vor. Sein technologischer Schwerpunkt sind moderne Architektur- und Entwicklungsansätze wie Cloud, Continuous Delivery, DevOps, Microservices und NoSQL.
Kommentare
  1. Markus Moldaschl2013-10-14 16:37:46

    Mit wie wenig Zeilen Code man mit Spring Boot eine Java/Groovy Webanwendung schreiben kann ist schon beeindruckend. Allerdings bin ich etwas skeptisch ob sich das durchsetzen wird. Immerhin bekommt man mit einer Servletengine wie Tomcat auch Startscripte für alle Betriebssysteme, eine Managementumgebung sowie sonstige Infrastruktur dazu.

    Trotzdem, bin schon sehr neugierig, wie sich das entwickelt.

    1. ewolff2013-10-15 10:17:24

      Danke für das Feedback.
      Zwei Punkte:
      - Man kann weiterhin WARs erstellen und damit die Anwendung dann auch auf einem Tomcat betreiben.
      - Der Schritt zu eingebetteten Servern ist IMHO trotzdem vorteilhaft. Dadurch wird die Komplexität der Infrastruktur reduziert und es ist auch immer sichergestellt, dass die richtige Infrastruktur in der richtigen Konfiguration mit der Anwendung ausgeliefert wird.
      Sicher sind für viele Organisationen Application Server von zentraler Wichtigkeit - aber ich denke, dieser Ansatz kann langfristig die bessere Alternative darstellen.

  2. spgmx2013-10-16 08:20:56

    Ich frage mich seit geraumer Zeit, welche Intention hinter RAD-Tools wie Roo und jetzt auch Boot steckt. Für echte produktive Projekte, die über "Zweizeiler" oder "0815" hinausgehen ist Roo nicht geeignet. Boot hingegen nimmt mir lediglich das Setup des Projektes ab, was mit Maven & Co bzw. geeigneten Projekt-Templates aber auch schnell erledigt ist. Also, wo ist der Sinn? Spielerei wird's ja nicht sein, auch Pivotal hat ja kein Geld zu verschenken.

    1. ewolff2013-10-17 07:33:03

      Danke für das Feedback! Ich hatte überlegt, einen Vergleich mit Roo in den Artikel einzubauen und habe es dann nicht getan, weil die beiden Ansätze sehr unterschiedlich sind. Während Roo wirklich ein RAD Tool ist, führt Spring Boot Convention over Configuration, einen einfachen Pfad zu Groovy und Embedded Server ein. Dieses Ziel wird auch recht gut umgesetzt und geht deutlich weiter als Maven Templates. Dafür gibt es keinen Generator für Web Sites oder so - über die man ja auch geteilter Meinung sein kann...

      1. spgmx2013-10-17 08:53:02

        Genau, scheint mir speziell auf Groovy + Embedded Server ausgerichtet zu sein. Im Java-Umfeld macht das für mich ehrlich gesagt nicht viel Sinn.

        1. Oliver Gierke2013-10-24 11:34:45

          Ich persönlich bin ehrlich gesagt auch nicht glücklich über das Groovy Beispiel. Ich kann durchaus verstehen, dass es schöner Aha!-Moment ist (wir haben das ja auch in ähnlicher form auf der Boot Seite). Es erzeugt aber auch gleichzeitig einen "Und was bringt mir das jetzt?"-Effekt bei Java Entwicklern.

          Ich denke den Kern von Boot machen 3 Punkte aus:

          1. Dependency Management

          Mit reinem Maven/Gradle bleibt es dem Entwickler immer noch selbst überlassen, sich die entsprechenden Bibliotheken in den richtigen Versionen zusammenzusuchen. Die Starter-poms helfen hier und sind trotzdem flexibel genug um bei Bedarf doch mal eine einzelne Version abzuändern.

          2. Konfigurationsdefaulting

          Nehmen wir an, du willst eine Webanwendung auf Basis von Thymealeaf, Spring MVC, und Spring Data JPA mit Hibernate bauen. Über den Mechanismus in 1. bekommst du hier sehr schnell die Dependencies in passenden Versionen zusammen. Was du jetzt aber immer noch tun musst ist ein wenig default Setup: DataSource konfigurieren, EntityManager konfigurieren, Spring Data aktivieren, ein wenig SpringMVC setup (ViewResolver für Thymeleaf) etc. Die Idee von Boot ist jetzt in Abhängigkeit (vor allem) des Classpath diese Konfiguration zu defaulten und dich dann selektiv die Konfiguration abändern zu lassen. Das macht es sehr einfach, schnell zu starten und trotzdem die volle Kontrolle darüber zu behalten, was da konfiguriert wird.

          3. Der Betrieb

          Wenn du einem nicht-Java-Entwickler erzählst was du alles tun musst um eine Webapplikation in Java neu anzulegen und zu starteb bzw. zu betreiben, ist der nach 2 verwirrt und rennt davon. Warum muss es denn eigentlich komplexer sein, als eine Klasse mit einer main(…)-Methode zu starten? Richtig, muss es nicht. Zumindest für die Entwicklungszeit ist das ein sehr bequemer weg mit einer Serverapplikation zu arbeiten. Wir sehen in den Staaten auch vermehrt Produktionsbetrieb auf diese Art und Weise. Es deployed ohnehin kaum jemand mehr als eine Applikation in einen Server (aus Gründen), von daher ist dieser Weg von App-in-den-Server zu Server-in-der-App nicht zu groß. Kritischer Punkt hier ist ganz klar die Integration des Systems in die Monitoring und App-Managementwelt, die Boot über die Actuators angeht. Hier ist definitiv noch Spielraum für Erweiterungen. Dass der gemeine Deutsche hier etwas konservativer ist liegt in seinem Naturell ;).

          Zusammenfassend: Boot ist ein wichtiger Baustein für uns, auch und vor allem für Java basierte Spring-Anwendungen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.