Java Reflection/Pufferung

Kamikatze

Captain
Registriert
Okt. 2004
Beiträge
3.703
Hey ihr. Echte Spezialisten sind gefragt! ;)

Großes, vllt. auch nur kleines Problem:

Ich programmiere derzeit ja ein zur Laufzeit erweiterbares Web-Projekt.

Wenn ich ein neues Modul hochlade, das ich installieren will, überprüfe ich auch, ob eine bestimmte Klasse in diesem Modul ein bestimmtes Interface implementiert.

Code:
Class initclass = Class.forName("aecp." + m.getName() + ".InitModule");

if (initclass.getInterfaces().length > 0 && initclass.getInterfaces()[0].getName().compareTo("aecp.backbone.module.iModule") == 0)

m ist das gerade zuvor hochgeladene Modul.
Die ganze Klasse lautet dann z.B. "aecp.Testmodul.InitModule".

Das Problem:
Ich hab mir 2 identische Module gebastelt (sprich auch Name und somit Package), nur mit dem Unterschied, dass eine dieses Interface implementiert und die andere nicht.

Die erste Überprüfung funktioniert, will ich dann aber auch die 2. Datei hochladen, bekomm ich das gleiche Ergebnis wie zuvor, obwohl die "InitModule.class" inzwischen ersetzt wurde - also die nicht korrekte Datei wird als korrekt angezeigt und umgekehrt.

Was kann ich dagegen tun?

Danke.
 
Hast du das ganze mal mit zwei Klassen probiert, die nicht identische Namen haben? Wahrscheinlich verursacht die Methode Class.forName() das Problem. Denn eventuell ist es so, dass diese Methode die Klasse nur dann nachlädt, wenn sie noch nicht bekannt ist.
 
Nein hab ich noch nicht, bin mir aber ziemlich sicher, dass es dann funktioniert.

Das heißt also, dass Class.forName(...) das Ergebnis praktisch puffert. Es gibt dann auch wahrscheinlich keine Möglichkeit, diese Puffer zurückzusetzen?

Sonst wüsste ich nur eine Möglichkeit:
Das Package zuerst in einen Temporären Ordner umbenennen ("z.B. tmp_0sa8f9s"), die Überprüfung durchführen und erst dann in den richtigen Namen (z.B. "Testmodul") umbenennen.

Aber eine weitere Frage:
Der Package-Namen, den man in der Java-Datei angibt ist eigentlich egal, oder?

Angenommen ich hab eine Javadatei:
package aecp.ordner1;

Diese befindet sich somit auch im Ordner "order1", der sich wiederum im Ordner "aecp" befindet.

Wenn ich diese class-Datei nun manuell in den "ordner2" verschiebe, kann ich doch trotzdem weiterhin ohne Probleme darauf zugreifen? Oder hat dieser Name noch irgendwelchen Einfluss auf das ganze?

EDIT: OK, ist anscheinend nicht egal...

Aber auch hier tritt leider wieder dasselbe Problem auf:
Wieder 2 Dateien, eine mit der richtigen Modulangabe, das 2. mit einer, die dann geändert wird.

Überprüfe ich zuerst die richtige, funktioniert danach auch die "fehlerhafte" bzw. wird zuerst die "fehlerhafte" überprüft, funktioniert dann auch die, die funktionieren sollte nicht.

Ich hab auch noch extra die zuerst hochgeladenen Dateien gelöscht, damit ich ja sicher gehen kann, dass die Dateien etwa nur nicht überschrieben werden. Und dann auch noch einmal extra nachgesehen - es ist dann die jeweils andere Dateiversion gespeichert:
 

Anhänge

  • 2006-12-26_161158.png
    2006-12-26_161158.png
    9 KB · Aufrufe: 148
Zuletzt bearbeitet:
Schon mal mit getInterfaces() probiert?
 
Ja, verwend ich ja oben im Code! ;)

Das Problem ist ja nur, ganz kurz gesagt, wenn ich Java-Methoden auf eine Klasse anwende und die class-Datei inzwischen austausche, bekomm ich immer noch die Ergebnisse der alten Class-Datei.

Java scheint die Daten zu puffern... :(
 
Aso hab mir den Code net so durchgesehen. ;)

Class.forName(String) sucht und bindet die Klasse nur dann, wenn sie noch nicht geladen wurde. Also funktioniert das so (einfach) nicht. Du musst also die Klasse unloaden bzw. reloaden (google mal danach) - eine kleine Info warum und wieso findest du hier

ABER: du hast 2 idente Klasse ja nur aus Testzwecken. Ich würde mich nicht um ein solches Problem kümmern, da du zur Laufzeit nur ein Klasse mit einem Identifier haben kannst.
 
Zuletzt bearbeitet:
Naja, ist nicht nur aus Testzwecken:

Die Klasse InitModule muss immer vorhanden sein - bei jedem Modul. Sollte ich jetzt nur ein einziges Modul ein zweites Mal hochladen müssen...

Praktisches Beispiel:
Ich hab ein Modul - z.B. Kalender v. 1.0 - installiert. Inzwischen ist Kalender v. 1.1 erschienen und ich will updaten. Die Überprüfung funktioniert dann aber nicht mehr.

Oder wenn ich einmal ein nicht korrektes Modul hochlade, funktioniert eine korrigierte Version davon nicht mehr.

Aber der Link war schon mal sehr gut.
Ich denke ich werde nach der Installation eines Moduls einen Neustart des Tomcat Servers & der JVM empfehlen, sprich ein und dasselbe Modul soll nicht 2 Mal innerhalb einer Sitzung upgedated bzw. zu installieren versucht werden können. (Außerdem würden sonst die neuen Funktionen der neuen class-Dateien ohnehin auch nicht greifen!)

Nur muss ich jetzt noch einen Weg finden, wie ich erkennen kann, dass der Server inzwischen neu gestartet wurde.

Danke, war mir schon mal eine große Hilfe!

PS:
Du wohnst ja gar nicht mal so weit weg von mir! ;)
 
Zuletzt bearbeitet:
Wenn das ganze im Tomcat läuft, sollte es auch reichen, den Web-Context zu reloaden.
 
Kamikatze schrieb:
Die Klasse InitModule muss immer vorhanden sein - bei jedem Modul.
Eben, die Klassen können ruhig mehrmals vorkommen, aber die Module (bzw. Packages) müssen unterschiedlich sein.
 
Cobinja schrieb:
Wenn das ganze im Tomcat läuft, sollte es auch reichen, den Web-Context zu reloaden.

Wie geht das?

Loopo schrieb:
Eben, die Klassen können ruhig mehrmals vorkommen, aber die Module (bzw. Packages) müssen unterschiedlich sein.

Ja schon klar. Aber wenn ich ein Modul irgendwann einmal aktualisieren will...
 
Am einfachsten über das Manager-Web-Interface. Das erreichst du über z.B.: http://localhost:8080/manager/html (8080 ist der Standard-Port, manche Leute instalieren den tomcat lieber auf 8088). Jetzt noch mit dem Benutzer admin einloggen und Du bekommst eine Liste mit den Web-Contexten und kannst sie einzeln abschießen, laden oder neu laden.
 
Zuletzt bearbeitet:
Ja, das Neustarten selbst ist auch kein Problem, nur

1.) wie weiß das Programm nun, dass inzwischen bereits einmal neu gestartet wurde.
2.) könnte das evtl. nicht reichen, falls die JVM noch von einem anderen Programm benötigt wird und nicht beendet wurde, sind die alten Klassen weiterhin geladen. Man wird wahrscheinlich den ganzen Tomcat + JVM neu starten müssen, wenn man auf Nummer Sicher gehen will.
 
Zurück
Oben