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/tasksals 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/taskserreichbar - 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 (
@GetMappingwird 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
- Lesbar –
findByCompleted(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
@Validund@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

