Skip to content

Commit 4398531

Browse files
committed
chore: updated app
1 parent 2b8dcbe commit 4398531

16 files changed

Lines changed: 177 additions & 67 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
HELP.md
22
target/
33
.mvn/wrapper/maven-wrapper.jar
4+
.mvn/wrapper/dists/
5+
.mvn/apache-maven-*/
46
!**/src/main/**/target/
57
!**/src/test/**/target/
68

README.md

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# DB-2 Ticket System Starter
22

3-
Dieses Projekt ist das kleine Spring-Boot-Starterprojekt fuer **Database Development**. Es ist bewusst kein fertiges Ticket-System. Die Anwendung zeigt die Layer-Struktur, laeuft gegen PostgreSQL und enthaelt gezielte Luecken, damit die Datenbanklogik im Unterricht selbst entwickelt wird.
3+
Dieses Projekt ist das kleine Spring-Boot-Starterprojekt für **Database Development**. Es ist bewusst kein fertiges Ticket-System. Die Anwendung zeigt die Layer-Struktur, läuft gegen PostgreSQL und enthält gezielte Lücken, damit die Datenbanklogik im Unterricht selbst entwickelt wird.
44

55
## Technischer Rahmen
66

@@ -10,24 +10,25 @@ Dieses Projekt ist das kleine Spring-Boot-Starterprojekt fuer **Database Develop
1010
- Flyway
1111
- PostgreSQL
1212
- Maven Wrapper
13-
- Lombok fuer DTOs, Entities und einfache Datenklassen
13+
- Lombok für DTOs, Entities und einfache Datenklassen
14+
- Swagger UI und OpenAPI über springdoc-openapi
1415

1516
## Code-Guidelines
1617

1718
- Verwende in diesem Kursprojekt **keine Java Records**.
18-
- Verwende fuer einfache Datenklassen Lombok:
19-
- `@Value` fuer unveraenderliche Antwort-DTOs und Value-Objekte
20-
- `@Data` fuer JPA Entities, Request-DTOs und mutable Framework-Modelle
19+
- Verwende für einfache Datenklassen Lombok:
20+
- `@Value` für unveränderliche Antwort-DTOs und Value-Objekte
21+
- `@Data` für JPA Entities, Request-DTOs und mutable Framework-Modelle
2122
- Nutze Maven als Build-Werkzeug; der Maven Wrapper ist Teil des Projekts.
2223
- Schreibe modernen Java-24-Code. Nutze Streams dort, wo sie Lesbarkeit und Datenfluss verbessern, aber nicht als Selbstzweck.
23-
- Datenbankregeln gehoeren nicht nur in Java-Validierung. Zentrale Invarianten muessen auch in PostgreSQL sichtbar sein.
24+
- Datenbankregeln gehören nicht nur in Java-Validierung. Zentrale Invarianten müssen auch in PostgreSQL sichtbar sein.
2425

2526
## Start
2627

2728
Die DB-2-PostgreSQL-Umgebung muss laufen:
2829

2930
```bash
30-
cd ../../postgres
31+
cd ../db-2/postgres
3132
podman compose up -d
3233
```
3334

@@ -37,16 +38,16 @@ Danach kann die Anwendung gestartet werden:
3738
./mvnw spring-boot:run
3839
```
3940

40-
Die Anwendung verwendet die Datenbank `ticket_system` auf Port `5433`, schreibt aber in ein eigenes Schema `app_starter`. Dadurch bleibt das vollstaendige Unterrichtsschema aus `db-2/postgres` als Referenz erhalten.
41+
Die Anwendung verwendet die Datenbank `ticket_system` auf Port `5433`, schreibt aber in ein eigenes Schema `app_starter`. Dadurch bleibt das vollständige Unterrichtsschema aus `db-2/postgres` als Referenz erhalten.
4142

4243
## Guided Gaps
4344

44-
Die erste Migration ist absichtlich schwach. Sie laesst Dinge offen, die Studierende fachlich entscheiden sollen:
45+
Die erste Migration ist absichtlich schwach. Sie lässt Dinge offen, die Studierende fachlich entscheiden sollen:
4546

4647
- Welche Felder braucht ein minimales Ticket wirklich?
47-
- Welche Spalten duerfen nie `NULL` sein?
48-
- Welche Statuswerte gehoeren als `CHECK` Constraint in die Datenbank?
49-
- Welche Regeln gehoeren in PostgreSQL, welche in den Service-Layer?
48+
- Welche Spalten dürfen nie `NULL` sein?
49+
- Welche Statuswerte gehören als `CHECK` Constraint in die Datenbank?
50+
- Welche Regeln gehören in PostgreSQL, welche in den Service-Layer?
5051
- Welche Repository-Methode bleibt lesbar?
5152

5253
Normale Tests laufen mit:
@@ -61,29 +62,29 @@ Ein Integrationstest mit Testcontainers startet eine frische PostgreSQL-Datenban
6162
./mvnw -Ptestcontainers test
6263
```
6364

64-
Ein Docker-Compose-Test gegen die lokale DB-2-PostgreSQL-Umgebung laeuft mit:
65+
Ein Docker-Compose-Test gegen die lokale DB-2-PostgreSQL-Umgebung läuft mit:
6566

6667
```bash
67-
cd ../../postgres
68+
cd ../db-2/postgres
6869
podman compose up -d
69-
cd ../app/ticket-system-java
70+
cd ../../db-2-app
7071
./mvnw -Pdocker-compose test
7172
```
7273

73-
Die aktivierbare Engineering-Aufgabe laeuft mit:
74+
Die aktivierbare Engineering-Aufgabe läuft mit:
7475

7576
```bash
7677
./mvnw -Pguided-gaps test
7778
```
7879

79-
Dieser Test schlaegt am Anfang erwartbar fehl. Er wird erst gruen, wenn die Migration datenbankseitige Regeln enthaelt.
80+
Dieser Test schlägt am Anfang erwartbar fehl. Er wird erst grün, wenn die Migration datenbankseitige Regeln enthält.
8081

8182
## Teststrategie
8283

8384
- `./mvnw test`: schnelle Tests ohne Docker.
8485
- `./mvnw -Ptestcontainers test`: echte PostgreSQL-Integration mit isolierter Testcontainers-Datenbank.
85-
- `./mvnw -Pdocker-compose test`: Pruefung gegen die Kursdatenbank aus `db-2/postgres/docker-compose.yml`.
86-
- `./mvnw -Pguided-gaps test`: bewusst fehlschlagende Engineering-Aufgabe fuer fehlende Datenbankregeln.
86+
- `./mvnw -Pdocker-compose test`: Prüfung gegen die Kursdatenbank aus `db-2/postgres/docker-compose.yml`.
87+
- `./mvnw -Pguided-gaps test`: bewusst fehlschlagende Engineering-Aufgabe für fehlende Datenbankregeln.
8788

8889
## Docker
8990

@@ -95,19 +96,27 @@ podman compose up --build
9596

9697
Danach ist die API unter `http://localhost:8080/api/tickets` erreichbar.
9798

98-
## API fuer Block 2
99+
## Swagger und OpenAPI
100+
101+
Die API-Dokumentation ist in der laufenden Anwendung verfügbar:
102+
103+
- Root: `http://localhost:8080/` leitet auf Swagger UI weiter.
104+
- Swagger UI: `http://localhost:8080/swagger-ui.html`
105+
- OpenAPI JSON: `http://localhost:8080/v3/api-docs`
106+
107+
## API für Block 2
99108

100109
```http
101110
GET /api/tickets
102111
GET /api/tickets?status=open
103112
POST /api/tickets
104113
```
105114

106-
Beispiel fuer `POST /api/tickets`:
115+
Beispiel für `POST /api/tickets`:
107116

108117
```json
109118
{
110-
"title": "Datenbankverbindung pruefen",
119+
"title": "Datenbankverbindung prüfen",
111120
"status": "open"
112121
}
113122
```

compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
services:
22
postgres:
3-
image: postgres:17-alpine
3+
image: postgres:17
44
environment:
55
POSTGRES_DB: ticket_system
66
POSTGRES_USER: ticket_user

pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@
3939
<groupId>org.springframework.boot</groupId>
4040
<artifactId>spring-boot-starter-flyway</artifactId>
4141
</dependency>
42+
<dependency>
43+
<groupId>org.springdoc</groupId>
44+
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
45+
<version>3.0.3</version>
46+
</dependency>
4247
<dependency>
4348
<groupId>org.flywaydb</groupId>
4449
<artifactId>flyway-database-postgresql</artifactId>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package ch.hftm.db2.ticketsystem;
2+
3+
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
4+
import io.swagger.v3.oas.annotations.info.Info;
5+
import org.springframework.context.annotation.Configuration;
6+
7+
@Configuration
8+
@OpenAPIDefinition(
9+
info = @Info(
10+
title = "DB-2 Ticket System API",
11+
version = "0.1.0",
12+
description = "Spring-Boot-Starterprojekt für DB-2 mit bewusst offenen Guided Gaps in der Datenbanklogik."
13+
)
14+
)
15+
class OpenApiConfig {
16+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package ch.hftm.db2.ticketsystem;
2+
3+
import io.swagger.v3.oas.annotations.Hidden;
4+
import org.springframework.stereotype.Controller;
5+
import org.springframework.web.bind.annotation.GetMapping;
6+
7+
@Hidden
8+
@Controller
9+
class SwaggerRedirectController {
10+
11+
@GetMapping("/")
12+
String redirectToSwagger() {
13+
return "redirect:/swagger-ui.html";
14+
}
15+
}

src/main/java/ch/hftm/db2/ticketsystem/ticket/CreateTicketRequest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package ch.hftm.db2.ticketsystem.ticket;
22

3+
import io.swagger.v3.oas.annotations.media.Schema;
34
import jakarta.validation.constraints.NotBlank;
45
import lombok.AllArgsConstructor;
56
import lombok.Data;
@@ -8,11 +9,14 @@
89
@Data
910
@NoArgsConstructor
1011
@AllArgsConstructor
12+
@Schema(description = "Eingabe für ein neues Starter-Ticket")
1113
class CreateTicketRequest {
1214

1315
@NotBlank
16+
@Schema(description = "Kurzer Tickettitel", example = "Datenbankverbindung prüfen")
1417
private String title;
1518

1619
@NotBlank
20+
@Schema(description = "Ticketstatus im Starterprojekt", example = "open")
1721
private String status;
1822
}

src/main/java/ch/hftm/db2/ticketsystem/ticket/TicketController.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
package ch.hftm.db2.ticketsystem.ticket;
22

3+
import io.swagger.v3.oas.annotations.Operation;
4+
import io.swagger.v3.oas.annotations.Parameter;
5+
import io.swagger.v3.oas.annotations.tags.Tag;
36
import jakarta.validation.Valid;
4-
import java.util.List;
57
import org.springframework.http.HttpStatus;
6-
import org.springframework.web.bind.annotation.GetMapping;
7-
import org.springframework.web.bind.annotation.PostMapping;
8-
import org.springframework.web.bind.annotation.RequestBody;
9-
import org.springframework.web.bind.annotation.RequestMapping;
10-
import org.springframework.web.bind.annotation.RequestParam;
11-
import org.springframework.web.bind.annotation.ResponseStatus;
12-
import org.springframework.web.bind.annotation.RestController;
8+
import org.springframework.web.bind.annotation.*;
9+
10+
import java.util.List;
1311

1412
@RestController
1513
@RequestMapping("/api/tickets")
14+
@Tag(name = "Tickets", description = "Ticket Controller")
1615
class TicketController {
1716

1817
private final TicketService ticketService;
@@ -22,14 +21,18 @@ class TicketController {
2221
}
2322

2423
@GetMapping
25-
List<TicketResponse> findTickets(@RequestParam(required = false) String status) {
24+
@Operation(summary = "Tickets lesen", description = "Liest alle Tickets oder filtert nach einem Status.")
25+
List<TicketResponse> findTickets(
26+
@Parameter(description = "Optionaler Statusfilter, zum Beispiel open")
27+
@RequestParam(required = false) String status
28+
) {
2629
return ticketService.findTickets(status);
2730
}
2831

2932
@PostMapping
3033
@ResponseStatus(HttpStatus.CREATED)
34+
@Operation(summary = "Ticket erstellen", description = "Erstellt ein minimales Ticket im Starter-Schema app_starter.")
3135
TicketResponse createTicket(@Valid @RequestBody CreateTicketRequest request) {
3236
return ticketService.createTicket(request);
3337
}
3438
}
35-

src/main/java/ch/hftm/db2/ticketsystem/ticket/TicketEntity.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
package ch.hftm.db2.ticketsystem.ticket;
22

3-
import jakarta.persistence.Column;
4-
import jakarta.persistence.Entity;
5-
import jakarta.persistence.GeneratedValue;
6-
import jakarta.persistence.GenerationType;
7-
import jakarta.persistence.Id;
8-
import jakarta.persistence.Table;
9-
import java.time.OffsetDateTime;
3+
import jakarta.persistence.*;
104
import lombok.AccessLevel;
115
import lombok.Data;
126
import lombok.NoArgsConstructor;
137

8+
import java.time.OffsetDateTime;
9+
1410
@Entity
1511
@Table(name = "tickets", schema = "app_starter")
1612
@Data

src/main/java/ch/hftm/db2/ticketsystem/ticket/TicketRepository.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package ch.hftm.db2.ticketsystem.ticket;
22

3-
import java.util.List;
43
import org.springframework.data.jpa.repository.JpaRepository;
54

5+
import java.util.List;
6+
67
interface TicketRepository extends JpaRepository<TicketEntity, Long> {
78

89
List<TicketEntity> findByStatusOrderByCreatedAtDesc(String status);

0 commit comments

Comments
 (0)