22 Arbeiten mit der Spring Boot CLI

22.1 Einführung

Die Spring Boot CLI (Command Line Interface) ist ein leistungsfähiges Werkzeug, das Entwicklern ermöglicht, Spring Boot-Anwendungen schnell und effizient über die Kommandozeile zu erstellen, zu testen und auszuführen. Besonders in der Contract-First-Entwicklung kann die Spring Boot CLI den Entwicklungsprozess beschleunigen, indem sie die Einrichtung und Verwaltung von Projekten vereinfacht. In diesem Kapitel werden wir die Grundlagen der Spring Boot CLI erläutern, ihre Installation und Konfiguration beschreiben und praxisnahe Beispiele für die Nutzung in der Contract-First-Entwicklung mit Spring Boot und OpenAPI vorstellen. Zudem werden wir Best Practices und nützliche Tipps für den effektiven Einsatz der CLI diskutieren.

22.2 Grundlagen der Spring Boot CLI

Die Spring Boot CLI ist ein Kommandozeilenwerkzeug, das es ermöglicht, Spring Boot-Anwendungen ohne umfangreiche Projektkonfiguration schnell zu erstellen und auszuführen. Sie unterstützt die Entwicklung mit Groovy-Skripten, bietet integrierte Unterstützung für Dependency Management und ermöglicht die schnelle Integration von Bibliotheken und Frameworks.

Hauptmerkmale der Spring Boot CLI:

22.3 Installation und Einrichtung der Spring Boot CLI

Die Installation der Spring Boot CLI ist einfach und plattformübergreifend möglich. Hier sind die Schritte zur Installation auf verschiedenen Betriebssystemen:

22.3.1 1. Voraussetzungen

22.3.2 2. Installation mit SDKMAN! (empfohlen)

SDKMAN! ist ein plattformübergreifendes Tool zur Verwaltung von SDKs, einschließlich der Spring Boot CLI.

Installation von SDKMAN!:

curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"

Installation der Spring Boot CLI:

sdk install springboot

22.3.3 3. Alternative Installationsmethoden

22.3.4 4. Überprüfung der Installation

Nach der Installation können Sie die erfolgreiche Einrichtung überprüfen, indem Sie den folgenden Befehl ausführen:

spring --version

22.3.4.1 Beispielhafte Ausgabe

Spring Boot v3.3.0

22.4 Grundlegende Befehle der Spring Boot CLI

Die Spring Boot CLI bietet eine Reihe von Befehlen, die den Entwicklungsprozess unterstützen. Hier sind einige der wichtigsten:

Befehl Beschreibung
spring init Erstellt ein neues Spring Boot-Projekt mit angegebenen Optionen.
spring run Führt ein Spring Boot-Anwendungsskript (Groovy) direkt aus.
spring help Zeigt eine Hilfeseite mit allen verfügbaren Befehlen.
spring jar Paketiert eine Anwendung in eine ausführbare JAR-Datei.
spring test Führt Tests für eine Spring Boot-Anwendung aus.

22.4.1 Beispiele für grundlegende Befehle

  1. Neues Projekt erstellen:

    spring init --dependencies=web,data-jpa,postgresql --build=maven --java-version=11 buchverwaltung

    Erläuterung:

  2. Anwendung aus einem Groovy-Skript ausführen:

    Erstellen Sie eine Datei namens app.groovy:

    @RestController
    class HelloController {
        @RequestMapping("/")
        String home() {
            "Hello, Spring Boot CLI!"
        }
    }

    Führen Sie das Skript aus:

    spring run app.groovy
  3. Projekt bauen und ausführen:

    Wechseln Sie in das erstellte Projektverzeichnis und führen Sie:

    ./mvnw spring-boot:run

    oder, falls das Projekt mit Gradle erstellt wurde:

    ./gradlew bootRun

22.5 Verwendung der Spring Boot CLI in der Contract-First-Entwicklung

In der Contract-First-Entwicklung kann die Spring Boot CLI den Prozess der Projektinitialisierung und der schnellen Prototypenerstellung erheblich beschleunigen. Hier sind einige Anwendungsfälle und Vorgehensweisen:

22.5.1 Schnelle Erstellung von Prototypen

Die Spring Boot CLI ermöglicht es Entwicklern, schnell Prototypen von APIs zu erstellen, die auf einer vorab definierten Spezifikation basieren. Dies ist besonders nützlich, um die Implementierung der Geschäftslogik zu testen und erste Feedbacks einzuholen.

22.5.1.1 Beispiel

spring init --dependencies=web,data-jpa,openapi --build=maven --java-version=11 buchverwaltung
cd buchverwaltung
spring run src/main/java/com/example/BuchverwaltungApplication.java

22.5.2 Integration mit OpenAPI

Die Spring Boot CLI kann in Kombination mit Springdoc OpenAPI verwendet werden, um die API-Dokumentation automatisch zu generieren und zu pflegen. Dies unterstützt die Synchronisation zwischen der API-Spezifikation und der Implementierung.

22.5.2.1 Schritte zur Integration

  1. Abhängigkeit hinzufügen:

    Fügen Sie die folgende Abhängigkeit zu Ihrer pom.xml hinzu:

    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-ui</artifactId>
        <version>1.6.14</version>
    </dependency>
  2. Konfiguration der OpenAPI-Spezifikation:

    Platzieren Sie Ihre api.yaml oder api.json im Verzeichnis src/main/resources/api/.

  3. Automatisierte Code-Generierung:

    Nutzen Sie den OpenAPI Generator in Kombination mit der Spring Boot CLI, um Server-Stubs und Modelle zu generieren, die strikt der Spezifikation entsprechen.

22.5.3 Automatisierung und Skripterstellung

Die Spring Boot CLI kann in Shell-Skripten oder Automatisierungswerkzeugen eingebunden werden, um wiederkehrende Aufgaben wie das Erstellen von Projekten, das Ausführen von Tests oder das Deployen von Anwendungen zu automatisieren.

22.5.4 Beispiel: Automatisiertes Erstellen und Starten einer Anwendung

Erstellen Sie ein Skript namens start.sh:

#!/bin/bash

# Projekt initialisieren
spring init --dependencies=web,data-jpa,openapi --build=maven --java-version=11 buchverwaltung

cd buchverwaltung

# OpenAPI Generator ausführen
mvn clean install

# Anwendung starten
./mvnw spring-boot:run

Führen Sie das Skript aus:

chmod +x start.sh
./start.sh

22.6 Best Practices für die Nutzung der Spring Boot CLI

  1. Versionskontrolle der Spezifikationen und Skripte
  2. Automatisierte Build-Prozesse
  3. Wiederverwendbare Vorlagen nutzen
  4. Skriptbasierte Automatisierung
  5. Dokumentation und Schulung
  6. Verwendung von Profile-Configs
  7. Integrierte Tests durchführen
  8. Nutzung von Abhängigkeitsmanagement
  9. Sicherheit implementieren
  10. Regelmäßige Updates und Wartung

22.7 Praktische Beispiele

22.7.1 Beispiel 1: Erstellung einer einfachen REST-API mit der Spring Boot CLI

  1. Projekt initialisieren:

    spring init --dependencies=web --build=maven --java-version=11 einfache-api
    cd einfache-api
  2. Erstellen eines Controllers:

    Erstellen Sie die Datei src/main/java/com/example/einfacheapi/HelloController.java:

    package com.example.einfacheapi;
    
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class HelloController {
    
        @GetMapping("/hello")
        public String sayHello() {
            return "Hallo, Spring Boot CLI!";
        }
    }
  3. Anwendung ausführen:

    ./mvnw spring-boot:run
  4. Testen der API:

    Öffnen Sie einen Browser oder nutzen Sie curl:

    curl http://localhost:8080/hello

    Antwort:

    Hallo, Spring Boot CLI!
22.7.1.0.1 Beispiel 2: Integration mit OpenAPI und automatisierter Code-Generierung
  1. Projekt initialisieren mit OpenAPI-Abhängigkeit:

    spring init --dependencies=web,openapi --build=maven --java-version=11 buchverwaltung
    cd buchverwaltung
  2. Hinzufügen von Springdoc OpenAPI zur pom.xml:

    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-ui</artifactId>
        <version>1.6.14</version>
    </dependency>
  3. Erstellen der OpenAPI-Spezifikation (api.yaml):

    Platzieren Sie die Datei im Verzeichnis src/main/resources/api/:

    openapi: 3.0.1
    info:
      title: Bücher API
      description: Eine API zur Verwaltung von Büchern.
      version: 1.0.0
    servers:
      - url: http://localhost:8080/api/v1
    paths:
      /books:
        get:
          summary: Liste aller Bücher abrufen
          responses:
            '200':
              description: Erfolgreiche Antwort
              content:
                application/json:
                  schema:
                    type: array
                    items:
                      $ref: '#/components/schemas/Book'
        post:
          summary: Ein neues Buch erstellen
          requestBody:
            description: Buchdaten
            required: true
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Book'
          responses:
            '201':
              description: Buch erstellt
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Book'
      /books/{id}:
        get:
          summary: Ein Buch anhand der ID abrufen
          parameters:
            - $ref: '#/components/parameters/BookId'
          responses:
            '200':
              description: Erfolgreiche Antwort
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Book'
            '404':
              description: Buch nicht gefunden
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/Error'
    components:
      parameters:
        BookId:
          name: id
          in: path
          required: true
          schema:
            type: integer
            format: int64
          description: Die ID des Buches
      schemas:
        Book:
          type: object
          properties:
            id:
              type: integer
              format: int64
              example: 1
            title:
              type: string
              example: Spring Boot in Action
            author:
              type: string
              example: Craig Walls
          required:
            - title
            - author
        Error:
          type: object
          properties:
            code:
              type: integer
              example: 404
            message:
              type: string
              example: Buch nicht gefunden
          required:
            - code
            - message
  4. Hinzufügen des OpenAPI Generators zum pom.xml:

    <build>
        <plugins>
            <!-- OpenAPI Generator Plugin -->
            <plugin>
                <groupId>org.openapitools</groupId>
                <artifactId>openapi-generator-maven-plugin</artifactId>
                <version>6.3.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <inputSpec>${project.basedir}/src/main/resources/api/api.yaml</inputSpec>
                            <generatorName>spring</generatorName>
                            <output>${project.build.directory}/generated-sources/openapi</output>
                            <configOptions>
                                <interfaceOnly>true</interfaceOnly>
                                <delegatePattern>true</delegatePattern>
                            </configOptions>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
    
            <!-- Maven Compiler Plugin -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>1.18.24</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
        <sourceDirectory>src/main/java</sourceDirectory>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
            <resource>
                <directory>${project.build.directory}/generated-sources/openapi</directory>
            </resource>
        </resources>
    </build>
    
    <dependencies>
        <!-- Spring Boot Starter Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    
        <!-- Springdoc OpenAPI UI -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.6.14</version>
        </dependency>
    
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    
    <pluginRepositories>
        <pluginRepository>
            <id>openapitools</id>
            <url>https://plugins.gradle.org/m2/</url>
        </pluginRepository>
    </pluginRepositories>
  5. Code-Generierung ausführen:

    mvn clean install
  6. Implementierung der Geschäftslogik:

    Füllen Sie die generierten Controller-Stubs aus. Beispiel für BookControllerImpl.java:

    package com.example.generated.api;
    
    import com.example.generated.model.Book;
    import com.example.generated.repository.BookRepository;
    import org.springframework.http.ResponseEntity;
    import org.springframework.stereotype.Controller;
    
    import java.util.List;
    import java.util.Optional;
    
    @Controller
    public class BookControllerImpl implements BookController {
    
        private final BookRepository bookRepository;
    
        public BookControllerImpl(BookRepository bookRepository) {
            this.bookRepository = bookRepository;
        }
    
        @Override
        public ResponseEntity<List<Book>> getBooks() {
            List<Book> books = bookRepository.findAll();
            return ResponseEntity.ok(books);
        }
    
        @Override
        public ResponseEntity<Book> getBookById(Long id) {
            Optional<Book> book = bookRepository.findById(id);
            return book.map(ResponseEntity::ok)
                       .orElse(ResponseEntity.notFound().build());
        }
    
        @Override
        public ResponseEntity<Book> createBook(Book book) {
            Book savedBook = bookRepository.save(book);
            return ResponseEntity.status(201).body(savedBook);
        }
    
        // Implementieren Sie weitere Methoden (updateBook, deleteBook etc.)
    }
  7. Erstellung des Datenmodells und Repository:

    Book.java

    package com.example.generated.model;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Book {
        private Long id;
        private String title;
        private String author;
    }

    BookRepository.java

    package com.example.generated.repository;
    
    import com.example.generated.model.Book;
    import org.springframework.stereotype.Repository;
    
    import java.util.*;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.atomic.AtomicLong;
    
    @Repository
    public class BookRepository {
        private final Map<Long, Book> bookStore = new ConcurrentHashMap<>();
        private final AtomicLong idGenerator = new AtomicLong();
    
        public Book save(Book book) {
            if (book.getId() == null) {
                book.setId(idGenerator.incrementAndGet());
            }
            bookStore.put(book.getId(), book);
            return book;
        }
    
        public Optional<Book> findById(Long id) {
            return Optional.ofNullable(bookStore.get(id));
        }
    
        public List<Book> findAll() {
            return new ArrayList<>(bookStore.values());
        }
    
        public boolean deleteById(Long id) {
            return bookStore.remove(id) != null;
        }
    }
  8. Anwendung ausführen und testen:

    Starten Sie die Anwendung:

    ./mvnw spring-boot:run

    Greifen Sie auf die Swagger UI zu unter: http://localhost:8080/swagger-ui.html

    Beispielhafte cURL-Anfragen:

22.7.2 Beispiel: Nutzung von Spring Boot CLI zur schnellen Prototypenerstellung mit OpenAPI

  1. Erstellen eines Groovy-Skripts für die API:

    Erstellen Sie eine Datei namens app.groovy:

    @RestController
    class BookController {
        @GetMapping("/api/v1/books")
        List<Book> getBooks() {
            return [
                new Book(id: 1, title: "Spring Boot in Action", author: "Craig Walls"),
                new Book(id: 2, title: "Java Concurrency in Practice", author: "Brian Goetz")
            ]
        }
    
        @PostMapping("/api/v1/books")
        Book createBook(@RequestBody Book book) {
            book.id = 3
            return book
        }
    }
    
    class Book {
        Long id
        String title
        String author
    }
  2. Anwendung ausführen:

    spring run app.groovy
  3. Testen der API:

    Alle Bücher abrufen:

    curl -X GET "http://localhost:8080/api/v1/books" -H "accept: application/json"

    Antwort:

    [
      {
        "id": 1,
        "title": "Spring Boot in Action",
        "author": "Craig Walls"
      },
      {
        "id": 2,
        "title": "Java Concurrency in Practice",
        "author": "Brian Goetz"
      }
    ]

    Ein neues Buch erstellen:

    curl -X POST "http://localhost:8080/api/v1/books" \
         -H "Content-Type: application/json" \
         -d '{"title": "Effective Java", "author": "Joshua Bloch"}'

    Antwort:

    {
      "id": 3,
      "title": "Effective Java",
      "author": "Joshua Bloch"
    }

22.8 Best Practices für die Nutzung der Spring Boot CLI

  1. Konsistente Projektstruktur beibehalten
  2. Verwendung von Profilen
  3. Automatisierte Tests integrieren
  4. Nutzung von Abhängigkeitsmanagement
  5. Dokumentation pflegen
  6. Sicherheitsmechanismen implementieren
  7. Effiziente Nutzung von Skripten
  8. Versionierung und Deprecation
  9. Kontinuierliche Integration und Deployment (CI/CD)
  10. Regelmäßige Updates und Wartung

22.9 tl;dr

Die Spring Boot CLI ist ein mächtiges Kommandozeilenwerkzeug, das die schnelle Erstellung, Verwaltung und Ausführung von Spring Boot-Anwendungen ermöglicht. Besonders in der Contract-First-Entwicklung unterstützt die CLI die schnelle Initialisierung von Projekten, die Integration mit OpenAPI und die automatisierte Generierung von Server-Stubs und Modellen. Durch die Nutzung von Tools wie OpenAPI Generator und Springdoc OpenAPI kann die Spring Boot CLI die Konsistenz zwischen API-Spezifikation und Implementierung sicherstellen, den Entwicklungsprozess beschleunigen und die Wartbarkeit der Anwendungen erhöhen. Best Practices wie die konsistente Projektstruktur, automatisierte Tests, klare Versionierungsstrategien und die Integration in CI/CD-Pipelines tragen dazu bei, dass die Spring Boot CLI effektiv eingesetzt wird, um robuste, gut dokumentierte und skalierbare APIs zu entwickeln.