enhancement
major
minor
defect
critical
major
minor
minor
#30265
TL-Script: try() gibt bei throw() und TopLogicException nur den Text der Meldung statt des ResKey an catch
Hintergrund
Eine Ansicht soll einen Fehler beim Lesen eines Inhalts abfangen und die Meldung selbst anzeigen, statt dass die Auswahl scheitert. Beispiel: Die Vorschau eines Dokuments, dessen Inhalt in einem nicht angeschlossenen Fremdsystem liegt.
Problem
Laut Doku bekommt die catch-Funktion von try($eval, $catch) „für eine I18NException den ResKey, sonst den Fehlertext“. Try.internalEval prüft dafür e instanceof I18NException. Die Fehler, die in TL-Script üblich sind, sind aber I18NRuntimeExceptions:
- throw(#"my.key") (Laufzeitfehler mit ResKey)
- TopLogicException aus Java-Funktionen
Für sie bekommt catch nur e.getMessage(), also den Text in der Sprache des Servers (hier Englisch), nicht den ResKey. Eine deutschsprachige Oberfläche zeigt die Meldung dann englisch an. Die Meldung des Befehls (Fehlerdialog bzw. Hinweis) ist dagegen richtig übersetzt.
Version: 8.0.0-alpha12 (com.top_logic.model.search.expr.Try).
Reproduktion
- In einer deutschsprachigen Sitzung auswerten: try(throw(#"tl.some.key"), catch: m -> v -> $m) mit einem Schlüssel, der eine deutsche Übersetzung hat.
- Ergebnis: ein String mit dem englischen Text (bzw. dem Schlüssel), kein ResKey.
Erwartetes Verhalten
Für jede Ausnahme mit Fehlerschlüssel (I18NException und I18NRuntimeException) bekommt catch den ResKey.
Umgehung
Die Vorschau zeigt einen allgemeinen Text („Der Inhalt dieser Version kann nicht gelesen werden …“) und schreibt den Grund als WARN ins Log; den genauen Grund meldet das Herunterladen.
Lösung
try() übergibt der catch-Funktion die Fehlermeldung als ResKey (Try prüft auf I18NFailure, die gemeinsame Schnittstelle von I18NException und I18NRuntimeException). Die Meldung wird damit in der Sprache der Oberfläche angezeigt. Das gilt für
- den Fehler aus throw(), auch wenn throw() ein einfacher Text übergeben wurde (dann ein literaler ResKey mit diesem Text),
- Fehler von Funktionen: eine TopLogicException liefert ihren Schlüssel, jede andere Java-Ausnahme wird von der Auswertung ohnehin mit dem Schlüssel „Auswertung von ... fehlgeschlagen“ gemeldet.
Dabei behoben:
- Der Schlüssel „Auswertung von ... fehlgeschlagen“ (SearchExpression.evalWith) enthielt den lebenden Auswertungskontext. Bindet die catch-Funktion die Meldung an eine Variable dieses Kontexts, enthielt der Schlüssel sich selbst; jede Textdarstellung (localize(), toString(), log()) endete in einem StackOverflowError. Der Schlüssel enthält jetzt die Variablenbelegung zum Zeitpunkt des Fehlers als Text.
- log(message, args...) setzte einen ResKey als Argument mit seiner internen Kodierung in die Meldung ein. Er wird jetzt als übersetzter Text eingesetzt, z.B. bei catch: e -> log("... Grund: {0}", $e).
Die Hilfeseite der Funktion try beschreibt das Verhalten.
Migration
Die catch-Funktion von try() bekommt die Fehlermeldung immer als ResKey, nicht mehr als Zeichenkette. Zur Anzeige und in log() ist keine Anpassung nötig. Ein Skript, das die Meldung als Zeichenkette weiterverarbeitet (Länge, regulärer Ausdruck, Vergleich mit einem String, Verkettung), wandelt sie vorher mit localize() um:
try(..., catch: msg -> $msg.localize().contains("..."))
Test
- test.com.top_logic.model.search.expr.TestTryCatch
- test.com.top_logic.model.search.expr.TestLog