Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
derzeit haben wir es so gelöst, dass wir eine große "Services" Klasse haben, in welcher alle Services per Setter und Getter gesetzt bzw. geholt werden.
Anschließend wird zwischen verschiedenen GUI Fenstern immer im Konstruktor das services-Object übergeben, wodurch am Ende alle GUI Elemente immer zugriff auf ihre benötigten Services haben.
Wir haben jetzt aber von unseren Professoren erfahren, dass wir es so nicht lösen dürfen, sondern es über Spring lösen sollen. Allerdings ist uns nicht wirklich klar, wie das funktionieren soll.
1) Wenn wir die benötigten Services in den einzelnen GUI Fenstern jeweils mit @autowired annotieren, dann werden die Services aber erst bei den Settern gesetzt, unsere Konstruktoren brauchen aber schon die ganzen Services. Die "beste Idee" die wir derzeit haben ist, das wir den gesamten Konstruktor immer in eine "init()" Methode rauskopieren und dann bei den Setter aufrufen, was aber richtig schlecht ist... (dann wird ja auch bei mehreren Settern es öfters aufgerufen bzw. das Fenster öfters initialisiert).
2) Wenn wir alle Fenster im Beans-File definieren, dann wird ja beim Start alles aufeinmal gezeichnet, was zu einer enormen Verzögerung beim Starten der App führen würde. Außerdem müsste man ja irgendwie dann auf den Application Context in den GUI Fenstern zugreifen können, d.h. man bräuchte den Application Context in allen Konstruktoren (was insgesamt ja wieder die gleiche Lösung wie mit der Services Klasse wäre) und das wäre ja auch eine zyklische Abhängigkeit, weil wir im Beans File vom Application Context den Application Context selbst definieren müssten.....?
Also meine Frage insgesamt wäre: Wie macht man das normalerweise, dass man innerhalb der GUI auf die Services zugreifen kann über Spring?
derzeit haben wir es so gelöst, dass wir eine große "Services" Klasse haben, in welcher alle Services per Setter und Getter gesetzt bzw. geholt werden.
Du fängst ja an zu erzählen, wie ihr es macht, bevor du sagst, was es werden soll.
Grundsätzlich arbeitet man natürlich über eine Init-Methode die mit [c]@PostConstruct[/c] annotiert ist und der Konstruktor bleibt normalerweise leer. Setzt natürlich voraus, dass ihr auf einem Application Server oder Servlet Container arbeitet, der eure Beans verwaltet ... dann wird die Methode nämlich automatisch aufgerufen. Ist es eine Standalone Anwendung, weiß ich grad nicht, ob es in Spring sowas wie [c]@PostConstruct[/c] gibt.
Also, konkret noch mal gefragt: Mit was arbeitet ihr da genau? Server, Frameworks?
ja ich fand das ist die einfachste Erklärung, wenn ich mal erklär, wie wir es gemacht haben (Dann versteht mans auch).
Ja es ist stand alone, wir machens über XML und nicht Annotations, aber dort gibts auch eine init-Methode zum angeben. Das geht eh schon.
Unser Problem derzeit ist aber: Bei uns können sich user einloggen. Das initialisieren der Fenster funktioniert aber erst, sobald der User sich eingeloggt hat. (z.b. weil er Permissions benötigt oder weil bestimmte User nicht alles in der GUI sehen). D.h. eine Init Methode geht meistens nicht, weil sich da noch kein User eingeloggt hat.
Lösung derzeit.... alle Fenster in der Main GUI Injecten und dort wird dann überall händisch fenster.init(); aufgerufen, nachdem er sich eingeloggt hat. Das Resultiert aber darin, dass wir sehr viele Fenster in MainGUI injecten.....
Andere Frage: Wenn wir alle Fenster dann beim Starten über Beans erzeugen, führt das nicht zu einer enormen Verzögerung? Bei uns wurden vorher alle Fenster zu runtime erzeugt, wenn der user z.b. auf einen Button klickt, jetzt wird ja alles auf einmal erzeugt...
die Idee vom Injecten is, dass du die Abhängigkeit nicht explizit auflösen musst, also keinen Constructor brauchst, sondern dass die Instanz halt da is, wenn man sie braucht
das ist mir natürlich auch alles klar und genau so (mit ApplicationContext) mache ich es auch schon die ganze Zeit. Ich hab auch "Spring im Einsatz" gelesen, also soweit kenne ich mich schon aus.
Unsere Application ist aber derzeit so, das man sich am Anfang einloggen muss. Es gibt verschiedene User, also normale User, Moderaten und Administratoren. Ein Admin darf mehr als ein User (z.b. User Daten editieren kann nur der admin). D.h. du Berechtigungsüberprüft wird natürlich nicht nur in der GUI sondern auch im Service gemacht.
Jetzt benötigen manche GUI Fenster die Services, z.b. das Fenster zum Ändern von User Informationen benötigt den User Service. In diesem Fenster werden unter anderem auch alle User angezeigt, eine Funktion, die nur der Admin machen darf, weshalb im Service das auch überprüft wird und falls es normaler User sie aufruft (oder kein User eingeloggt ist), eine Exception geworfen wird.
Wenn ich jetzt dieses Fenster im Beans file definiere, dann kann ich dort auch eine Init Methode angeben. Die brauche ich, weil ich das Fenster nicht innerhalb des Konstruktors initialisieren kann, da ich fürs initialisieren den userService brauche, welchen ich aber erst per Setter setze. Deshalb benutze ich derzeit eine eigene Init() Methode.
Das Problem ist jetzt, das wenn ich die init Methode im Beans file definiere (oder es per Annotation mache, das ist ja egal), dann wird das Bean initialisiert BEVOR sich jemand einloggt. Folglich wird eine Exception geworfen.
Mein derzeitiger Workaround ist, das ich _nicht_ im Beans file die Init Methode angebe, sondern im MainWindow direkt nach dem Login aufruf die Init() Funktion dieses Fensters aufrufe. Deshalb braucht natürlich das MainWindow auch einen Verweis auf dieses Fenster, weshalb ich das Fenster per Setter injecte.
Jetzt gibt es aber nicht nur 1 so ein Fenster das vom aktuellen User abhängt, sondern ca. 40-50. D.h. ich muss 40-50 Instanzvariablen im MainWindow machen, dafür die Setter und dann für alle danach init() Aurufen.
Meine Frage: Gibts dazu eine bessere/elegantere Lösung?
im Tomcat ist es so, dass quasi alles immer initialisiert ist.
Das heisst, beim Start wird alles injected was gebraucht wird.
Du prüfst beim Zugriff, ob es legal ist, mit deinen aktuellen Rechten die Aktion durchzuführen.
Auf dich umgesetzt:
du brauchst ein Prüflayer (evtl ein Sicherheitsaspekt), welches vor einer Aktion prüft, ob das legal ist.
Wenn du erst der Reihe nach injecten willst... keine Ahnung... das musst du wohl per Hand machen... (also so, wie du es machst)
Die 'richtige' Methode ist einfach die Prüfung zur Laufzeit... zumindest soweit ich weiss
du kannst ja dem User nur das anzeigen, was er darf, und dann ist es egal ob der Rest schon initialisiert wurde