Java JDBC Observer auf Db Änderungen



  • Hallo,

    ich habe ein Applet, welches mit einer MySQL 5 Datenbank arbeitet. Falls in einer Tabelle ein Datensatz hinzugefügt wurde, soll das Applet davon benachrichtigt werden.

    Wie kann ich das am besten umsetzen? Polling sollte es möglichst nicht sein.



  • Wie schreibst du denn die Daten in die DB?

    Gibt es dafür z.B. eine Klasse dann könntest du z.B. das Observer Pattern einbinden um das Applet zu benachrichtigen.



  • Da davon auszugehen ist, dass mehr als ein Client gleichzeitig auf die Datenbank zugreift, ist das Observer Pattern keine Lösung.

    Es müsste geprüft werden, ob MySQL ein solches Feature anbietet. Falls nein, dann gehts wohl nur mit Polling.



  • Ich denke auch, dass das wohl nur über Polling geht. Wüsste nicht dass es da so ein Feature gibt (bin aber auch noch bei MySQL 4.x ;).
    Wobei das natürlich nicht automatisch heißt, dass du das Polling in jedem Client durchführen musst. Da gäbe es schon auch Wege das relativ elegant zu lösen.

    Btw: Bist du dir sicher, dass du das ganze wirklich in nem Applet laufen lassen willst? Um das zu realisieren müsstest du dein Applet nämlich auch noch mit einem Zertifikat ausstatten, weil du ansonsten an den Sicherheitsberechtigungen scheiterst. Und wenn du dein Zertifiakt nicht gerade von einer CA signieren lässt (kostet), dann wird es evtl. User geben die deinem signierten Applet trotzdem nicht vertrauen.



  • Hallo,

    vielen Dank für die Antworten.

    Mittlerweile sehe ich es auch so, dass Polling wohl das einzig sichere Mittel dafür ist.

    @nep
    Welche eleganten Wege gibts denn da so? Bin immer an Ideen interessiert.

    Was das Zertifikat angeht, das Applet darf doch auch ohne Zertifikat auf den Server per JDBC zugreifen, oder sehe ich das falsch?



  • Und es ist das einzige Mittel dem man wirklich zustimmen könnte. Keine GUI muss sofort über Änderungen an Daten in einer Datenbank informiert werden. Ich sehe da ehrlich gesagt keinen echten Anwendungsfall dafür.

    Ansonsten, wenns auch DB-intern genügt: Datenbanktrigger



  • Das Applet ist dafür da um dem Benutzer anzuzeigen, wenn er eine neue PN bekommen hat. Nun kann das relativ häufig sein oder auch nicht, je nachdem wie exzessiv der User seine Mail Kontakte pflegt.
    Jedenfalls ist Polling dafür eigentlich eher ungeeignet, da wohl die meisten Anfragen nicht nötig wären.

    Das ist wie bei einem Email Client. Die meisten pollen beim Server alle x Minuten nach neuen Emails. Die meisten Polling Anfragen sind unnötig.



  • deetee schrieb:

    Das ist wie bei einem Email Client. Die meisten pollen beim Server alle x Minuten nach neuen Emails. Die meisten Polling Anfragen sind unnötig.

    Warum unnötig? "Keine neuen Nachrichten" ist genauso eine sinnvolle Information wie "drei neue Nachrichten". Es ist nun mal technisch nicht machbar. Einzig die Datenbank kann wissen, wann neue Datensätze geschrieben werden. Ich kenne aber keine Datenbank, die solch ein Observer Feature anbietet. So ein "Server-Push" ist auch nicht trivial zu realisieren.



  • deetee schrieb:

    Hallo,

    vielen Dank für die Antworten.

    Mittlerweile sehe ich es auch so, dass Polling wohl das einzig sichere Mittel dafür ist.

    @nep
    Welche eleganten Wege gibts denn da so? Bin immer an Ideen interessiert.

    Was das Zertifikat angeht, das Applet darf doch auch ohne Zertifikat auf den Server per JDBC zugreifen, oder sehe ich das falsch?

    Nein, ein Applet läuft ja immer in einem Browser, und für Applets wird da automatisch immer ein sog. Security Manager mitgeführt, der im Prinzip alle "heiklen" Operationen die ein Applet so machen kann unterbindet (Google mal danach). Du kannst im Applet z.B. nicht auf das Dateisystem des Users zugreifen, du kannst aber z.B. auch nicht irgendwelche Socket-Verbindungen öffnen, d.h. eine Kommunikation mit einer Datenbank wird so im Applet erst mal nicht funktionieren. Ein Applet läuft eben sozusagen immer in einer Sandbox.
    Um obiges aber trotzdem zu erreichen müsstest du dein Applet signieren, und die User müssten dann quasi immer explizit zustimmen, dass sie deinem signierten Applet vertrauen. Dann kann es solche Operationen durchführen.

    So jetzt zum Thema wie man das mit dem Polling einigermaßen elegant lösen könnte: Es wäre meiner Meinung nach blöd wenn du quasi in jedem Applet die Datenbank pollst, das macht architektonisch keinen Sinn und ist auch nicht wirklich praktikabel. Ich würde vielmehr eine kleine Server-Anwendung schreiben, die du dann z.b. auf dem selben Server wie dem deiner Datenbank laufen lässt, und diese Anwendung führt dann in einem fest definierten Zeitintervall das Polling durch. Diese Server-Anwendung implementierst du mittels RMI. Deine Applets fungieren dann als RMI-Clients. Warum RMI? RMI bietet dir die nette Möglichkeit sog. Callbacks zu realisieren, d.h. jeder Client kann sich bei einer RMI-Server-Anwendung registrieren (in dem Fall dein Polling-Programm). Sobald dein Server-Poll-Programm eine Änderung in der Datenbank feststellt, kann es die registrierten Clients benachrichtigen mithilfe von Callback-Funktionen. Damit reduzierst du den Netzwerkverkehr deiner Applets drastisch, da diese quasi nur dann vom Server benachrichtigt werden, wenn quasi tatsächlich was passiert. Zu dem Thema kannst du auch einfach mal nach RMI Callbacks googeln.
    Das ist einfach mal so eine Idee von mir ins Blaue, aber ich denke das wäre hier ganz gut für dein Szenario. Aber um das mit Applets zu realisieren, müsstest du natürlich auch wieder den Security Manager berücksichtigen (d.h. Applet signieren... ohne das geht nun mal gar nichts).



  • Also ich habe es aber mittlerweile laufen und zwar ohne Signierung. Die JDBC Verbindung mit der MySQL Datenbank funktioniert, ich muss eben nur die Treiber .jar dem Applet mitgeben, was satte 700kB sind für MySql.

    Die Datenbank ist ja auf dem Host von dem das Applet geladen wurde, demnach muss das Applet nicht signiert sein.
    Allerdings kann ich auch auf die Db zugreifen, wenn ich das Applet per Appletviewer auf meinem lokalen Rechner ausführe. Das widerum kann ich mir grad nciht so schnell erklären...evtl. weil beim Appletviewer die Sicherheitsbeschränkungen nicht gelten?



  • Lokale Netzwerkverbindungen klappen normal auch. Und normal ist es meines Wissens nach auch möglich, eine Verbindung zu dem Rechner aufzubauen von welchem das Applet geladen wurde. D.h. ok, falls es so sein sollte, dass Applet vom selben Host kommt wie der auf dem die DB läuft, könnte es auch so klappen. Solltest du aber vorher tatsächlich mal so testen. Alles andere würde ansonsten aber definitiv nicht klappen, da bin ich mir ziemlich sicher.



  • Ok, jetzt hab ich noch ein andere Problem, welches mir jetzt erst klar geworden ist.

    Und zwar wird das Applet so eingebunden:

    <applet codebase="http://domain.de/" code="applet/Beeper.class" archive="mysql-connector-java-5.1.7-bin.jar,Beeper.jar" width="300" height="120">
    	<param name="userid" value="1">
    </applet>
    

    Das Problem ist nun, jeder kann den Code kopieren, lokal speichern, die userid ändern und hat dann quasi die Informationen für diesen User.

    Das ist ziemlich scheiße. Aber sicher bin ich nicht der erste mit dem Problem. Gibts da gängige Sicherheitsabfragen? Spontan fällt mir ein, eine Session ID und die Userid miteinander zu verknüpfen und wenn die nicht zusammen passen, dann ist es ncht der Nutzer hinter der Id. Also sowas dann:

    <applet codebase="http://domain.de/" code="applet/Beeper.class" archive="mysql-connector-java-5.1.7-bin.jar,Beeper.jar" width="300" height="120">
    	<param name="userid" value="1">
    	<param name="ticket" value="398df53sf7546">
    </applet>
    

    Jetzt bringt es nichts mehr sich das Applet zu laden und die Userid zu ändern. Hat jemand andere Ideen?

    edit:

    Mir ist noch eine Möglichkeit eingefallen. Ich könnte die userid mit einem Salt Wert verbinden und diesen Wert dann verschlüsseln und als Parameter userid eintragen. Damit spar ich mir das zusätzliche Verwalten von SessionIDs zu jedem Benutzer.
    Ich weiß nur noch nicht mit welcher Verschlüsselung ich das am besten mache. Klar ist jedenfalls, dass ich dafür keine Einwegverschlüsselung brauchen kann, denn aus dem Hashwert muss ich die userid problemlos auslesen können, ohne zusätzliche Vergleichstabelle, sonst bin ich wieder beim selben Prinzip wie mit SessionIDs.


Log in to reply