Fachlicher Vertrag: unverändert zu erhalten
- Absender, Empfänger, Betreff, Body und Charset bleiben kompatibel.
- Header Injection wird verhindert.
- Transportfehler sind wiederholbar und nachvollziehbar.
javax.mail MimeMessage wird nachvollziehbar in Jakarta Mail und Mail Gateway ü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 | explizite Java-Abstraktionen | Annotationen und Containerfunktionen werden nur dort eingesetzt, wo sie eine konkrete technische Verantwortung übernehmen. |
| Abhängigkeiten | 2 direkte Dependencies | 2 direkte Dependencies | 1 neu, 1 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 LegacyMailFactory | class JakartaMailGateway, record MailCommand | 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 | Parallelbetrieb, Replay/Retry und Rückrouting müssen vor Abschaltung des Legacy-Pfads erprobt sein. |
| 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. |
header injection, transport errors and charset drift
recipient validation, Unicode, transport failure and header tests
Die Zuordnung ist semantisch: Eine Legacy-Klasse kann in mehrere moderne Rollen zerlegt werden.
| Legacy-Rolle / Datei | Modern-Rolle / Datei | Bedeutung |
|---|---|---|
| LegacyMailFactory.java | MailCommand.java + JakartaMailGateway.java | Message-Erzeugung wird validiertes Kommando plus Gateway. |
| Datei | Typ | Annotationen | öffentliche API | Pattern | Zeilen |
|---|---|---|---|---|---|
| LegacyMailFactory.java | class LegacyMailFactory | — | MimeMessage create(String from, String to, String subject, String body) | Factory – erzeugt vorkonfigurierte MimeMessage-Objekte. | 18 |
| Datei | Typ | Annotationen | öffentliche API | Pattern | Zeilen |
|---|---|---|---|---|---|
| JakartaMailGateway.java | class JakartaMailGateway | — | MimeMessage prepare(MailCommand c) void send(MailCommand c) | Gateway | 27 |
| MailCommand.java | record MailCommand | — | — | Command | 6 |
| Status | Dependency | Version | Scope | Prüfung |
|---|---|---|---|---|
| ENTFERNT | com.sun.mail:javax.mail | 1.6.2 | compile | Legacy-Laufzeit entfällt oder wird durch Plattform/BOM ersetzt. |
| NEU | org.eclipse.angus:jakarta.mail | 2.0.3 | compile | Neue Laufzeit-/Testabhängigkeit; transitiv, lizenz- und security-seitig prüfen. |
| 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: Message-Erzeugung wird validiertes Kommando plus Gateway.
projects/33-smtp-mail/legacy/src/main/java/at/aydin/lab/mail/legacy/LegacyMailFactory.java
package at.aydin.lab.mail.legacy;
// Design Pattern: Factory – erzeugt vorkonfigurierte MimeMessage-Objekte.
import javax.mail.*;
import javax.mail.internet.*;
import java.util.*;
public final class LegacyMailFactory {
public MimeMessage create(String from, String to, String subject, String body) throws Exception {
Session session = Session.getDefaultInstance(new Properties());
MimeMessage m = new MimeMessage(session);
m.setFrom(new InternetAddress(from));
m.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
m.setSubject(subject, "UTF-8");
m.setText(body, "UTF-8");
return m;
}
}
projects/33-smtp-mail/modern/src/main/java/at/aydin/lab/mail/modern/MailCommand.java
package at.aydin.lab.mail.modern;
// Design Pattern: Command
// Zweck: Vollständiger Versandauftrag wird als unveränderliches Objekt übergeben.
public record MailCommand(String from, String to, String subject, String body) {
}
projects/33-smtp-mail/modern/src/main/java/at/aydin/lab/mail/modern/JakartaMailGateway.java
package at.aydin.lab.mail.modern;
import jakarta.mail.*;
import jakarta.mail.internet.*;
import java.util.*;
// Design Pattern: Gateway
// Zweck: Jakarta-Mail-API bleibt außerhalb des fachlichen Aufrufers.
public final class JakartaMailGateway {
private final Session session;
public JakartaMailGateway(Properties properties) {
session = Session.getInstance(properties);
}
public MimeMessage prepare(MailCommand c) throws Exception {
MimeMessage m = new MimeMessage(session);
m.setFrom(new InternetAddress(c.from()));
m.setRecipient(Message.RecipientType.TO, new InternetAddress(c.to()));
m.setSubject(c.subject(), "UTF-8");
m.setText(c.body(), "UTF-8");
return m;
}
public void send(MailCommand c) throws Exception {
Transport.send(prepare(c));
}
}
| ID | Ebene | Prüfung | erforderlicher Nachweis |
|---|---|---|---|
| 33-SMTP-MAIL-A01 | Integration/Contract | Unicode-Inhalte kommen korrekt an. | Automatisierter Test und CI-Protokoll |
| 33-SMTP-MAIL-A02 | Integration/Contract | CR/LF in Headerfeldern wird abgewiesen. | Automatisierter Test und CI-Protokoll |
| 33-SMTP-MAIL-A03 | Integration/Contract | Transportfehler enthalten Empfänger-/Correlation-Kontext ohne Body-Leak. | Automatisierter Test und CI-Protokoll |
| 33-SMTP-MAIL-A04 | Integration/Contract | TLS/Auth-Konfiguration ist externisiert. | Automatisierter Test und CI-Protokoll |
| 33-SMTP-MAIL-A05 | Integration/Contract | Keine javax.mail-Imports im Modern-Modul. | Automatisierter Test und CI-Protokoll |
| 33-SMTP-MAIL-T01 | Unit | Fachlogik ohne Container oder externen Dienst testen. | Unit-Test |
| 33-SMTP-MAIL-T02 | Regression | Legacy- und Modern-Ergebnis für denselben Golden-Master-Vektor vergleichen. | Vergleichsreport |
| 33-SMTP-MAIL-T03 | Negative | Fehlerhafte, leere und grenzwertige Eingaben prüfen. | Negativtest |
| 33-SMTP-MAIL-T04 | Operations | Start, Health, Shutdown und Konfigurationsfehler prüfen. | Deployment-/Startprotokoll |
| 33-SMTP-MAIL-T05 | Contract | Protokoll, Status/Headers, Payload und Timeout gegen Consumer Contract prüfen. | Contract-Test |
| 33-SMTP-MAIL-F01 | Fokus | recipient validation, Unicode, transport failure and header tests | Modulspezifischer Testreport |
| Risiko | Auswirkung | Gegenmaßnahme | Gate |
|---|---|---|---|
| header injection, transport errors and charset drift | NIEDRIG | recipient validation, Unicode, transport failure and header tests | vor Cutover |
| Neue Framework-/Library-Laufzeitabhängigkeiten | MITTEL | SBOM, Lizenz-, CVE- und transitive Dependency-Prüfung im Online-Build | vor Release |
| Legacy-Verhalten war implizit an entfernte Library gekoppelt | MITTEL | Contract-/Golden-Master-Tests und gezielte Fehlerpfade | vor Abschaltung |
Keine zusätzlichen Ressourcen.
MailCommand bleibt stabil; ein LegacyMailAdapter kann temporär denselben Command über javax.mail senden.