Fachlicher Vertrag: unverändert zu erhalten
- Timeout, Redirect, Encoding und Nicht-2xx-Verhalten sind Teil des Vertrags.
- Fachlogik hängt nur vom TextTransport-Port ab.
- Tests benötigen keinen externen Internetdienst.
HttpURLConnection wird nachvollziehbar in Java HttpClient mit Transport-Port überführt. Die Akte zeigt nicht nur das Ziel, sondern die tatsächlichen Dateien, APIs, Dependencies, Codebelege, Tests, Risiken und Cutover-Schritte.
| Dimension | Legacy | Modern | Migrationskonsequenz |
|---|---|---|---|
| Programmiermodell | imperativ / ohne Framework-Annotationen | FunctionalInterface | Annotationen und Containerfunktionen werden nur dort eingesetzt, wo sie eine konkrete technische Verantwortung übernehmen. |
| Abhängigkeiten | 1 direkte Dependencies | 1 direkte Dependencies | 0 neu, 0 entfernt; Versionen und transitive Auswirkungen im erfolgreichen Online-Build prüfen. |
| Öffentliche API | 1 erkannte Methoden | 2 erkannte Methoden | Methoden werden nach fachlicher Rolle gemappt; reine Bootstrap- und Framework-Methoden sind kein fachlicher Vertrag. |
| Datenmodell | class LegacyHttpClient | class JavaHttpTransport, class PageTitleService, interface TextTransport | Feldnamen, IDs, Null-Semantik, Gleichheit und Serialisierungsform werden separat regressionstestet. |
| Fehlerverhalten | Legacy-Exceptions und Rückgabewerte | explizitere Fach-/Framework-Fehlerabbildung | Fehler dürfen nicht nur technisch übersetzt werden; Status, Ursache, Retrybarkeit und Client-Vertrag müssen erhalten oder versioniert werden. |
| Tests | Bestands- und Golden-Master-Tests | Unit-, Slice-, Contract- und Integrationstests | Der Modern-Pfad wird zuerst gegen denselben fachlichen Vektor geprüft und danach um neue technische Risiken ergänzt. |
| Betrieb | Legacy-Start/Lifecycle | modernes Packaging, Health und externe Konfiguration | CI-Mischbetrieb nur zeitlich begrenzt; keine still deaktivierten Tests. |
| Rollback | Legacy-Artefakt bleibt unverändert | Modern-Artefakt getrennt deploybar | Kein Rollback über Datenverlust: Schema, Nachrichten und verschlüsselte Daten müssen rückwärtslesbar oder durch Dual-Read abgesichert sein. |
timeouts, redirects and encoding
timeout, non-2xx, headers, redirect and body-size tests
Die Zuordnung ist semantisch: Eine Legacy-Klasse kann in mehrere moderne Rollen zerlegt werden.
| Legacy-Rolle / Datei | Modern-Rolle / Datei | Bedeutung |
|---|---|---|
| LegacyHttpClient.java | JavaHttpTransport.java | HttpURLConnection wird Java HttpClient Adapter. |
| direkter Transportaufruf | TextTransport.java + PageTitleService.java | Port trennt Transport von Fachauswertung. |
| Datei | Typ | Annotationen | öffentliche API | Pattern | Zeilen |
|---|---|---|---|---|---|
| LegacyHttpClient.java | class LegacyHttpClient | — | String get(String url) | Adapter – kapselt HttpURLConnection hinter einer kleinen Client-API. | 18 |
| Datei | Typ | Annotationen | öffentliche API | Pattern | Zeilen |
|---|---|---|---|---|---|
| JavaHttpTransport.java | class JavaHttpTransport | — | String get(URI uri) | Adapter | 16 |
| PageTitleService.java | class PageTitleService | — | String title(URI uri) | — | 17 |
| TextTransport.java | interface TextTransport | FunctionalInterface | — | Port | 10 |
| Status | Dependency | Version | Scope | Prüfung |
|---|---|---|---|---|
| BEIBEHALTEN | org.junit.jupiter:junit-jupiter | BOM/Parent → BOM/Parent | test → test | Gemeinsame Dependency; Version und Scope im effektiven POM prüfen. |
Die folgenden Ausschnitte stammen direkt aus den enthaltenen Projekten. Dadurch ist sichtbar, welche Verantwortung tatsächlich verschoben wurde.
Migrationsbedeutung: HttpURLConnection wird Java HttpClient Adapter.
projects/20-http-client-testing/legacy/src/main/java/at/aydin/lab/http/legacy/LegacyHttpClient.java
package at.aydin.lab.http.legacy;
// Design Pattern: Adapter – kapselt HttpURLConnection hinter einer kleinen Client-API.
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
public final class LegacyHttpClient {
public String get(String url) throws IOException {
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("GET");
try (InputStream in = connection.getInputStream()) {
return new String(in.readAllBytes(), StandardCharsets.UTF_8);
} finally {
connection.disconnect();
}
}
}
projects/20-http-client-testing/modern/src/main/java/at/aydin/lab/http/modern/JavaHttpTransport.java
package at.aydin.lab.http.modern;
import java.net.*;
import java.net.http.*;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
// Design Pattern: Adapter
// Zweck: Adaptiert java.net.http.HttpClient an den fachlichen TextTransport-Port.
public final class JavaHttpTransport implements TextTransport {
private final HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();
public String get(URI uri) throws Exception {
HttpRequest request = HttpRequest.newBuilder(uri).timeout(Duration.ofSeconds(10)).GET().build();
return client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)).body();
}
}
--- LegacyHttpClient.java
+++ JavaHttpTransport.java
@@ -1,18 +1,16 @@
-package at.aydin.lab.http.legacy;
+package at.aydin.lab.http.modern;
-// Design Pattern: Adapter – kapselt HttpURLConnection hinter einer kleinen Client-API.
-import java.io.*;
import java.net.*;
+import java.net.http.*;
import java.nio.charset.StandardCharsets;
+import java.time.Duration;
-public final class LegacyHttpClient {
- public String get(String url) throws IOException {
- HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
- connection.setRequestMethod("GET");
- try (InputStream in = connection.getInputStream()) {
- return new String(in.readAllBytes(), StandardCharsets.UTF_8);
- } finally {
- connection.disconnect();
- }
+// Design Pattern: Adapter
+// Zweck: Adaptiert java.net.http.HttpClient an den fachlichen TextTransport-Port.
+public final class JavaHttpTransport implements TextTransport {
+ private final HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build();
+ public String get(URI uri) throws Exception {
+ HttpRequest request = HttpRequest.newBuilder(uri).timeout(Duration.ofSeconds(10)).GET().build();
+ return client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)).body();
}
}
Migrationsbedeutung: Port trennt Transport von Fachauswertung.
projects/20-http-client-testing/legacy/src/main/java/at/aydin/lab/http/legacy/LegacyHttpClient.java
package at.aydin.lab.http.legacy;
// Design Pattern: Adapter – kapselt HttpURLConnection hinter einer kleinen Client-API.
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
public final class LegacyHttpClient {
public String get(String url) throws IOException {
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("GET");
try (InputStream in = connection.getInputStream()) {
return new String(in.readAllBytes(), StandardCharsets.UTF_8);
} finally {
connection.disconnect();
}
}
}
projects/20-http-client-testing/modern/src/main/java/at/aydin/lab/http/modern/TextTransport.java
package at.aydin.lab.http.modern;
import java.net.URI;
// Design Pattern: Port
// Zweck: HTTP-Transport wird für Tests und alternative Implementierungen austauschbar.
@FunctionalInterface
public interface TextTransport {
String get(URI uri) throws Exception;
}
projects/20-http-client-testing/modern/src/main/java/at/aydin/lab/http/modern/PageTitleService.java
package at.aydin.lab.http.modern;
import java.net.URI;
import java.util.regex.*;
public final class PageTitleService {
private static final Pattern TITLE = Pattern.compile("<title>(.*?)</title>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
private final TextTransport transport;
public PageTitleService(TextTransport transport) {
this.transport = transport;
}
public String title(URI uri) throws Exception {
Matcher m = TITLE.matcher(transport.get(uri));
return m.find() ? m.group(1).trim() : "";
}
}
| ID | Ebene | Prüfung | erforderlicher Nachweis |
|---|---|---|---|
| 20-HTTP-CLIENT-TESTING-A01 | Integration/Contract | Timeout tritt innerhalb definierter Grenze ein. | Automatisierter Test und CI-Protokoll |
| 20-HTTP-CLIENT-TESTING-A02 | Integration/Contract | Nicht-2xx wird nicht als Erfolg interpretiert. | Automatisierter Test und CI-Protokoll |
| 20-HTTP-CLIENT-TESTING-A03 | Integration/Contract | Unicode-Titel werden korrekt gelesen. | Automatisierter Test und CI-Protokoll |
| 20-HTTP-CLIENT-TESTING-A04 | Integration/Contract | Tests laufen offline gegen lokalen Server. | Automatisierter Test und CI-Protokoll |
| 20-HTTP-CLIENT-TESTING-A05 | Integration/Contract | Transport kann in Unit-Tests ersetzt werden. | Automatisierter Test und CI-Protokoll |
| 20-HTTP-CLIENT-TESTING-T01 | Unit | Fachlogik ohne Container oder externen Dienst testen. | Unit-Test |
| 20-HTTP-CLIENT-TESTING-T02 | Regression | Legacy- und Modern-Ergebnis für denselben Golden-Master-Vektor vergleichen. | Vergleichsreport |
| 20-HTTP-CLIENT-TESTING-T03 | Negative | Fehlerhafte, leere und grenzwertige Eingaben prüfen. | Negativtest |
| 20-HTTP-CLIENT-TESTING-T04 | Operations | Start, Health, Shutdown und Konfigurationsfehler prüfen. | Deployment-/Startprotokoll |
| 20-HTTP-CLIENT-TESTING-F01 | Fokus | timeout, non-2xx, headers, redirect and body-size tests | Modulspezifischer Testreport |
| Risiko | Auswirkung | Gegenmaßnahme | Gate |
|---|---|---|---|
| timeouts, redirects and encoding | NIEDRIG | timeout, non-2xx, headers, redirect and body-size tests | vor Cutover |
Keine zusätzlichen Ressourcen.
Ein zweiter TextTransport kann weiterhin HttpURLConnection nutzen; Umschaltung erfolgt an der Composition Root.