Von Nova Trent, Junior Entwicklerin bei Java Fleet Systems Consulting in Essen-Rüttenscheid

Kurze Zusammenfassung

In diesem Learning Monday teile ich meine ersten Schritte mit Spring Boot – vom Spring Initializr über die erste REST API bis hin zu meinen größten „Aha!“-Momenten. Du lernst, warum Spring Boot wie ein „Fertighaus-Bausatz“ funktioniert, was der Initializr wirklich macht und wie aus drei Dependencies plötzlich 20+ JARs werden. Plus: Meine erste Begegnung mit Spring Data JPA und die Entdeckung der „Magic“ Naming Conventions! 🚀

Hallo und willkommen zu meinem ersten Learning Monday! 👋

Ich bin Nova, seit drei Monaten Junior Entwicklerin hier bei Java Fleet, und heute war endlich der Tag – ich habe mich getraut, eine Spring Boot Anwendung komplett von Null zu starten.

Morgens bin ich wie immer mit dem Fahrrad ins Büro nach Rüttenscheid gefahren – das sind zum Glück nur 5 Minuten – und habe mich mit einem extra großen Kaffee an meinen Platz gesetzt. Heute würde ich endlich verstehen, was alle mit diesem „Spring Boot Magic“ meinen!

Schritt 1: Was ist eigentlich Spring Boot?

Elyndra hat es mir so erklärt: „Nova, stell dir vor, du willst ein Haus bauen. Spring Boot ist wie ein Fertighaus-Bausatz – alle wichtigen Teile sind schon da, du musst sie nur noch zusammensetzen.“

Ohne Spring Boot müsste ich:

  • Einen Web-Server (wie Tomcat) installieren und konfigurieren
  • Eine Datenbank aufsetzen und verbinden
  • JSON-Handling für APIs programmieren
  • Stunden mit Konfigurationsdateien verbringen

Mit Spring Boot bekomme ich das alles automatisch – und kann sofort mit dem eigentlichen Programmieren anfangen!

Schritt 2: Spring Initializr – Der Magic Project Generator

Elyndra hat mir start.spring.io gezeigt. Das ist wie ein Projekt-Konfigurator für Spring Boot!

🎯 Was macht der Initializr eigentlich?

Spring Initializr ist viel cleverer als er aussieht. Er generiert nicht nur eine pom.xml, sondern:

  • Komplette Maven-Struktur mit allen richtigen Verzeichnissen
  • Main-Klasse die sofort lauffähig ist
  • Kompatible Dependency-Versionen – kein „Dependency Hell“
  • Sinnvolle Standard-Konfiguration für 80% der Use Cases

🔧 Meine Initializr-Konfiguration:

Project Metadata:

Group: de.javafleet          // Wie ein "Firmen-Namespace"
Artifact: taskmanager-v1     // Der Projekt-Name
Name: Nova's Taskmanager     // Anzeigename
Package: de.javafleet.taskmanager  // Java-Package-Struktur
Java: 17                     // Aktuelle LTS-Version

🪄 Dependencies – Die wahre Magic!

Ich wählte nur 3 Dependencies, aber bekomme viel mehr:

1. Spring Web – Nicht nur ein JAR!

Was ich sehe: „Spring Web“ – 1 Dependency
Was ich wirklich bekomme: 20+ JARs!

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Das inkludiert automatisch:

  • Embedded Tomcat – kompletter Web-Server läuft in meiner App!
  • Spring MVC – für REST Controllers
  • Jackson – automatische JSON Serialization
  • Validation – Bean Validation für Input-Checks

„Ich dachte, ich bekomme nur ‚Web-Support‘, aber eigentlich ist da ein kompletter Web-Server mit drin! Das ist wie ein All-in-One-Paket!“

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

2. Spring Data JPA – Database Magic

Was ich sehe: „Spring Data JPA“ – 1 Dependency
Was ich wirklich bekomme: Enterprise Database Layer!

Das inkludiert:

  • Hibernate – ORM für Datenbankzugriff
  • HikariCP – Connection Pooling
  • Auto-Configuration – Datenbank wird automatisch erkannt
  • Repository Pattern – CRUD-Operations ohne SQL

3. H2 Database – Development Database

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

Embedded In-Memory-Database – perfekt zum Testen und Entwickeln!

Schritt 3: Der erste Code – Task Controller

Mein allererstes REST Controller:

package de.javafleet.taskmanager.controller;

import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.ArrayList;

@RestController
@RequestMapping("/api/tasks")
public class TaskController {
    
    private List<String> tasks = new ArrayList<>();
    
    @GetMapping
    public List<String> getAllTasks() {
        return tasks;
    }
    
    @PostMapping
    public String addTask(@RequestBody String task) {
        tasks.add(task);
        return "Task hinzugefügt: " + task;
    }
}

🤯 Spring Boot Magic in Action

Was passiert hier automatisch:

  • @RestController – Spring Boot erkennt: „Das ist ein REST API!“
  • @RequestMapping – Alle Methoden bekommen /api/tasks als Basis-URL
  • @GetMapping/@PostMapping – HTTP-Methoden werden automatisch gemappt
  • @RequestBody – JSON wird automatisch zu String konvertiert
  • Return Value – Java-Objekte werden automatisch zu JSON

Ich musste NICHTS konfigurieren! Kein XML, keine Annotations-Konfiguration, nichts!

Schritt 4: Die Spring Boot Anwendung starten – Ein magischer Moment

Main-Klasse (generiert vom Initializr):

package de.javafleet.taskmanager;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TaskmanagerApplication {
    public static void main(String[] args) {
        SpringApplication.run(TaskmanagerApplication.class, args);
    }
}

Ein Klick auf „Run“ und…

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.4.2)

INFO 1234 --- [main] d.j.t.TaskmanagerApplication: Started TaskmanagerApplication in 1.847 seconds

BOOM! Es läuft! 🎉

  • Tomcat Server läuft auf Port 8080
  • Meine REST API ist unter http://localhost:8080/api/tasks erreichbar
  • H2 Database ist automatisch gestartet
  • Alles funktioniert ohne weitere Konfiguration!

Schritt 5: Testing mit curl

Code Sentinel hat mir gezeigt, wie echte Entwickler APIs testen – mit curl im Terminal!

GET Request:

curl http://localhost:8080/api/tasks

Response: [] (Super leere Liste – perfekt!)

POST Request:

curl -X POST http://localhost:8080/api/tasks \
  -H "Content-Type: application/json" \
  -d '"Mein erster Task"'

Nochmal GET:

curl http://localhost:8080/api/tasks

ES FUNKTIONIERT! 🚀


WAIT… Aber ich will eine ECHTE Datenbank! 🤔

Nach dem ersten Erfolg dachte ich mir: „Das ist cool, aber die ArrayList ist ja nur im Speicher. Wenn ich die App neustarte, sind alle Tasks weg!“

Elyndra hat gelacht: „Nova, du hast doch Spring Data JPA hinzugefügt! Zeit für echte Database Magic!“

Schritt 6: Meine erste JPA Entity

Weg mit der ArrayList, her mit echten Database-Objekten!

package de.javafleet.taskmanager.entity;

import jakarta.persistence.*;

@Entity
@Table(name = "tasks")
public class Task {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false)
    private String title;
    
    private String description;
    
    private boolean completed = false;
    
    // Constructors
    public Task() {} // JPA braucht das!
    
    public Task(String title) {
        this.title = title;
    }
    
    public Task(String title, String description) {
        this.title = title;
        this.description = description;
    }
    
    // Getters und Setters
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    
    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }
    
    public String getDescription() { return description; }
    public void setDescription(String description) { this.description = description; }
    
    public boolean isCompleted() { return completed; }
    public void setCompleted(boolean completed) { this.completed = completed; }
}

Was bedeuten diese Annotations?

  • @Entity – „Spring, das ist eine Datenbank-Tabelle!“
  • @Table(name = „tasks“) – „Nenne die Tabelle ‚tasks'“
  • @Id – „Das ist der Primary Key“
  • @GeneratedValue – „Die Datenbank soll automatisch IDs vergeben“
  • @Column(nullable = false) – „Titel darf nicht leer sein“

Das Coole: Hibernate erstellt automatisch die SQL-Tabelle aus meiner Java-Klasse! 🪄

Schritt 7: Repository Magic – Der Moment, der alles änderte!

Jetzt kommt der Teil, der mein Hirn gesprengt hat:

package de.javafleet.taskmanager.repository;

import de.javafleet.taskmanager.entity.Task;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface TaskRepository extends JpaRepository<Task, Long> {
    // Kein Code nötig! Spring Data generiert automatisch:
    // - findAll()
    // - findById(Long id) 
    // - save(Task task)
    // - deleteById(Long id)
    // - count()
    // und viele mehr!
}

WAIT… WAS?! 🤯

Ich schreibe ein Interface ohne Implementierung und bekomme trotzdem alle CRUD-Methoden?!

Dr. Cassian hat es mir erklärt: „Nova, das nennt sich ‚Code Generation zur Laufzeit‘. Spring Data analysiert dein Interface und generiert automatisch die Implementierung basierend auf den Methoden-Namen. Das ist moderne Metaprogrammierung!“

„Okay, ich verstehe es nicht komplett, aber es ist FANTASTISCH!“

🎯 Nova entdeckt Spring Data JPA Naming Conventions!

Und dann ist mir was aufgefallen… Ich habe aus Neugier eine Methode hinzugefügt:

@Repository
public interface TaskRepository extends JpaRepository<Task, Long> {
    // Die Standard-CRUD-Methoden...
    
    // Moment mal... kann ich das?
    List<Task> findByCompleted(boolean completed);
}

Das ist unglaublich: Ich schreibe eine Methodensignatur und Spring Data versteht automatisch, was ich will!

// Ich schreibe:
List<Task> findByCompleted(boolean completed);

// Spring Data JPA generiert automatisch:
// SELECT * FROM tasks WHERE completed = ?

Das ist kein Zufall – das ist ein cleveres System!

🪄 Die Naming Convention Regeln:

Basis-Pattern: findBy + PropertyName + (optionaler Operator)

// Meine Entity hat: id, title, description, completed
public interface TaskRepository extends JpaRepository<Task, Long> {
    
    // Nach einzelnen Properties suchen:
    List<Task> findByTitle(String title);           // WHERE title = ?
    List<Task> findByCompleted(boolean completed);  // WHERE completed = ?
    
    // Mit Text-Operatoren:
    List<Task> findByTitleContaining(String text);  // WHERE title LIKE %?%
    List<Task> findByTitleStartingWith(String text); // WHERE title LIKE ?%
    
    // Kombinationen:
    List<Task> findByCompletedAndTitleContaining(boolean completed, String title);
    // WHERE completed = ? AND title LIKE %?%
    
    // Mit Sortierung:
    List<Task> findByCompletedOrderByTitleAsc(boolean completed);
    // WHERE completed = ? ORDER BY title ASC
}

Das ist MIND-BLOWING! 🤯

Schritt 8: Controller-Update für echte Database

Zeit, meinen Controller von ArrayList auf Repository umzustellen:

package de.javafleet.taskmanager.controller;

import de.javafleet.taskmanager.entity.Task;
import de.javafleet.taskmanager.repository.TaskRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/api/tasks")
public class TaskController {
    
    @Autowired  // Erstmal @Autowired (Constructor Injection lerne ich später!)
    private TaskRepository taskRepository;
    
    @GetMapping
    public List<Task> getAllTasks() {
        return taskRepository.findAll();
    }
    
    @GetMapping("/{id}")
    public Optional<Task> getTaskById(@PathVariable Long id) {
        return taskRepository.findById(id);
    }
    
    @PostMapping
    public Task createTask(@RequestBody Task task) {
        return taskRepository.save(task);
    }
    
    // Hier kommt meine Naming Convention Entdeckung zum Einsatz!
    @GetMapping("/completed/{status}")
    public List<Task> getTasksByStatus(@PathVariable boolean status) {
        return taskRepository.findByCompleted(status);
    }
}

Was ist anders?

  • Weg mit ArrayList – jetzt echte Database!
  • Repository Injection – Spring gibt mir automatisch eine TaskRepository-Instanz
  • Echte Task-Objekte statt nur Strings
  • findByCompleted() – meine erste Custom Query!

Schritt 9: Die H2 Console entdecken – Database Browser im Browser!

Das coolste Feature überhaupt: http://localhost:8080/h2-console

Eine komplette Datenbank-Oberfläche im Browser!

  • JDBC URL: jdbc:h2:mem:testdb
  • Username: sa
  • Password: (leer lassen)

„Ich kann SQL-Abfragen schreiben, Tabellen anschauen, Daten einfügen – alles im Browser! Das ist wie phpMyAdmin für meine Entwicklungsumgebung!“

Schritt 10: Testing der neuen Database API

Zeit für echte Tests mit JSON-Objekten:

# Alle Tasks abrufen (erstmal leer)
curl http://localhost:8080/api/tasks
# Response: []

# Neuen Task erstellen
curl -X POST http://localhost:8080/api/tasks \
  -H "Content-Type: application/json" \
  -d '{"title": "Mein erster echter Task", "description": "Spring Data JPA lernen!"}'

# Response: 
# {"id":1,"title":"Mein erster echter Task","description":"Spring Data JPA lernen!","completed":false}

# Alle Tasks abrufen (jetzt mit Inhalt!)
curl http://localhost:8080/api/tasks
# Response: [{"id":1,"title":"Mein erster echter Task",...}]

Und jetzt kommt der Test meiner Naming Convention Entdeckung:

# Einen erledigten Task erstellen
curl -X POST http://localhost:8080/api/tasks \
  -H "Content-Type: application/json" \
  -d '{"title": "Erledigter Task", "completed": true}'

# Nur offene Tasks abrufen
curl http://localhost:8080/api/tasks/completed/false
# Response: [{"id":1,"title":"Mein erster echter Task","completed":false}]

# Nur erledigte Tasks abrufen  
curl http://localhost:8080/api/tasks/completed/true
# Response: [{"id":2,"title":"Erledigter Task","completed":true}]

ES FUNKTIONIERT! 🎉🎉🎉

Das ist mein erstes „Ich verstehe Spring Data!“ Moment! 🏆

Meine größten „Aha!“-Momente

1. „Spring Boot ist ein Framework, keine Library!“

Anfangs dachte ich, Spring Boot wäre nur eine Sammlung von Hilfsfunktionen. Aber nein – es steuert meine Anwendung, nicht umgekehrt!

Framework vs Library:

  • Library: Ich rufe Funktionen auf (z.B. List.add())
  • Framework: Das Framework ruft meinen Code auf (@GetMapping wird automatisch ausgeführt)

2. „Embedded Server = Game Changer!“

Früher: Anwendung separat auf Tomcat deployen
Spring Boot: Tomcat läuft IN meiner App!

Das bedeutet:

  • Keine separaten Server-Installationen
  • Einfaches Deployment (nur eine JAR-Datei)
  • Gleiche Umgebung für Development und Production

3. „Convention over Configuration funktioniert wirklich!“

Spring Boot errät 90% meiner Konfiguration richtig:

  • Datenbank-Connection (durch H2 Dependency)
  • JSON-Serialization (durch Jackson)
  • Port 8080 (Spring Boot Standard)
  • Component Scanning (durch @SpringBootApplication)

Ich muss nur das konfigurieren, was von der Norm abweicht!

4. „Spring Data Naming Conventions sind pure Magic!“

Das war mein größtes Aha-Moment:

  • Ich schreibe findByCompleted(boolean completed)
  • Spring Data generiert automatisch SELECT * FROM tasks WHERE completed = ?
  • Kein SQL, Type-Safe, selbsterklärend!

Warum ist das so genial?

  • Kein SQL schreiben – ich denke in Java-Properties
  • Type-Safe – Compiler checkt meine Methodensignatur
  • LesbarfindByCompleted(true) ist selbsterklärend
  • Konsistent – einmal gelernt, funktioniert überall gleich

Was ich heute gelernt habe

Erfolge:

  • Spring Initializr beherrschen
  • Erste REST API zum Laufen gebracht
  • Spring Boot Magic verstanden
  • Embedded Server Konzept kapiert
  • JPA Entities erstellt
  • Repository Pattern entdeckt
  • Spring Data Naming Conventions verstanden!

🤔 Noch Verwirrend:

  • Was passiert alles im Hintergrund? (Auto-Configuration)
  • Wie funktioniert Dependency Injection genau?
  • Constructor Injection vs @Autowired? (Elyndra hat das erwähnt)
  • Wie komme ich von H2 zu PostgreSQL?

📚 Nächste Schritte:

  • Constructor Injection lernen (Elyndra’s Tipp)
  • Validation für Input-Daten hinzufügen
  • Error Handling implementieren
  • Security hinzufügen (Code Sentinel wird mir helfen!)

Fazit – Spring Boot + Spring Data = Mind = Blown! 🤯

Heute habe ich verstanden, warum alle von „Spring Boot Magic“ reden!

Mit 3 Dependencies und 50 Zeilen Code habe ich eine funktionsfähige REST API mit echter Datenbank erstellt. Das wäre mit Plain Java mindestens 500 Zeilen gewesen!

Aber das Coolste: Die findByCompleted() Entdeckung! Spring Data versteht meine Methodennamen und generiert automatisch SQL. Das ist echte Entwickler-Magic!

Spring Boot nimmt mir 80% der Arbeit ab, so dass ich mich auf die Geschäftslogik konzentrieren kann. Perfekt für Anfänger wie mich!

Ich merke auch: Ich verstehe noch nicht alles, was im Hintergrund passiert. Aber das ist ok – ich lerne Schritt für Schritt!

Ausblick auf nächste Woche

Learning Monday #2: „Security & Validation – Meine Task API wird erwachsen!“

In der nächsten Woche werde ich meine Task-App sicherer machen:

  • Spring Security hinzufügen (Basic Authentication)
  • Validation mit @Valid und @NotBlank
  • Bessere Error Messages für ungültige Inputs
  • Security Best Practices die Code Sentinel mir gezeigt hat

Und: Elyndra hat versprochen, mir Constructor Injection zu zeigen und zu erklären, warum das besser als @Autowired ist!

Bis nächste Woche – und danke fürs Lesen! 💚


💻 Code zum Nachprogrammieren

Den kompletten Code aus diesem Learning Monday findest du hier:
👉 GitHub: nova-task-manager v1.0

Du kannst das Projekt klonen und direkt ausprobieren:

git clone https://github.com/Java-Fleet-Systems-Consulting-Ltd/nova-task-manager.git
cd nova-task-manager
./mvnw spring-boot:run

FAQ – Häufige Fragen zu Spring Boot

Frage 1: Ist Spring Boot schwer zu lernen?
Antwort: Nein! Spring Boot ist sehr anfängerfreundlich. Du kannst sofort produktive Apps bauen, auch ohne alle Details zu verstehen. Die Lernkurve ist viel flacher als bei Plain Spring.

Frage 2: Was ist der Unterschied zwischen Spring und Spring Boot?
Antwort: Spring ist das Framework, Spring Boot macht es einfacher zu verwenden. Spring Boot = Spring + Auto-Configuration + Embedded Server + Starter Dependencies.

Frage 3: Wie funktionieren Spring Data Naming Conventions?
Antwort: Spring Data parst deine Methodennamen mit einem Pattern: findBy + PropertyName + Operator. Aus findByCompleted(boolean) wird automatisch SELECT * FROM tasks WHERE completed = ?.

Frage 4: Brauche ich IntelliJ für Spring Boot?
Antwort: Nein! VS Code mit Java Extension Pack reicht völlig aus. IntelliJ ist mächtiger, aber für den Einstieg nicht nötig.


Nova Trent arbeitet als Junior Entwicklerin bei Java Fleet Systems Consulting in Essen-Rüttenscheid und dokumentiert ihre Lernreise von der Theorie zur Praxis. Folge ihrer Entwicklung jeden Montag hier im Blog!

#SpringBootAnfänger #JavaLernen #RestAPI #SpringBoot #SpringData #JPA #JavaFleetBlog #LearningMonday #JuniorDeveloper #NamingConventions #RepositoryPattern #DatabaseMagic



Avatar-Foto

Ensign Nova Trent

24 Jahre alt, frisch von der Universität als Junior Entwicklerin bei Java Fleet Systems Consulting. Nova ist brilliant in Algorithmen und Datenstrukturen, aber neu in der praktischen Java-Enterprise-Entwicklung. Sie brennt darauf, ihre ersten echten Projekte zu bauen und entdeckt dabei die Lücke zwischen Uni-Theorie und Entwickler-Realität. Sie liebt Star Treck das ist der Grund warum alle Sie Ensign Nova nennen und arbeitet daraufhin das sie Ihren ersten Knopf am Kragen bekommt.

0 Kommentare

Schreibe einen Kommentar

Avatar-Platzhalter

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert