Spring Boot Basic – Tag 9 von 10
Von Elyndra Valen, Senior Entwicklerin bei Java Fleet Systems Consulting

📍 Deine Position im Kurs
| Tag | Thema | Status |
|---|---|---|
| ✅ 1 | Erste REST API | Abgeschlossen |
| ✅ 2 | Spring Container & DI | Abgeschlossen |
| ✅ 3 | @Controller & Thymeleaf Basics | Abgeschlossen |
| ✅ 4 | Thymeleaf Forms & MVC-Pattern | Abgeschlossen |
| ✅ 5 | Konfiguration & Logging | Abgeschlossen |
| ✅ 6 | DI & AOP im Detail | Abgeschlossen |
| ✅ 7 | Scopes in Spring | Abgeschlossen |
| ✅ 8 | WebSockets | Abgeschlossen |
| → 9 | JAX-RS in Spring Boot | 👉 DU BIST HIER! |
| 10 | Integration & Abschluss | Morgen! |
Modul: Spring Boot Basic (10 Arbeitstage)
Dein Ziel: REST APIs mit Java Standards bauen!
📋 Voraussetzungen
Du brauchst:
- ✅ Tag 1-8 abgeschlossen
- ✅ REST APIs mit Spring MVC verstehen (@RestController, @GetMapping)
- ✅ JSON Serialisierung verstehen
- ✅ HTTP-Methoden kennen (GET, POST, PUT, DELETE)
Tag 8 verpasst? → Hier geht’s zum Blogbeitrag Tag 8
⚡ Was dich heute erwartet
Bisher: Du hast REST APIs mit Spring MVC gebaut:
@RestController
@RequestMapping("/api/persons")
public class PersonApiController {
@GetMapping
public List<Person> getAllPersons() {
return personService.getAllPersons();
}
}
Das funktioniert perfekt! Aber es ist Spring-spezifisch.
Heute: Lernst du JAX-RS – den Java Standard für REST APIs!
@Path("/persons")
public class PersonResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<Person> getAllPersons() {
return personService.getAllPersons();
}
}
Der Unterschied:
- Spring MVC = Spring-spezifisch (@RestController, @GetMapping)
- JAX-RS = Java Standard (@Path, @GET) – funktioniert in jedem Java EE Server!
Warum ist das wichtig?
- 🏢 Enterprise-Welt nutzt JAX-RS
- 📦 Portabilität – Code läuft auf Tomcat, WildFly, GlassFish, Payara
- 🔄 Migration – von Java EE zu Spring Boot (und zurück!)
- 📚 Standard-Wissen – gilt für ganze Java-Welt
Hier kannst du dir die Sourcen von heute auf Github herunterladen.
🎯 Dein Lernpfad heute
Du arbeitest heute in mehreren aufbauenden Schwierigkeitsstufen. Arbeite in deinem eigenen Tempo durch die Schritte:
🟢 Grundlagen (Schritte 1-3)
Was du lernst:
- JAX-RS verstehen – was ist das?
- Unterschied Spring MVC vs JAX-RS
- Jersey in Spring Boot integrieren
- Dependencies einrichten
- Erste JAX-RS Resource erstellen
- @Path, @GET, @POST, @PUT, @DELETE
Ziel: Du verstehst JAX-RS und hast eine funktionierende Resource
Dauer: ~3 Stunden
🟡 Professional (Schritte 4-5)
Was du lernst:
- @Produces und @Consumes (Content Negotiation)
- Parameter-Annotations (@PathParam, @QueryParam)
- Response-Objekte und HTTP-Status
- Exception Handling mit @Provider
- Custom Exceptions und ExceptionMapper
Ziel: Production-Ready JAX-RS API mit Error Handling
Dauer: ~3 Stunden
🔵 Bonus: Enterprise Features (Schritt 6)
Was du lernst:
- Spring MVC vs JAX-RS Side-by-Side
- Migration-Patterns von Java EE zu Spring Boot
- Wann JAX-RS, wann Spring MVC?
- Beide Ansätze parallel nutzen
- Best Practices für Enterprise
Ziel: Migration-Ready sein und beide Welten beherrschen
Dauer: ~2 Stunden
💻 Los geht’s!
🟢 GRUNDLAGEN (Schritte 1-3)
Schritt 1: Was ist JAX-RS? (45 Min)
1.1 JAX-RS verstehen
JAX-RS = Jakarta RESTful Web Services (früher: Java API for RESTful Web Services)
Was ist das?
- Ein Java Standard für REST APIs
- Teil von Jakarta EE (früher Java EE)
- Vendor-neutral – nicht an Spring gebunden!
- Implementierungen: Jersey, RESTEasy, Apache CXF
Die Analogie:
JDBC = Standard für Datenbank-Zugriff → Implementierungen: MySQL Driver, PostgreSQL Driver JAX-RS = Standard für REST APIs → Implementierungen: Jersey, RESTEasy, CXF
1.2 Spring MVC vs JAX-RS – Der Vergleich
Vergleichstabelle:
| Feature | Spring MVC | JAX-RS |
|---|---|---|
| Standard | Spring-spezifisch | Java/Jakarta Standard |
| Annotation Style | @GetMapping, @PostMapping | @GET, @POST |
| Path Definition | @RequestMapping(„/api/persons“) | @Path(„/persons“) |
| Content Type | produces/consumes in Mapping | @Produces, @Consumes |
| Parameter Binding | @RequestBody, @PathVariable | Automatisch, @PathParam |
| Portabilität | Nur Spring Boot | Jeder Jakarta EE Server |
1.3 Warum JAX-RS lernen?
1. Enterprise-Standard:
Banken, Versicherungen, große Konzerne: → Nutzen oft Java EE/Jakarta EE → JAX-RS ist der Standard dort → Wenn du in diesen Firmen arbeitest: JAX-RS-Wissen essentiell!
2. Portabilität:
JAX-RS Code läuft auf: ✅ Tomcat, WildFly, GlassFish, Payara, Open Liberty, Spring Boot Spring MVC Code läuft auf: ✅ Spring Boot ❌ WildFly (ohne Spring)
3. Migration:
Firma hat Java EE Apps mit JAX-RS → Migration zu Spring Boot → Du musst JAX-RS verstehen!
4. Job-Markt:
"Java Backend Developer" Stellenanzeigen: → 60% fordern JAX-RS Kenntnisse → 80% fordern Spring Boot Kenntnisse → Wenn du BEIDES kannst: 2x wertvoller!
Schritt 2: Jersey in Spring Boot integrieren (1 Stunde)
2.1 Dependencies hinzufügen
pom.xml:
<dependencies>
<!-- Existing dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Jersey (JAX-RS) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
</dependencies>
Maven reload!
mvn clean install
2.2 Jersey Configuration erstellen
config/JerseyConfig.java:
package com.example.springbootbasic.config;
import com.example.springbootbasic.resource.PersonResource;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Configuration;
import jakarta.ws.rs.ApplicationPath;
@Configuration
@ApplicationPath("/api") // Base-Path für alle JAX-RS Resources
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
// Resources registrieren
register(PersonResource.class);
}
}
Was macht das:
@ApplicationPath("/api")
→ Alle JAX-RS Endpoints starten mit /api
register(PersonResource.class)
→ PersonResource wird verfügbar unter /api/persons
2.3 Erste JAX-RS Resource erstellen
resource/PersonResource.java:
package com.example.springbootbasic.resource;
import com.example.springbootbasic.model.Person;
import com.example.springbootbasic.service.PersonService;
import org.springframework.stereotype.Component;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.util.List;
@Component // Spring Bean!
@Path("/persons")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class PersonResource {
private final PersonService personService;
// Constructor Injection funktioniert!
public PersonResource(PersonService personService) {
this.personService = personService;
}
@GET
public List<Person> getAllPersons() {
return personService.getAllPersons();
}
@GET
@Path("/{id}")
public Response getPersonById(@PathParam("id") Long id) {
Person person = personService.getPersonById(id);
if (person == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
return Response.ok(person).build();
}
@POST
public Response createPerson(Person person) {
Person created = personService.createPerson(person);
return Response
.status(Response.Status.CREATED)
.entity(created)
.build();
}
}
WICHTIG: @Component – damit Spring die Resource als Bean verwaltet!
Schritt 3: JAX-RS Annotations im Detail (1.5 Stunden)
3.1 @Path – URL-Mapping
Basis-Syntax:
@Path("/persons") // /api/persons
public class PersonResource {
@GET
public List<Person> getAll() { }
@GET
@Path("/{id}") // /api/persons/123
public Person getById(@PathParam("id") Long id) { }
@GET
@Path("/{id}/address") // /api/persons/123/address
public Address getAddress(@PathParam("id") Long id) { }
}
3.2 HTTP-Method Annotations
Standard-Methods:
@GET // Daten holen @POST // Daten erstellen @PUT // Daten aktualisieren (vollständig) @DELETE // Daten löschen @PATCH // Daten aktualisieren (teilweise)
Beispiel – CRUD vollständig:
@Path("/persons")
public class PersonResource {
@GET
public List<Person> getAll() {
return personService.getAllPersons();
}
@POST
public Response create(Person person) {
Person created = personService.createPerson(person);
return Response.status(Response.Status.CREATED)
.entity(created)
.build();
}
@PUT
@Path("/{id}")
public Person update(@PathParam("id") Long id, Person person) {
return personService.updatePerson(id, person);
}
@DELETE
@Path("/{id}")
public Response delete(@PathParam("id") Long id) {
personService.deletePerson(id);
return Response.noContent().build();
}
}
3.3 Testen!
# App starten
mvn spring-boot:run
# GET alle Personen (JAX-RS)
curl http://localhost:8080/api/persons
# GET eine Person (JAX-RS)
curl http://localhost:8080/api/persons/1
# POST neue Person (JAX-RS)
curl -X POST http://localhost:8080/api/persons \
-H "Content-Type: application/json" \
-d '{"firstname":"Tom","lastname":"Miller"}'
JAX-RS funktioniert! ✅
✅ Checkpoint Grundlagen
Kontrolliere:
- [ ] Du verstehst was JAX-RS ist
- [ ] Du kennst den Unterschied zu Spring MVC
- [ ] Jersey Dependencies sind in pom.xml
- [ ] JerseyConfig ist erstellt
- [ ] PersonResource funktioniert
- [ ] @Path, @GET, @POST verstanden
- [ ] Du kannst die API testen
Alles ✅? Weiter zu 🟡 Professional!
🟡 PROFESSIONAL (Schritte 4-5)
Schritt 4: @Produces, @Consumes & Parameter (1.5 Stunden)
4.1 @Produces und @Consumes – Content Negotiation
@Produces – Was sendet die API:
@Path("/persons")
public class PersonResource {
@GET
@Produces(MediaType.APPLICATION_JSON) // Nur JSON
public List<Person> getAllJson() {
return personService.getAllPersons();
}
@GET
@Path("/flexible")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) // Beides!
public List<Person> getAllFlexible() {
// Client entscheidet via Accept-Header
return personService.getAllPersons();
}
}
Client-Request:
# JSON anfordern curl -H "Accept: application/json" http://localhost:8080/api/persons/flexible # XML anfordern curl -H "Accept: application/xml" http://localhost:8080/api/persons/flexible
4.2 Parameter-Annotations
@PathParam – URL-Parameter:
@GET
@Path("/{id}")
public Person getById(@PathParam("id") Long id) {
return personService.getPersonById(id);
}
// URL: /api/persons/42
// id = 42
@QueryParam – Query-String-Parameter:
@GET
public List<Person> search(
@QueryParam("firstname") String firstname,
@QueryParam("lastname") String lastname,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("10") int size) {
return personService.search(firstname, lastname, page, size);
}
// URL: /api/persons?firstname=Max&page=0&size=20
@DefaultValue – Default-Werte:
@GET
public List<Person> getAll(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("10") int size) {
// Wenn nicht angegeben: page=0, size=10
return personService.getAll(page, size);
}
4.3 Response-Objekte und HTTP-Status
Wichtige HTTP-Status-Codes:
| Code | Status | Verwendung |
|---|---|---|
| 200 | OK | Erfolgreiche GET/PUT-Operation |
| 201 | CREATED | Erfolgreiche POST-Operation |
| 204 | NO_CONTENT | Erfolgreiche DELETE-Operation |
| 400 | BAD_REQUEST | Ungültige Client-Daten |
| 404 | NOT_FOUND | Resource nicht gefunden |
Beispiel:
@GET
@Path("/{id}")
public Response getById(@PathParam("id") Long id) {
Person person = personService.getPersonById(id);
if (person == null) {
return Response
.status(Response.Status.NOT_FOUND)
.entity("Person not found with id: " + id)
.build();
}
return Response
.status(Response.Status.OK)
.entity(person)
.build();
}
Schritt 5: Exception Handling (1.5 Stunden)
5.1 ExceptionMapper erstellen
exception/PersonNotFoundExceptionMapper.java:
package com.example.springbootbasic.exception;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;
@Provider // JAX-RS Exception Mapper
public class PersonNotFoundExceptionMapper
implements ExceptionMapper<PersonNotFoundException> {
@Override
public Response toResponse(PersonNotFoundException exception) {
ErrorResponse error = new ErrorResponse(
Response.Status.NOT_FOUND.getStatusCode(),
exception.getMessage(),
System.currentTimeMillis()
);
return Response
.status(Response.Status.NOT_FOUND)
.entity(error)
.build();
}
}
dto/ErrorResponse.java:
package com.example.springbootbasic.dto;
public class ErrorResponse {
private int status;
private String message;
private long timestamp;
public ErrorResponse() {
}
public ErrorResponse(int status, String message, long timestamp) {
this.status = status;
this.message = message;
this.timestamp = timestamp;
}
// Getters and Setters
public int getStatus() { return status; }
public void setStatus(int status) { this.status = status; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public long getTimestamp() { return timestamp; }
public void setTimestamp(long timestamp) { this.timestamp = timestamp; }
}
5.2 Exception registrieren
@Configuration
@ApplicationPath("/api")
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(PersonResource.class);
register(PersonNotFoundExceptionMapper.class); // Exception Mapper!
}
}
5.3 Custom Exceptions nutzen
exception/PersonNotFoundException.java:
package com.example.springbootbasic.exception;
public class PersonNotFoundException extends RuntimeException {
public PersonNotFoundException(Long id) {
super("Person not found with id: " + id);
}
}
Resource nutzt Exception:
@GET
@Path("/{id}")
public Person getById(@PathParam("id") Long id) {
Person person = personService.getPersonById(id);
if (person == null) {
throw new PersonNotFoundException(id); // Exception werfen!
}
return person;
}
Resultat:
curl http://localhost:8080/api/persons/999
# Response: 404 NOT FOUND
{
"status": 404,
"message": "Person not found with id: 999",
"timestamp": 1697543210567
}
✅ Checkpoint Professional
Kontrolliere:
- [ ] @Produces und @Consumes verstanden
- [ ] @PathParam und @QueryParam funktionieren
- [ ] Response-Objekte mit Status-Codes nutzen
- [ ] ExceptionMapper erstellt
- [ ] Custom Exceptions funktionieren
- [ ] ErrorResponse als JSON zurückgeben
Alles ✅? Weiter zu 🔵 Enterprise Features!
🔵 BONUS: ENTERPRISE FEATURES (Schritt 6)
Schritt 6: Spring MVC vs JAX-RS – Side by Side (2 Stunden)
6.1 Code-Vergleich
| Feature | Spring MVC | JAX-RS |
|---|---|---|
| Class Annotation | @RestController | @Path |
| Base Path | @RequestMapping(„/persons“) | @Path(„/persons“) |
| GET Method | @GetMapping | @GET |
| POST Method | @PostMapping | @POST |
| Path Variable | @PathVariable Long id | @PathParam(„id“) Long id |
| Request Body | @RequestBody Person | Person (automatisch) |
| Response | ResponseEntity | Response |
Ähnlichkeiten:
- ✅ Beide nutzen Annotations
- ✅ Beide unterstützen DI
- ✅ Beide JSON-Serialisierung automatisch
Unterschiede:
- ❌ Verschiedene Annotation-Namen
- ❌ JAX-RS = Standard, Spring MVC = Framework-spezifisch
6.2 Wann was nutzen?
JAX-RS wenn:
- Migration von Java EE zu Spring Boot
- Portabilität wichtig (mehrere Server-Typen)
- Enterprise-Standard gefordert
- Team kennt Java EE
Spring MVC wenn:
- Neue Spring Boot App
- Spring-Ökosystem voll nutzen
- Team kennt nur Spring
- Keine Migrations-Anforderung
6.3 Beide parallel nutzen
// Spring MVC: /spring/persons
@RestController
@RequestMapping("/spring/persons")
public class PersonSpringController { }
// JAX-RS: /api/persons
@Path("/persons")
public class PersonJaxRsResource { }
// Beide laufen parallel! ✅
✅ Checkpoint Enterprise Features
Kontrolliere:
- [ ] Du siehst den Unterschied Spring MVC vs JAX-RS
- [ ] Du verstehst Vor- und Nachteile
- [ ] Du weißt wann du was nutzt
- [ ] Du kannst beide parallel nutzen
- [ ] Du bist Migration-Ready!
Alles ✅? Du bist jetzt ein JAX-RS-Profi! 🎉
Hier sind noch ein paar sehr nützliche externe Links zum Thema JAX‑RS in Spring Boot – REST mit Java-Standards, die sich gut als Quellen oder weiterführende Materialien für dein Buchkapitel eignen:
- „Create Jersey REST APIs with Spring Boot“ – Tutorial bei HowToDoInJava: zeigt Schritt-für-Schritt wie man JAX-RS (Jersey) neben Spring Boot einsetzt. HowToDoInJava
- „Using JAX-RS with Spring Boot instead of MVC“ – Artikel bei DZone: erklärt die Integration von JAX-RS in Spring-Umgebung und worauf man achten sollte. DZone
- „REST API: JAX-RS vs Spring“ – Artikel bei Baeldung: erläutert die Unterschiede zwischen JAX-RS und Spring MVC/REST-Ansatz. Baeldung on Kotlin
- „Spring Boot JAX-RS Example“ – Java Code Geeks: Beispielprojekt mit Spring Boot + JAX-RS (z. B. mit Apache CXF) inkl. Konfigurationsdetails. Examples Java Code Geeks
- „JAX-RS Spec and Implementations“ – Baeldung: erklärt, was JAX-RS eigentlich ist, als Spezifikation und welche Implementierungen existieren. Baeldung on Kotlin
🔥 Elyndras Real Talk:
Nova kam heute zu mir: „Elyndra, warum gibt es zwei Wege für REST APIs? Ist das nicht verwirrend?“
Die AutoTech Migration-Story
Das war 2021, mein viertes Jahr bei AutoTech. Wir hatten eine große Legacy-Anwendung auf WildFly mit JAX-RS.
Der Auftrag: „Wir wollen zu Spring Boot migrieren. Wie lange dauert das?“
Mein erster Gedanke: „Alles neu schreiben mit Spring MVC? 3 Monate!“
Code Sentinel: „Oder… du nutzt Jersey in Spring Boot. Dann läuft dein JAX-RS Code 1:1!“
Das Ergebnis:
Migration-Zeit: 5 Tage (statt 3 Monate) Code-Änderungen: <5% (statt 100%) Bugs: 2 kleine (statt viele neue) ✅ Production-Ready nach 1 Woche!
Nova war beeindruckt: „Das ist ja 12x schneller!“
„Exakt,“ sagte ich. „Das ist der Wert von Standards. JAX-RS ist portabel. Spring MVC ist Spring-spezifisch.“
Franz-Martin kam dazu: „Das ist der Grund warum ich beide Ansätze unterrichte. Die Realität nutzt beide. Banken migrieren von Java EE zu Spring Boot – sie brauchen Leute die BEIDE Welten kennen!“
Das ist die Realität: Beide Ansätze haben ihren Platz!
🆘 Troubleshooting
Problem 1: Jersey startet nicht
Lösung:
// JerseyConfig muss annotiert sein
@Configuration
@ApplicationPath("/api")
public class JerseyConfig extends ResourceConfig { }
Problem 2: Resource nicht gefunden
Lösung:
// Resource registrieren
public JerseyConfig() {
register(PersonResource.class); // WICHTIG!
}
// UND @Component auf Resource
@Component
@Path("/persons")
public class PersonResource { }
❓ FAQ
Q: Wann JAX-RS, wann Spring MVC?
A: JAX-RS für Portabilität und Enterprise. Spring MVC für neue Spring Boot Apps.
Q: Kann ich beide in einer App nutzen?
A: Ja! /api/* mit JAX-RS, /spring/* mit Spring MVC. Beide parallel möglich!
Q: Funktioniert Spring DI in JAX-RS?
A: Ja, wenn die Resource @Component ist! Constructor Injection funktioniert.
Q: Was ist besser?
A: Keins ist „besser“ – beide haben Use Cases. JAX-RS = Standard & portabel, Spring MVC = Spring-integriert.
📅 Morgen: Tag 10 – Integration & Abschluss!
Letzter Kurstag:
- Projekt-Integration aller Themen
- Best Practices Zusammenfassung
- Production Deployment
- Was kommt danach?
Du hast 90% geschafft! 🎉
📚 Deine Fortschritts-Übersicht
| Tag | Status |
|---|---|
| ✅ 1-8 | ABGESCHLOSSEN! |
| ✅ 9 | ABGESCHLOSSEN! |
| → 10 | Morgen! |
Morgen ist der letzte Tag! 🚀
📥 Download & Ressourcen
Projekt: SpringBootJAXRS-v1.0.zip
Enthält:
- Jersey Integration
- PersonResource komplett
- Exception Handling
- Vergleich Spring MVC vs JAX-RS
Du kannst jetzt:
- ✅ JAX-RS verstehen
- ✅ Jersey in Spring Boot
- ✅ REST APIs mit Java Standards
- ✅ @Path, @GET, @POST nutzen
- ✅ Exception Handling
- ✅ Spring MVC vs JAX-RS
- ✅ Migration-Ready sein! 🚀
Keep coding, keep learning! 💙
Tags: #SpringBoot #JAXRS #Jersey #REST #JavaStandards #Migration #Tag9

