Modul 20 · Migration Deep Dive · Stufe 2 Java Core

HTTP-Client und Webtest

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.

AdapterPort
1 → 3Produktionsdateien
18 → 43Java-Zeilen
1 → 1Testdateien
0 / 0Dependencies entfernt / neu
NIEDRIGRisiko · Score 1

Was sich konkret ändert

DimensionLegacyModernMigrationskonsequenz
Programmiermodellimperativ / ohne Framework-AnnotationenFunctionalInterfaceAnnotationen und Containerfunktionen werden nur dort eingesetzt, wo sie eine konkrete technische Verantwortung übernehmen.
Abhängigkeiten1 direkte Dependencies1 direkte Dependencies0 neu, 0 entfernt; Versionen und transitive Auswirkungen im erfolgreichen Online-Build prüfen.
Öffentliche API1 erkannte Methoden2 erkannte MethodenMethoden werden nach fachlicher Rolle gemappt; reine Bootstrap- und Framework-Methoden sind kein fachlicher Vertrag.
Datenmodellclass LegacyHttpClientclass JavaHttpTransport, class PageTitleService, interface TextTransportFeldnamen, IDs, Null-Semantik, Gleichheit und Serialisierungsform werden separat regressionstestet.
FehlerverhaltenLegacy-Exceptions und Rückgabewerteexplizitere Fach-/Framework-FehlerabbildungFehler dürfen nicht nur technisch übersetzt werden; Status, Ursache, Retrybarkeit und Client-Vertrag müssen erhalten oder versioniert werden.
TestsBestands- und Golden-Master-TestsUnit-, Slice-, Contract- und IntegrationstestsDer Modern-Pfad wird zuerst gegen denselben fachlichen Vektor geprüft und danach um neue technische Risiken ergänzt.
BetriebLegacy-Start/Lifecyclemodernes Packaging, Health und externe KonfigurationCI-Mischbetrieb nur zeitlich begrenzt; keine still deaktivierten Tests.
RollbackLegacy-Artefakt bleibt unverändertModern-Artefakt getrennt deploybarKein Rollback über Datenverlust: Schema, Nachrichten und verschlüsselte Daten müssen rückwärtslesbar oder durch Dual-Read abgesichert sein.

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.

Hauptrisiko und Testfokus

timeouts, redirects and encoding

timeout, non-2xx, headers, redirect and body-size tests

Die Modernisierung gilt erst als abgeschlossen, wenn der fachliche Vertrag automatisiert belegt ist.

Verbindliches Code- und Rollenmapping

Die Zuordnung ist semantisch: Eine Legacy-Klasse kann in mehrere moderne Rollen zerlegt werden.

Legacy-Rolle / DateiModern-Rolle / DateiBedeutung
LegacyHttpClient.javaJavaHttpTransport.javaHttpURLConnection wird Java HttpClient Adapter.
direkter TransportaufrufTextTransport.java + PageTitleService.javaPort trennt Transport von Fachauswertung.

Legacy-Quellinventar

DateiTypAnnotationenöffentliche APIPatternZeilen
LegacyHttpClient.javaclass LegacyHttpClientString get(String url)Adapter – kapselt HttpURLConnection hinter einer kleinen Client-API.18

Dependency- und Laufzeitmigration

StatusDependencyVersionScopePrüfung
BEIBEHALTENorg.junit.jupiter:junit-jupiterBOM/Parent → BOM/Parenttest → testGemeinsame Dependency; Version und Scope im effektiven POM prüfen.
Direkte POM-Daten ersetzen keinen erfolgreichen Online-Build mit transitiver SBOM- und CVE-Prüfung.

Vorher-/Nachher-Codebelege

Die folgenden Ausschnitte stammen direkt aus den enthaltenen Projekten. Dadurch ist sichtbar, welche Verantwortung tatsächlich verschoben wurde.

Legacy
LegacyHttpClient.java
Modern
JavaHttpTransport.java

Migrationsbedeutung: HttpURLConnection wird Java HttpClient Adapter.

Legacy-Code

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();
        }
    }
}

Modern-Code

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();
    }
}
Technischen Unified Diff öffnen
--- 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();
     }
 }
Legacy
direkter Transportaufruf
Modern
TextTransport.java + PageTitleService.java

Migrationsbedeutung: Port trennt Transport von Fachauswertung.

Legacy-Code

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();
        }
    }
}

Modern-Code

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;
}

Modern-Code

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() : "";
    }
}

Umsetzungsplan mit Qualitäts-Gates

  1. Arbeitspaket 1
    LegacyHttpClient-Verhalten mit lokalem HTTP-Server erfassen. Nachweis: Commit/PR, automatisierter Test und aktualisierte Betriebsdokumentation.
  2. Arbeitspaket 2
    TextTransport als Port definieren und PageTitleService davon abhängig machen. Nachweis: Commit/PR, automatisierter Test und aktualisierte Betriebsdokumentation.
  3. Arbeitspaket 3
    JavaHttpTransport mit expliziten Timeouts und Headern implementieren. Nachweis: Commit/PR, automatisierter Test und aktualisierte Betriebsdokumentation.
  4. Arbeitspaket 4
    Nicht-2xx, Redirect und große Antworten behandeln. Nachweis: Commit/PR, automatisierter Test und aktualisierte Betriebsdokumentation.
  5. Arbeitspaket 5
    Deterministische lokale Integrationstests ergänzen. Nachweis: Commit/PR, automatisierter Test und aktualisierte Betriebsdokumentation.
  6. Arbeitspaket 6
    HttpURLConnection erst nach Vertragsvergleich entfernen. Nachweis: Commit/PR, automatisierter Test und aktualisierte Betriebsdokumentation.

Konkreter Test- und Abnahmekatalog

IDEbenePrüfungerforderlicher Nachweis
20-HTTP-CLIENT-TESTING-A01Integration/ContractTimeout tritt innerhalb definierter Grenze ein.Automatisierter Test und CI-Protokoll
20-HTTP-CLIENT-TESTING-A02Integration/ContractNicht-2xx wird nicht als Erfolg interpretiert.Automatisierter Test und CI-Protokoll
20-HTTP-CLIENT-TESTING-A03Integration/ContractUnicode-Titel werden korrekt gelesen.Automatisierter Test und CI-Protokoll
20-HTTP-CLIENT-TESTING-A04Integration/ContractTests laufen offline gegen lokalen Server.Automatisierter Test und CI-Protokoll
20-HTTP-CLIENT-TESTING-A05Integration/ContractTransport kann in Unit-Tests ersetzt werden.Automatisierter Test und CI-Protokoll
20-HTTP-CLIENT-TESTING-T01UnitFachlogik ohne Container oder externen Dienst testen.Unit-Test
20-HTTP-CLIENT-TESTING-T02RegressionLegacy- und Modern-Ergebnis für denselben Golden-Master-Vektor vergleichen.Vergleichsreport
20-HTTP-CLIENT-TESTING-T03NegativeFehlerhafte, leere und grenzwertige Eingaben prüfen.Negativtest
20-HTTP-CLIENT-TESTING-T04OperationsStart, Health, Shutdown und Konfigurationsfehler prüfen.Deployment-/Startprotokoll
20-HTTP-CLIENT-TESTING-F01Fokustimeout, non-2xx, headers, redirect and body-size testsModulspezifischer Testreport

Risikoregister des Moduls

RisikoAuswirkungGegenmaßnahmeGate
timeouts, redirects and encodingNIEDRIGtimeout, non-2xx, headers, redirect and body-size testsvor Cutover

Konfiguration und Ressourcen

Keine zusätzlichen Ressourcen.

Rollback und Koexistenz

Ein zweiter TextTransport kann weiterhin HttpURLConnection nutzen; Umschaltung erfolgt an der Composition Root.

Abbruchkriterien

  • Fachlicher Golden-Master weicht ab.
  • Daten-, Nachrichten- oder API-Kompatibilität ist ungeklärt.
  • Fehlerquote, Latenz oder Ressourcenverbrauch überschreiten das vereinbarte Limit.
  • Monitoring oder Rückfallpfad ist nicht funktionsfähig.

Definition of Done

Direkte Arbeitslinks

⌂ Cockpit