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

[IsInsideExternalDataset] classpath not sufficient #30

Open
edigonzales opened this issue Oct 5, 2023 · 3 comments
Open

[IsInsideExternalDataset] classpath not sufficient #30

edigonzales opened this issue Oct 5, 2023 · 3 comments
Labels
NGK Solothurn wird benötigt für NGK Solothurn

Comments

@edigonzales
Copy link

System.getProperty("java.class.path") wird verwendet um eine Liste sämtlicher Jar-Dateien im Classpath zu erhalten. Das funktioniert in paar Fällen nicht wie gewünscht:

  • (Spring Boot) Fatjars: Da sieht man nur die Fatjar resp. es werden die Jar im Fatjar gemeldet aber so, dass man sie nicht weiterverwenden kann.
  • Spring Boot layered: Man kann die Fatjar wieder auseinandernehmen (insb. für schneller Docker builds). Da ist aber der gemeldete Classpath nur ".". Die Main-Klasse ist dann ein "JarLauncher".

Bei Spring Boot konnte ich es lösen, indem ich gar keine Fatjar herstelle, sondern direkt einfach meinen Code build und noch die Dependencies in ein Verzeichnis kopiere. Dann wird zwar der Aufruf bissle komplizierter aber es funktioniert.

Mit Gradle sehe ich momentan keine Lösung. Da meldet es mir den Classpath /Users/stefan/.sdkman/candidates/gradle/5.1.1/lib/gradle-launcher-5.1.1.jar. Also auch wieder so ein Launcher-Teil, das sich wohl um den "richtigen" Classpath kümmert. Das Arbeiten mit dem normalen Plugins-Ordner führt aus gleichem Grund zu ähnlichen Problemen. Da findet es die Custom Functions schon gar nicht. Das war schon früher das Problem. Kann man umgehen, wenn man die Functions "registriert".

Weil es (?) keine einfache Lösung gibt, um den Klassenpfad nach Resourcen zu durchsuchen, war meine Idee, eine weitere Variante der Funktion zu definieren. Man muss zusätzlich den Namen der Datei angeben, die gefunden werden soll:

IsInsideExternalDataset2("ch.so.agi.hoheitsgrenzen.xtf", "SO_Hoheitsgrenzen_Publikation_20170626.Hoheitsgrenzen.Gemeindegrenze.Geometrie", "39969c9c-ca50-40af-ab67-f7f018182a66", THIS, "Pos");
Classloader loader = getClass().getClassloader();
try (InputStream in = loader.getResourceAsStream(datasetFileName)) {
   doStuff(in);
}

@Philippluca @patrickackermann Was meint ihr? Man kann sichs auch ein wenig schön reden: Immerhin wäre es jetzt qualifizierter. Wenn man nur den qualifizierten Attributnamen angibt und es mehrere XTF mit diesem gibt, passiert vielleicht was, was man nicht will. Mit dem zusätzlichen "Identifikator" (dem Dateinamen) gibt es bereits weniger Kollisionen.

Oder gar komplett auf diesen Zug aufspringen? Auch mit meinem Vorschlag könnte man zuerst im Classpath suchen und dann im lokalen Filesystem.

@patrickackermann
Copy link
Collaborator

Ich verstehe nicht, wo dann der angegebene Filename gesucht würde?

Ich finde, ein Interlis Model sollte nur wirklich notwendige dependencies auf files ausserhalb haben. Der Filename des XTF ist eigentlich irrelevant um die Geometrie eindeutig zu identifizieren daher möchte ich den Filenamen des XTF nicht als Parameter in der IsInsideExternalDataset Funktion.

IsInsideExternalDataset durchsucht alle XTF, die es finden kann nach dem gesuchten Dataset. Zuerst Im classpath und wenn dort nichts gefunden wird im Ordner, in dem sich das geow-interlis-functions jar befindet.

@edigonzales
Copy link
Author

Ich verstehe nicht, wo dann der angegebene Filename gesucht würde?

In den Ressourcen loader.getResourceAsStream(datasetFileName).

Ich finde, ein Interlis Model sollte nur wirklich notwendige dependencies auf files ausserhalb haben. Der Filename des XTF ist eigentlich irrelevant um die Geometrie eindeutig zu identifizieren daher möchte ich den Filenamen des XTF nicht als Parameter in der IsInsideExternalDataset Funktion.

Den ersten Satz verstehe ich nicht ganz. Den zweiten Satz würde ich negieren. Meines Erachtens ist es Definitionssache, was genau benötigt wird, um die Geometrie zu identifizieren. Da kann man schon auf die Idee kommen, dass das mit dem Filenamen anfängt. Man muss ja auch regeln, was passiert, wenn es mehrere Objekte mit der TID gibt, die gefunden werden.

IsInsideExternalDataset durchsucht alle XTF, die es finden kann nach dem gesuchten Dataset. Zuerst Im classpath und wenn dort nichts gefunden wird im Ordner, in dem sich das geow-interlis-functions jar befindet.

Das ist eben das Problem: System.getProperty("java.class.path") kann dir einen Classpath liefern, der - sehr plakativ formuliert - nichtssagend ist. So liefert er dir unter Umständen nur ein einziges Jar (nämlich so ein Launcher-Jar und da drin steckt logischerweise kein XTF). Oder im Falle eines Fatjars liefert es dir die Informationen in einer Form, mit der der Code in der Funktion nicht umgehen kann.

Man könnte ja auch auf die Idee kommen, das XTF aus einem ilidata-Repo zu laden. Dann braucht es m.E. erst recht eine Identifikation der Datei. Sonst musst man immer alle ilidata-Repos durchsuchen nach Dateien, die das Modell implementieren und jede Datei nach der TID durchsuchen.

@patrickackermann
Copy link
Collaborator

Meines Erachtens ist es Definitionssache, was genau benötigt wird, um die Geometrie zu identifizieren

Ja, es ist definitionssache und wir haben definiert, das es über Modell.Topic.Class und TID identifiziert wird.
Übrigens bei mehreren identischen TIDs wird das erste gefundene objekt verwendet.

Ich kenne mich mit Spring Boot nicht aus und weiss daher auch nicht, wie man dort am besten alle XTF aus den resourcen holt. Gibt loader.getResources("") in der Spring Boot umgebung nützliche URLs zurück, die man durchsuchen könnte?

Man könnte ja auch auf die Idee kommen, das XTF aus einem ilidata-Repo zu laden. Dann braucht es m.E. erst recht eine Identifikation der Datei. Sonst musst man immer alle ilidata-Repos durchsuchen nach Dateien, die das Modell implementieren und jede Datei nach der TID durchsuchen.

Bei ilidata-Repo würde es je nach dem noch weitere information für die identifikation benötigen. z.B. die DatasetId aber nicht der Filenamen der XML datei, da dieser im ilidata unter der DatasetID hinterlegt ist.
Eine allfällige ilidata-Repo unterstützung wäre aber eine grössere Erweiterung.

@olivergrimm olivergrimm added the NGK Solothurn wird benötigt für NGK Solothurn label Dec 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NGK Solothurn wird benötigt für NGK Solothurn
Projects
None yet
Development

No branches or pull requests

3 participants