Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blockungsexport #327

Open
ws46 opened this issue Dec 31, 2024 · 39 comments
Open

Blockungsexport #327

ws46 opened this issue Dec 31, 2024 · 39 comments
Assignees

Comments

@ws46
Copy link

ws46 commented Dec 31, 2024

Ich habe versucht, über die REST-Schnittstelle eine Blockung in die DB zu exportieren. Das ist misslungen. Der Dateiname, wie verlangt, im Body.

Hier die Rückmeldung:

https://localhost/db/..../datenaustausch/gost/kurs42/import/zip
REST-Fehler: 415, Unsupported Media Type
C:\Users\Walter\AppData\Local\Temp\Kurs42.zip

Bezieht sich die Fehlermeldung auf das Format der zip-Datei oder das Format einer der in der Datei enthaltenen Textdateien?

@hmt
Copy link
Collaborator

hmt commented Dec 31, 2024

Der Export bzw Import bezieht sich auf diese Schnittstelle: debug/index.html#/Server/importKurs42Blockung?
Der Fehler kommt mir bekannt vor, da stimmt wahrscheinlich etwas nicht mit der Übergabe. Ich habe jetzt nicht geschaut, wie das außerhalb von JavaScript gemacht wird, aber ich erstelle in FormData-Objekt und setze die Datei auf den Schlüssel data:

const formData = new FormData();
formData.append("data", file);

@ws46
Copy link
Author

ws46 commented Dec 31, 2024

debug/index.html#/Server/importKurs42Blockung?

Genau.

@FPfotenhauer
Copy link
Contributor

Ich würde das Issue schließen, wenn hier keine weiteren Informationen getauscht werden.

@ws46
Copy link
Author

ws46 commented Jan 7, 2025

Ich wüsste schion gerne, ob es eine Lösung für das Problem gibt (bzw. geben wird)

@FPfotenhauer
Copy link
Contributor

Wir verstehen das Problem nicht, da es bei uns ja funktioniert.
Warum ist der Hinweis von @hmt nicht hilfreich?

@ws46
Copy link
Author

ws46 commented Jan 9, 2025

Warum ist der Hinweis von @hmt nicht hilfreich?

Meinst du den hier:

Der Fehler kommt mir bekannt vor, da stimmt wahrscheinlich etwas nicht mit der Übergabe.

Inwieweit das für mein Problem hilfreich sein soll, erschließt sich mir nicht. Ich habe das API, so wie hier

POST /db/{schema}/datenaustausch/gost/kurs42/import/zip
Importiert die Kurs 42-Blockung aus dem übergebenen ZIP-File in das Schema mit dem angegebenen Namen."

beschrieben, angewendet und bekomme den oben gemeldeten Fehler. Dass das bei euch funktioniert, hilft mir nicht weiter.

@hmt
Copy link
Collaborator

hmt commented Jan 9, 2025

Der Hinweis war der, dass die zip über das Feld data transportiert werden muss als multipart/formdata.

Klappt es denn über die Debug-Schnittstelle? Oder kommt der Fehler auch darüber? Unsupported Media Type klingt erstmal nach falscher Übertragung, nicht falscher Inhalt. Ich kann es hier so nicht reproduzieren.

@ws46
Copy link
Author

ws46 commented Jan 9, 2025

Der Hinweis war der, dass die zip über das Feld data transportiert werden muss als multipart/formdata.

Das hatte ich so nicht verstanden. Über die Debug-Schnittstelle klappt es. Das hilft mir jetzt weiter.

@hmt
Copy link
Collaborator

hmt commented Jan 9, 2025

wenn man im Firefox die Debug-Schnittstelle verwendet, dann kann man über Netzwerk in den Developer-Tools recht gut nachvollziehen, was passiert und welche Daten verschickt werden.

@ws46
Copy link
Author

ws46 commented Jan 9, 2025

Der Mediatype-Fehler ist beseitigt, dafür erhalte ich jetzt die Antwort

"id":null,"success":false,"log":["Erstelle eine temporäres Verzechnis mit dem Inhalt der Zip-Datei unter dem Namen
"C:\ProgramData\SVWS-Server/temp/svwsdb_ZSV80wuTxIVPPaerHNnQzft905B9rENQxKP78fIO.zip"","
[FEHLER] Unerwarteter Fehler: Cannot read the array length because "buf" is null"]}

Das temporäre Verzeichnist wird angelegt, bleibt aber leer. Ich hätte vermutet, dass das Verzeichnis vom SVWS-Server mit den Dateien der übergebenen Zip-Datei gefüllt wird.

@ws46
Copy link
Author

ws46 commented Jan 10, 2025

Es wird besser, aber Fehler bleiben. Zur Verdeutlichung ein Auszug aus dem Log:

Rest-Antwort: 400, Bad Request
{
"id":null,
"success":false,
"log":["Erstelle eine temporäres Verzechnis mit dem Inhalt der Zip-Datei unter dem Namen
"C:\ProgramData\SVWS-Server/temp/svwsdb_XVLNNfvnFFvGEtygYkShcyXER6sBg1XYkUhCDIwG.zip"",
"Importiere die Blockung mithilfe der extrahierten Daten:",
"-> Lese Informationen zu der Schule ein..."," [OK]",
"-> Bestimme die Schüler der Schule aus der Datenbank..."," [OK]",
"-> Bestimme die Lehrkräfte der Schule aus der Datenbank..."," [OK]",
"-> Bestimme die Fächer der Schule aus der Datenbank..."," [OK]",
"-> Lese die Kurs 42 - Export - Textdateien ein..."," [Fehler] - Fehler beim Einlesen des Kurs42-Text-Exports: ",
" java.nio.file.NoSuchFileException: C:\ProgramData\SVWS-Server\temp\svwsdb_XVLNNfvnFFvGEtygYkShcyXER6sBg1XYkUhCDIwG.zip\Blockung.txt

Die Datei existiert definitiv. Kann es sein, dass von Java durch den Backslash vor temp "\t" als Tabulator interpretiert wird?

@hmt
Copy link
Collaborator

hmt commented Jan 13, 2025

Verstehe ich das richtig, wenn die Daten über die Debug-Schnittstelle verschickt werden, klappt es, wenn es mit einer eigenen Methode über die API verschickt wird, geht es nicht?
Sobald die Daten auf dem Server angekommen sind, sollte es eigentlich egal sein, wie sie verschickt wurden. Dies sieht mir nach einem Zugriffsfehler aus. Kann der Server in dem Verzeichnis die Daten lesen? Schreiben kann er ja offensichtlich, wenn die Datei vorhanden ist. Das \t dürfte kein Problem sein.

@ws46
Copy link
Author

ws46 commented Jan 13, 2025

Verstehe ich das richtig, wenn die Daten über die Debug-Schnittstelle verschickt werden, klappt es

Ja. Der Export der identischen Datei aus Kurs 42 bricht mit der o.a. Fehlermeldung ab. In den Verzeichnissen (die ja bei der Installation des Servers angelegt wurden) bestehen alle notwendigen Rechte. Ausführung des Programmes als Administrator bringt keine Änderung. Ich bin ratlos.

@ws46
Copy link
Author

ws46 commented Jan 13, 2025

Das liefert das Ergebnislog:

Kursexport

@ws46
Copy link
Author

ws46 commented Jan 13, 2025

Der Fehler scheint darin zu bestehen, dass beim Aufruf des Endpunktes aus dem Programm das temporäre Verzeichnis unter einem anderen Namen als beim Aufruf über die Debug-Schnittstelle angelegt wird (s. Screenshot). Beim Versuch, die Dateien aus dem temporären Verzeichnis zu lesen, wird in beiden Fällen offensichtlich der gleiche Pfad (C:\ProgramData\SVWS-Server\temp\svwsdb_....zip\Blockung.txt) verwendet, was dann zu dem beschriebenen Fehler (Datei nicht gefunden, da das Verzeichnis nicht existiert) führt.

@hmt
Copy link
Collaborator

hmt commented Jan 13, 2025

wurde der Pfad in der svwsconfig.json festgelegt? Mit TempPath kann man einen eigenen Pfad bestimmen. Das ist der Pfad, der für die zips genutzt wird. Warum die slashes und backslashes gemischt werden, erschließt sich mir nicht ganz aus dem Java-Code. Probieren sie mal einen anderen Pfad und geben sie ihn absolut ein.

Der für den Pfad verantworliche Code ist dieser hier, da fällt mir nichts dran auf:

			final String tmpDirectory = SVWSKonfiguration.get().getTempPath();
			final String tmpFilename = conn.getUser().getConfig().getDBSchema() + "_" + _random.ints(48, 123)  // from 0 to z
					.filter(i -> ((i <= 57) || (i >= 65)) && ((i <= 90) || (i >= 97)))  // filter some unicode characters
					.limit(40)
					.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
					.toString() + ".zip";
			logger.logLn("Erstelle eine temporäres Verzechnis mit dem Inhalt der Zip-Datei unter dem Namen \"" + tmpDirectory + "/" + tmpFilename + "\"");
			final Path path = Paths.get(tmpDirectory).resolve(tmpFilename);

Dieser Pfad wird dann später mit der Blockung.txt aufgelöst und wirft den Fehler.

@ws46
Copy link
Author

ws46 commented Jan 14, 2025

wurde der Pfad in der svwsconfig.json festgelegt? Mit TempPath kann man einen eigenen Pfad bestimmen.

Ja, aber das hilft auch nicht. Ich habe den Pfad jetzt mal so festgelegt:
c:\\Users\\Walter\\AppData\\Local\\Temp\\SVWSTest\\

Die Debug-Schnittstelle macht daraus
"Erstelle eine temporäres Verzechnis mit dem Inhalt der Zip-Datei unter dem Namen "c:\Users\Walter\AppData\Local\Temp\SVWSTest/svwsdb_T...u.zip""
Beim Aufruf aus Kurs42 wird daraus
"Erstelle eine temporäres Verzechnis mit dem Inhalt der Zip-Datei unter dem Namen "c:\Users\Walter\AppData\Local\Temp\SVWSTest\/svwsdb_q...Y.zip""

Im ersten Fall werden die zwei Backslashes am Ende von TempPath (korrekt) durch einen Slash ersetzt, im zweiten Fall durch Backslash plus Slash. Übrigens wird, wenn bereits in TempPath, wie im Opriginal (C:\\ProgramData\\SVWS-Server/temp), ein Slash vorkommt, dieser ebenfalls durch Backslash plus Slash ersetzt.

Ich könnte mir vorstellen, dass die fehlerhafte Behandlung der Separatoren hier
final Path path = Paths.get(tmpDirectory).resolve(tmpFilename);
passiert, aber das können Sie besser beurteilen.

@hmt
Copy link
Collaborator

hmt commented Jan 14, 2025

lassen Sie mal die abschließenden Slashes weg am Ende von tempPath. Das sollte das Problem beheben.
Also: c:\\Users\\Walter\\AppData\\Local\\Temp\\SVWSTest (wieso eigentlich immer zwei? Ist das etwas, was man unter Windows so macht?)

@kroerig
Copy link
Contributor

kroerig commented Jan 14, 2025

Nein, normalerweise nicht. Ich kenne das aber auch nur so, dass Java-Anwendungen Windows-Pfade immer mit Doppel-Backslash brauchen, weil ein Backslash als Escape-Zeichen interpretiert wird.

@ws46
Copy link
Author

ws46 commented Jan 14, 2025

lassen Sie mal die abschließenden Slashes weg am Ende von tempPath. Das sollte das Problem beheben.

Habe ich gemacht, ändert aber nichts.
Ich habe mal hier nachgesehen. Offenbar bauen get und resolve in Abhängigkeit vom Filesystem den Pfad zusammen. Wie das geschieht, weiß ich nicht, dafür verstehe ich zu wenig von Java.

@ws46
Copy link
Author

ws46 commented Jan 15, 2025

Kann man den Code nicht dahingehend ändern, dass die zwei letzten Zeilen vertauscht werden? Dann wüsste man, wie der ezeugte Pfad genau aussieht.

final Path path = Paths.get(tmpDirectory).resolve(tmpFilename);
logger.logLn("Erstelle ein temporäres Verzeichnis mit dem Inhalt der Zip-Datei unter dem Namen \"" + path.toString() + "\"");

@FPfotenhauer
Copy link
Contributor

Image

Bei mir klappt der Import mit diesen Einstellungen im Body einwandfrei.

@ws46
Copy link
Author

ws46 commented Jan 26, 2025

Bei mir klappt der Import mit diesen Einstellungen im Body einwandfrei.

Das habe ich auch nie bezweifelt. Dennoch ist es so, dass der Import aus Kurs 42 mit identischen Einstellungen, offenbar wegen des nicht korrekt gebildeten tempörären Pfades, scheitert. Ich kann auch die gleiche Datei über das Debug-Inteface importieren, obwohl dabei andere Fehler auftreten. Aber das ist eine andere Sache.

@ThomasBachran
Copy link
Collaborator

ThomasBachran commented Jan 26, 2025

Kann man den Code nicht dahingehend ändern, dass die zwei letzten Zeilen vertauscht werden? Dann wüsste man, wie der ezeugte Pfad genau aussieht.

final Path path = Paths.get(tmpDirectory).resolve(tmpFilename);
logger.logLn("Erstelle ein temporäres Verzeichnis mit dem Inhalt der Zip-Datei unter dem Namen \"" + path.toString() + "\"");

Das Vertauschen ist hier nicht möglich, da die untere Zeile von der oberen abhängt. Insgesamt ist es interessant, dass sich das Verhalten zwischen Delphi und anderen Schnittstellen unterscheidet.

Interessant ist auch, dass bei dem Log zu dem Aufruf aus Delphi heraus. die forward-slashes escaped sind. Das ist laut RFC 8259 in Punkt 7 für JSON optional. Unsere Java-Implementierung macht dies z.B. per Default nicht. In der svwsconfig.json habe ich das auch nicht gesehen, so dass dieses Verhalten erstmal irritierend ist. Wenn ich das korrekt im Kopf habe, dann fügt Delphi bei forward slashes ein back-slash als escape character hinzu. Könnte das etwas damit zu tun haben?

Ansonsten können wir das Verhalten bei uns leider in mehreren Konstellationen nicht nachstellen. Allerdings wird in unserem Projekt auch kein Delphi verwendet...

@ws46
Copy link
Author

ws46 commented Jan 26, 2025

Interessant ist auch, dass bei dem Log zu dem Aufruf aus Delphi heraus. die forward-slashes escaped sind. Das ist laut RFC 8259 in Punkt 7 für JSON optional. Unsere Java-Implementierung macht dies z.B. per Default nicht.

Delphi macht das auch nicht und hat mit der Sache, wenn ich das richtig sehe, auch nichts zu tun, weil der temporäre Pfad vom Server und nicht von Kurs 42 angelegt wird.

@FPfotenhauer
Copy link
Contributor

Kannst du bitte mal probieren den TempPath in der svwsconfig.json zu verändern.
Default ist "C:\ProgramData\SVWS-Server/temp". Danach den ServerDienst einmal neu starten.
Das wird unter Windows von Inno-Setup so gemacht.
Das ist der einzige Unterschied, den ich hier noch erkennen kann.

@FPfotenhauer
Copy link
Contributor

Letzte Überlegung für heute:
Wie lautet der Dateipfad zur Originaldatei, den Kurs42 an den REST-Aufruf übergibt?

@FPfotenhauer FPfotenhauer self-assigned this Jan 26, 2025
@FPfotenhauer
Copy link
Contributor

FPfotenhauer commented Jan 26, 2025

{
  "id": null,
  "success": false,
  "log": [
    "Erstelle eine temporäres Verzechnis mit dem Inhalt der Zip-Datei unter dem Namen \"./Temp/svwsdb_lIwXeoD8uO23APFwmxREKbbAUyeVX8LO8BOdWKXe.zip\"",
    "Importiere die Blockung mithilfe der extrahierten Daten:",
    "-> Lese Informationen zu der Schule ein...",
    "  [OK]",
    "-> Bestimme die Schüler der Schule aus der Datenbank...",
    "  [OK]",
    "-> Bestimme die Lehrkräfte der Schule aus der Datenbank...",
    "  [OK]",
    "-> Bestimme die Fächer der Schule aus der Datenbank...",
    "  [OK]",
    "-> Lese die Kurs 42 - Export - Textdateien ein...",
    "  [Fehler] - Fehler beim Einlesen des Kurs42-Text-Exports: ",
    "  java.nio.file.NoSuchFileException: ./Temp/svwsdb_lIwXeoD8uO23APFwmxREKbbAUyeVX8LO8BOdWKXe.zip/Blockung.txt\n\tat java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92)\n
....

Diesen Fehler bekomme ich, wenn ich in dem ZIP einen Unterordner anlege und die txts darin sind und nicht auf der obersten Ebene im ZIP.

Kann es sein, dass Kurs42 diesen Unterordner im Zip anlegt? Und in der Datei die manuell genutzt wird, kein Unterordner existiert?

@ws46
Copy link
Author

ws46 commented Jan 26, 2025

Wie lautet der Dateipfad zur Originaldatei,

c:\Users\Walter\AppData\Local\Temp\Kurs42.zip

Die Zip-Datei enthält keine Unterordner. Bei Bedarf kann ich die gerne mal mischicken.

@ws46
Copy link
Author

ws46 commented Jan 27, 2025

Kannst du bitte mal probieren den TempPath in der svwsconfig.json zu verändern.

Habe ich alles schon gemacht. Keine Änderung.

@ws46
Copy link
Author

ws46 commented Jan 29, 2025

Das Vertauschen ist hier nicht möglich, da die untere Zeile von der oberen abhängt. Insgesamt ist es interessant, dass sich das Verhalten zwischen Delphi und anderen Schnittstellen unterscheidet.

Das verstehe ich nicht. Wieso beeinflusst die Bildung des Strings für die Logausgabe die Berechnung des Pfades?

logger.logLn("Erstelle eine temporäres Verzechnis mit dem Inhalt der Zip-Datei unter dem Namen "" + tmpDirectory + "/" + tmpFilename + """);
final Path path = Paths.get(tmpDirectory).resolve(tmpFilename);

Mein Vorschlag bedeutet nur, die Logausgabe nach der endgültigen Berechnung des Pfades zu erzeugen.

@FPfotenhauer
Copy link
Contributor

Es liegt nicht an den Pfadangaben.
Die ZIP-Datei wird im temp-Verzeichnis des SVWS-Servers gefunden.
Aber beim Entpacken geht etwas schief und die erste Datei die verarbeitet werden soll "Blockung.txt" in dieser ZIP wird nicht gefunden.
Deshalb hatte ich das mit dem Unterordner probiert. Es kann ja auch eine andere Ursache haben.

@kroerig
Copy link
Contributor

kroerig commented Feb 1, 2025

Mal ne blöde Frage: Wie lautet der volle Pfad zur Blockung.txt?
Und: Könnte Groß-/ Kleinschreibung in den Dateinamen eine Rolle spielen?

@ws46
Copy link
Author

ws46 commented Feb 1, 2025

Wie lautet der volle Pfad zur Blockung.txt?

Es gibt keine Pfade in der Zip-Datei, wie man dem Directory entnehmen kann:
28.01.2025 17:19 162 Blockgruppen.txt
28.01.2025 17:19 919 Blockplan.txt
28.01.2025 17:19 1.166 Blockung.txt
28.01.2025 17:19 119.681 Fachwahlen.txt
28.01.2025 17:19 1.220 Faecher.txt
28.01.2025 17:19 593 Jahrgaenge.txt
28.01.2025 17:19 3.345 Klassen.txt
28.01.2025 17:19 2.364 Klausuren.xml
28.01.2025 17:19 71.481 Kursbelegung.txt
28.01.2025 17:19 3.982 Kurse.txt
28.01.2025 17:19 47 Kursplaene.txt
28.01.2025 17:19 20.339 Lehrer.txt
28.01.2025 17:19 241 Raeume.txt
28.01.2025 17:19 2.061 Schienen.txt
28.01.2025 17:19 15.282 Schueler.txt
28.01.2025 17:19 4.824 SchulLogo.jpg
28.01.2025 17:19 490 ZulKurse.txt

Und: Könnte Groß-/ Kleinschreibung in den Dateinamen eine Rolle spielen

Das muss die Server-Seite beantworten.
Ich glaube aber nicht, weil die als fehlend bemängelte Datei (Blockung.txt) in der Fehlermeldung genau so geschrieben ist wie im Verzeichnis.

Ich habe die anonymisierte (ansonsten echte) Blockungsdatei mal angehängt:
Kurs42.zip

@kroerig
Copy link
Contributor

kroerig commented Feb 1, 2025

Ich meinte den Pfad, wo der SVWS die Datei sucht. Und zwar vom C: an.

Welche Datenbank brauche ich um die Datei einlesen zu können? Und ohne die Blockunsgdatei geht es ja auch nicht.

@ws46
Copy link
Author

ws46 commented Feb 6, 2025

Ich meinte den Pfad, wo der SVWS die Datei sucht. Und zwar vom C: an.

hier: c:\Users\Walter\AppData\Local\Temp\Kurs42.zip. Das scheint ja auch kein Problem zu sein, weil der Server ja die Datei, wie FrankPfotenhauer schrieb, offenbar findet.

Welche Datenbank brauche ich um die Datei einlesen zu können? Und ohne die Blockunsgdatei geht es ja auch nicht.

Ich kann gerne eine anonymisierte Access-DB mit zugehöriger Blockung und Programm auf meiner Homepage ablegen, wenn das weiterhilft.

@kroerig
Copy link
Contributor

kroerig commented Feb 6, 2025

Meine Idee war, dass mit dem doch recht langem temporärem Verzeichnisnamen nach dem Entpacken der Zip-Datei möglicherweise die max. Pfadlänge von 255 Zeichen unter Windows überschritten wird.

Aber das erklärt nicht, warum es über die SwaggerUI und mit Bruno funktioniert. Dürfte es dann nämlich auch nicht.

@ws46
Copy link
Author

ws46 commented Feb 6, 2025

warum es über die SwaggerUI und mit Bruno funktioniert.

Wer oder was ist Bruno?

Dürfte es dann nämlich auch nicht.

Sehe ich auch so. Deshalb mein Angebot. Möglicherweise kann man das dann mal im Debugger laufen lassen.

@hmt
Copy link
Collaborator

hmt commented Feb 6, 2025

Wer oder was ist Bruno?

https://www.usebruno.com/ -> Ein Api-Client

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants