(fix) Implementiere einen Service-Layer

Erstellung von DTOs für alle Ressourcen
Implement a versioning system
This commit is contained in:
2025-06-30 22:25:35 +02:00
parent 418e692092
commit e2432510af
28 changed files with 4102 additions and 14 deletions
+272
View File
@@ -0,0 +1,272 @@
# API Versioning Implementation
## Übersicht
Dieses Dokument beschreibt die implementierte Versionierungsstrategie für die Meldestelle API. Das System unterstützt sowohl DTO-Versionierung als auch API-Versionierung für eine saubere Evolution der API.
## Architektur
### 1. DTO Versionierung
Alle DTOs implementieren das `VersionedDto` Interface, welches folgende Eigenschaften bereitstellt:
```kotlin
interface VersionedDto {
val schemaVersion: String
val dataVersion: Long?
}
```
#### Beispiel Implementation:
```kotlin
@Serializable
@Since("1.0")
data class ArtikelDto(
@Serializable(with = UuidSerializer::class)
val id: Uuid,
val bezeichnung: String,
// ... andere Felder
override val schemaVersion: String = "1.0",
override val dataVersion: Long? = null
) : VersionedDto
```
### 2. Version Manager
Der `VersionManager` verwaltet API-Versionen und Kompatibilität:
```kotlin
object VersionManager {
const val CURRENT_API_VERSION = "1.0"
val SUPPORTED_VERSIONS = listOf("1.0")
val DEPRECATED_VERSIONS = emptyList<String>()
const val MINIMUM_CLIENT_VERSION = "1.0"
}
```
### 3. API Versioning Plugin
Das Ktor-Plugin `VersioningPlugin` behandelt:
- Version-Header Validierung
- Automatische Version-Header in Responses
- Deprecation Warnings
- Unsupported Version Errors
## Verwendung
### Client-seitige Version Headers
Clients können die API-Version über Header spezifizieren:
```http
GET /api/artikel
API-Version: 1.0
```
oder
```http
GET /api/artikel
X-API-Version: 1.0
```
### Server Response Headers
Der Server antwortet mit Version-Informationen:
```http
HTTP/1.1 200 OK
API-Version: 1.0
X-Supported-Versions: 1.0
```
### Versioned Responses
Verwende die Extension-Funktionen für versionierte Antworten:
```kotlin
// Einzelnes DTO
call.respondVersioned(HttpStatusCode.OK, artikelDto)
// Liste von DTOs
call.respondVersionedList(HttpStatusCode.OK, artikelList)
```
## Migration System
### VersionMigrator Interface
```kotlin
interface VersionMigrator<T : VersionedDto> {
fun migrate(dto: T, fromVersion: String, toVersion: String): T
fun canMigrate(fromVersion: String, toVersion: String): Boolean
}
```
### Beispiel Migrator
```kotlin
class ArtikelDtoMigrator : VersionMigrator<ArtikelDto> {
override fun migrate(dto: ArtikelDto, fromVersion: String, toVersion: String): ArtikelDto {
return when {
fromVersion == "1.0" && toVersion == "1.1" -> migrateFrom1_0To1_1(dto)
else -> throw IllegalArgumentException("Unsupported migration")
}
}
private fun migrateFrom1_0To1_1(dto: ArtikelDto): ArtikelDto {
return dto.copy(
schemaVersion = "1.1",
// Neue Felder mit Standardwerten hinzufügen
)
}
}
```
## Annotations
### @Since(version)
Markiert, seit welcher Version ein DTO oder Feld verfügbar ist.
### @Deprecated(version, message)
Markiert veraltete DTOs oder Felder.
### @Until(version)
Markiert, bis zu welcher Version ein DTO oder Feld verfügbar war.
## Best Practices
### 1. Neue API Version hinzufügen
1. **VersionManager aktualisieren:**
```kotlin
const val CURRENT_API_VERSION = "1.1"
val SUPPORTED_VERSIONS = listOf("1.1", "1.0")
val DEPRECATED_VERSIONS = listOf("1.0")
```
2. **DTOs erweitern:**
```kotlin
@Serializable
@Since("1.1")
data class ArtikelDto(
// Bestehende Felder...
@Since("1.1")
val neuesFeld: String? = null,
override val schemaVersion: String = "1.1"
) : VersionedDto
```
3. **Migrator implementieren:**
```kotlin
class ArtikelDtoMigrator : VersionMigrator<ArtikelDto> {
override fun migrate(dto: ArtikelDto, fromVersion: String, toVersion: String): ArtikelDto {
return when {
fromVersion == "1.0" && toVersion == "1.1" -> migrateFrom1_0To1_1(dto)
// Weitere Migrationen...
}
}
}
```
### 2. Backward Compatibility
- Neue Felder sollten optional sein (nullable oder mit Standardwerten)
- Bestehende Felder nicht entfernen, sondern als @Deprecated markieren
- Migratoren für alle unterstützten Versionsübergänge bereitstellen
### 3. Breaking Changes
Bei Breaking Changes:
1. Neue Major Version erstellen
2. Alte Version als deprecated markieren
3. Migration Path bereitstellen
4. Dokumentation aktualisieren
## Beispiel API Calls
### Erfolgreiche Anfrage
```http
GET /api/artikel
API-Version: 1.0
HTTP/1.1 200 OK
API-Version: 1.0
X-Supported-Versions: 1.0
Content-Type: application/json
```
### Unsupported Version
```http
GET /api/artikel
API-Version: 2.0
HTTP/1.1 400 Bad Request
Content-Type: application/json
```
### Deprecated Version Warning
```http
GET /api/artikel
API-Version: 0.9
HTTP/1.1 200 OK
API-Version: 1.0
X-API-Version-Warning: Version 0.9 is deprecated
```
## Testing
Das Versioning System wird durch `VersioningTest.kt` getestet:
```bash
./gradlew test --tests "at.mocode.VersioningTest"
```
## Implementierte DTOs
Folgende DTOs wurden bereits mit Versionierung ausgestattet:
-`ArtikelDto`, `CreateArtikelDto`, `UpdateArtikelDto`
-`VereinDto`, `CreateVereinDto`, `UpdateVereinDto`
### Noch zu implementieren:
- `AbteilungDto`
- `BewerbDto`
- `DomaeneDto`
- `StammdatenDto`
- `TurnierDto`
- `VeranstaltungDto`
- `CommonDto` (alle Klassen)
- `SpecializedDto`
## Nächste Schritte
1. Alle verbleibenden DTOs mit Versionierung ausstatten
2. API Routes auf DTO-Verwendung umstellen
3. Versioning Plugin in Application.kt aktivieren
4. Client-seitige Version-Header Implementation
5. Monitoring für Version-Usage implementieren
### Noch zu implementieren:
- `AbteilungDto`
- `BewerbDto`
- `DomaeneDto`
- `StammdatenDto`
- `TurnierDto`
- `VeranstaltungDto`
- `CommonDto` (alle Klassen)
- `SpecializedDto`
## Nächste Schritte
1. Alle verbleibenden DTOs mit Versionierung ausstatten
2. API Routes auf DTO-Verwendung umstellen
3. Versioning Plugin in Application.kt aktivieren
4. Client-seitige Version-Header Implementation
5. Monitoring für Version-Usage implementieren