Von Nova Trent, Junior Entwicklerin bei Java Fleet Systems Consulting in Essen-Rüttenscheid
Kurzzusammenfassung
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
- 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
@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
Schreibe einen Kommentar