Donnerstag, 4. Dezember 2008

entwickler.com Magazine Konferenzen Akademie Entwickler-Forum Jobbörse Bücher
Software & Support Verlag




April 2006
aus Der Entwickler Ausgabe: 1.2003
Schnappschuss
Mit WebSnap lassen sich Daten einfach ins Web bringen
von Bob Swart

WebSnap ist die neue Webserver-Applikationsarchitektur für Delphi, C++Builder und Kylix. Basierend auf WebBroker und den Ideen, die etwas früher in InternetExpress gezeigt wurden, wurde WebSnap zuerst in Delphi 6 eingeführt. WebSnap ist Teil der Enterprise-Editionen.


Zum Erstellen einer WebSnap-Applikation starten Sie Delphi, schließen das Defaultprojekt, klicken auf Datei | Neu - Weitere und gehen zum WebSnap-Register in der Objektgalerie. Beachten Sie hier die Register für die IntraWeb- und ExpressWeb-Frameworks: Diese beinhalten zwei Sätze mit Entwicklungskomponenten und Wizards für Webserver-Applikationen, die das Thema von weiteren Artikeln im Entwickler sein könnten (bleiben Sie also dran).

Es gibt drei Icons in dem WebSnap-Register: Zuerst sehen Sie das WebSnap-Applikationssymbol, das wir gleich brauchen werden, um eine neue WebSnap-Applikation zu erstellen. Die anderen zwei Symbole können verwendet werden, um ein WebSnap-Datenmodul (das DataSets und DataSources enthält) und ein WebSnap-Seitenmodul (das PageProducers enthält) zu erzeugen - wir sehen diese etwas später in diesem Artikel.

Führen Sie einen Doppelklick auf dem WebSnap-Applikationssymbol aus, um den Wizard für die neue WebSnap-Applikation aufzurufen (siehe Abb. 1).


Abb. 1: Neue WebSnap-Applikation erstellen

Selektieren Sie einen Web App Debugger executable-Servertyp (Web-Debugger-Anwendung), der ohne die Notwendigkeit eines Webservers verwendet (und getestet) werden kann. Beachten Sie das CrossPlattform-Kontrollkästchen, welches die Erstellung von solchen WebSnap-Applikationen unterstützt, die mit Delphi unter Windows als auch Kylix 3 unter Linux kompiliert werden können.

Für eine Web Debugger-Anwendung müssen wir einen Klassennamen (wie Entwickler in meinem Beispiel) spezifizieren. Ändern Sie ebenso den Name der Startseite in Startseite und klicken dann auf OK, um eine neue WebSnap-Applikation mit einem Applikationsseitenmodule (die Startseite) sowie einem leeren Web App Debugger Formular zu erstellen. Speichern Sie über Datei | Alles Speichern das Seitenmodul als pmHome.pas, das Formular als WADForm.pas und das Projekt selbst als WAD.dpr.

Das WebSnap-Datenmodul
So weit das WebSnap-Gerüst. Es ist nun Zeit, ein WebSnap-Datenmodul hinzuzufügen, um einige Datensätze, Tabellen und Abfragen zu platzieren. Gehen Sie zu Datei | Neu - Weitere, dort wieder zum WebSnap-Register und führen Sie einen Doppelklick auf das WebSnap-Datenmodulsymbol aus. Dies blendet einen Dialog ein, in dem Sie einfach nur auf OK klicken müssen, um ein neues WebSnap-Datenmodul zu produzieren.

Speichern Sie die erstellte WebSnap-Datenmodul-Unit in der Datei wDataMod.pas. Auf meinen Webseiten habe ich eine Reihe an WebSnap-Sitzungen bereitgestellt, welche die Borland Datenbank Engine (BDE) als Datenzugriffbibliothek verwenden. Und das werden Sie so in den meisten Publikationen über WebSnap finden: Entweder werden die BDE oder Stand-alone-ClientDataSets verwendet. Nichtsdestotrotz werde ich Ihnen dieses Mal zeigen, wie Sie dbExpress verwenden können (der empfohlene Ersatz für SQL-Links und die BDE), was ein bisschen anspruchvoller ist.

Wir werden dbExpress verwenden, um eine Verbindung zu einer InterBase-Datenbank aufzubauen. Also ziehen Sie eine TSQLConnection-Komponente aus dem dbExpress-Register der Komponentenpalette. Öffnen Sie die ConnectionName-Eigenschaft der TSQLConnection-Komponente, welche uns in Delphi 7 Enterprise eine Auswahl für die Verbindung zu DB2, InterBase, Informix, MS SQL Server, MySQL und Oracle anbietet. Da die InterBase-Beispieldatenbank mit Delphi 7 installiert werden kann, verwende ich immer diese (damit jeder mitspielen kann) und wähle den IBLocal-Wert für die ConnectionName-Eigenschaft. Dieses wird automatisch die DriverName-Eigenschaft auf Interbase, GetDriverFunc auf getSQLDriverINTERBASE, LibraryName auf dbexpint.dll und VendorLib auf GDS32.DLL setzen. Wir müssen nun einen Rechtsklick auf die SQLConnection-Komponente ausführen, um die Verbindungseigenschaften zu bearbeiten (siehe Abb. 2).


Abb. 2. Verbindungs-Eigenschaften editieren

Beachten Sie, dass der Ort der Datenbank mit dem Name des Serverrechners vorbelegt ist, der InterBase ausführt (in Abbildung 4 ein Rechner mit Namen voyager, aber wenn es sich um den gleichen Rechner handelt, auf dem Sie auch entwickeln, kann localhost vorkommen, so dass der Vorgabeort der Datenbank irgendetwas wie localhost:c:\program files\common files\borland shared\data\employee.gdb sein kann). Beachten Sie ebenso die User_Name- und Password-Eigenschaften, welche garantieren, dass wir die LoginPrompt-Eigenschaft auf False setzen können, um das Loginprompt vermeiden zu können (dessen Anzeige sich nicht gut in Ihrer WebSnap Webserver-Applikation machen würde).

Nachdem Sie den Verbindungseigenschaften-Dialog geschlossen haben (und die LoginPrompt-Eigenschaft auf False gesetzt haben), können Sie die Verbindung testen, indem Sie die Connected-Eigenschaft auf True setzen. Sobald Sie verifiziert haben, dass die Verbindung aufgebaut werden kann, können Sie eine TSQLTable-Komponente einsetzen, um mit der InterBase employee.gbd-Datenbank zu kommunizieren. Setzen Sie die Name-Eigenschaft auf tblJOB, lassen Sie dessen SQLConnection-Eigenschaft auf die SQLConnection-Komponente zeigen und öffnen Sie die Drop-Down-Liste für die TableName-Eigenschaft, um alle verfügbaren Tabellen der employee.gbd-Datenbank anzuzeigen. Wählen Sie die JOB-Tabelle.

Führen Sie nun im Feldereditor einen Doppelklick auf tblJOB aus. Führen Sie dann einen Rechtsklick im Feldereditor aus und wählen Sie Hinzufügen aller Felder, um alle verfügbaren, persistenten Felder hinzuzufügen. Selektieren Sie das erste Feld mit Namen JOB_CODE, gehen Sie zum Objektinspektor und setzen die pfInKey-Untereigenschaft der ProviderFlags-Eigenschaft auf True. Dies stellt sicher, dass JOB_CODE als eindeutiges Identifikationsschlüsselfeld verwendet wird, wann auch immer wir einen Record aus der JOB-Tabelle brauchen (in einer Such-, Editier- oder Löschoperation zum Beispiel).

Unabhängig von der JOB-Tabelle möchte ich einige weitere Information aus der InterBase-Datenbank zeigen. Ziehen Sie also eine Weitere TSQLTable-Komponente auf das Modul, nenen diese dsEMP, lassen deren SQLConnection-Eigenschaft auf die SQLConnection-Komponente zeigen und wählen die EMPLOYEE-Tabelle als TableName. Führen Sie einen Doppelklick auf dsEMP aus, um den Feldereditor zu starten. Führen Sie dann wieder einen Rechtsklick im Feldereditor aus und wählen Sie Hinzufügen aller Felder, um alle elf persistenten Felder hinzuzufügen. Selektieren Sie das erste Feld mit Namen EMP_NO, gehen Sie zum Objektinspektor und setzen Sie die pfInKey-Untereigenschaft der ProviderFlags-Eigenschaft auf True.

Wir haben nun zwei verbundene dbExpress-Tabellen, welche in der Tat nur zu lesende, unidirektionale Datasets sind (das Hauptcharakteristikum von dbExpress). Also sollten wir zwei TDataSetProvider- und zwei TClientDataSet-Komponenten zusätzlich hinzufügen. Nennen Sie die zwei DataSetProviders dspJOB und dspEMP und verbinden Sie deren DataSet-Eigenschaft mit tblJOB bzw. tblEMP. Nennen Sie die zwei ClientDataSets cdsJOB und cdsEMP und verbinden Sie deren ProviderName-Eigenschaft mit dspJOB bzw. dspEMP.

Abschließend ziehen Sie zwei TDataSetAdapter-Komponenten aus dem WebSnap-Register der Komponentenpalette, nennen sie dsaJOB und dsaEMP und verbinden deren DataSet-Eigenschaft mit cdsJOB bzw. cdsEMP (beachten Sie, dass Sie diese mit den ClientDataSets und nicht den SQLTables verbinden müssen). Siehe auch Abbildung 3 für das WebSnap-Datenmodul bis zu diesem Punkt:


Abb. 3: WebSnap-Datenmodul

Das WebSnap-Seitenmodul
Nun lassen Sie uns zwei WebSnap-Seitenmodule erstellen, um die Daten von diesen Tabellen (oder genauer - von den zwei DataSetAdapter) anzuzeigen. Zu Beginn wählen Sie Datei | Neu - Weitere, gehen zum WebSnap-Register der Objektgalerie und führen einen Doppelklick auf dem WebSnap-Seitenmodulsymbol aus. Dies präsentiert uns den neuen WebSnap-Seitenmoduldialog, in dem wir zuerst angeben müssen, dass wir eine AdapterPageProducer anstatt dem Default-PageProducer verwenden wollen. Setzen Sie den Seitennamen auf Jobs.

Klicken Sie auf OK, um das neue WebSnap-Seitenmodul zu erstellen (siehe Abb. 7) und speichern Sie die neue Unit als pmJobs.pas. Fügen Sie die Unit wDataMod (das WebSnap-Datenmodule) der uses-Klausel von diesem WebSnap-Seitenmodul hinzu, indem Sie zum Beispiel Alt+F11 drücken und wDataMod auswählen.


Abb. 4: Neues WebSnap Seitenmodul

Führen Sie einen Doppelklick auf dem AdapterPageProducer aus, um den Webseiteneditor zu starten (siehe Abb. 5). Dies ist eine spezielle Designzeitumgebung, wo wir WebSnap-Anzeigekomponenten hinzufügen können, die sich mit den WebSnap-Adapterkomponenten unterhalten können. In diesem Fall möchte ich den Inhalt der dsaJOB DataSetAdapter-Komponente anzeigen.

Zuerst führen Sie einen Rechtsklick auf der AdapterPageProducer in dem Webseiteneditor aus und selektieren Neue Komponente zum Anzeigen des Add Web Komponente-Dialogs. Dieser Dialog wird immer nur die Webkomponenten anzeigen, die für den selektierten Knoten in der Baumansicht relevant sind. Im Fall von einem AdapterPageProducer sind die einzig möglichen relevanten Webkomponenten, die wir hinzufügen können, AdapterForm und LayoutGroup (ein Mittel zum Anzeigen von Kindkomponenten in Mehrfachspalten). Selektieren Sie die AdapterForm. Dann führen Sie einen Rechtsklick auf die AdapterForm aus und fügen ein AdapterGrid hinzu. Dies erzeugt eine Designzeit-Warnung (siehe Abb. 5), um anzuzeigen, dass wir die Adapter-Eigenschaft mit der AdapterGrid-Komponente verbinden müssen.


Abb. 5: Der Webseiteneditor

Um diese Designzeitwarnung zu entfernen, müssen Sie das AdapterGrid selektieren, zum Objektinspektor gehen und dessen Adapter-Eigenschaft auf WebDataModule1.dsaJOB (der dsaJOB-DataSetAdapter vom WebSnap-Datenmodul) setzen. Dies mag Ihnen eine Weitere Designzeitwarnung erzeugen, die indiziert, dass der Dataset cdsJOB nicht aktiv ist (das hängt aber von Ihrer Situation ab). Wenn Sie die Warnung erhalten, können Sie diese einfach beseitigen: Im Objektinspektor klicken Sie auf das +-Zeichen vor der Adapter-Eigenschaft, um die verschachtelten Eigenschaften der Adapter-Komponente zu öffnen und die DataSet-Eigenschaft (neben anderen) anzuzeigen. Klicken Sie ebenso auf das + vor der DataSet-Untereigenschaft und setzen Sie dann die Active-Eigenschaft auf True. Dies wird den cdsJOB-Dataset öffnen und die letzte Designzeitwarnung beseitigen.

Das Resultat wird sein, dass wir die Ausgabe der JOB-Tabelle im Webseiteneditor zur Designzeit sehen können. Dennoch - diese Tabelle beinhaltet zu viele Felder, um sie in einem Gitter anzuzeigen. Also möchte ich eine Anzahl an Feldern entfernen. Führen Sie einen Rechtsklick auf der AdapterGrid-Komponente in dem Webseiteneditor aus und wählen Sie Hinzufügen von Spalten aus. Dies wird Ihnen einen Dialog präsentieren, in welchen Sie die Spalten selektieren können, die angezeigt werden sollen: JOB_CODE, JOB_GRADE, JOB_COUNTRY, JOB_TITLE, MIN_SALARY, MAX_SALARY, JOB_REQUIREMENT und LANGUAGE_REQ. Für jetzt will ich nur die ersten vier Felder sehen. Daher selektieren Sie nur diese (siehe Abb. 6).


Abb. 6: Der Webseiteneditor in Aktion

Wenn Sie einen Blick auf das AdapterGrid in Abbildung 6 werfen, werden Sie möglicherweise bemerken, dass es ziemlich lang ist. Es gibt eine ganze Reihe an Records in der Jobs-Tabelle und diese werden alle auf ein Mal angezeigt. Um das Scrollen zu unterbinden, um alle Records zu sehen (und was auch immer nach dem AdapterGrid auf dem Seitenmodul kommt), können wir die Anzahl der Records begrenzen, die zu einem bestimmten Zeitpunkt zu sehen ist - auf einer Seite, sozusagen. Dies wird mit der PageSize-Eigenschaft von dem dsaJOB-DataSetAdapter gemacht. Unter erneuter Verwendung der verschachtelten Eigenschaftadapter im Objektinspektor greifen wir auf PageSize zu und setzen den Wert auf 4 (oder einen anderen Wert, den Sie vorziehen). Dies resultiert in einem AdapterGrid, das nur vier Records gleichzeitig anzeigt. Um nun zur nächsten Seite zu gelangen, brauchen wir einige spezielle Schaltflächen zum Weiterblättern. Um diese hinzuzufügen, führen Sie einen Rechtsklick auf der AdapterForm aus, selektieren Neue Komponente und fügen eine AdapterCommandGroup hinzu. Die Designzeitwarnung, die Sie erhalten, kann beseitigt werden, indem die DisplayComponent-Eigenschaft der AdapterCommandGroup auf das AdapterGrid gesetzt wird. Dies zeigt eine größere Anzahl an Button an. Nicht alle sind für uns zu dieser Zeit relevant. Um sicherzustellen, dass wir nur die Blätterbutton sehen, die in Bezug zu der Seite stehen, führen Sie einen Rechtsklick auf die AdapterCommandGroup aus und wählen den Befehl zum Hinzufügen von Befehlen. In den Dialog selektieren Sie nur die Kommandos für die vorherige (PrevPage) Seite, Gehe zu einer Seite (GotoPage) und nächste (NextPage) Seite.

Wenn Sie zufrieden sind, können Sie den Webseiteneditor schließen, damit wir ein anderes Webseitenmodul erstellen können.

Employees
Wählen Sie wieder Datei | Neu - Andere, selektieren dort ein neues WebSnap-Seitenmodul und in dem Dialog selektieren Sie wieder einen AdapterPageProducer. Und dieses Mal setzen Sie den Seitennamen auf Employees. Speichern Sie die resultierende Unit als pmEmployees und fügen wieder wDataMod der Uses-Klausel hinzu (damit wir den dsaEMP-DataSetAdapter verwenden können).

Führen Sie einen Doppelklick auf den AdapterPageProducer aus, um den Webseiteneditor zu starten. Dieses Mal fügen Sie eine AdapterForm, gefolgt von einer AdapterCommandGroup und AdapterFieldGroup hinzu. Weisen Sie die DisplayComponent-Eigenschaft der AdapterCommandGroup der AdapterFieldGroup zu und die Adapter-Eigenschaft der AdapterFieldGroup dsaEMP vom WebSnap-Datenmodul. Dies präsentiert Ihnen wieder die Daten zur Designzeit (siehe Abb. 17).


Abb. 7: Webseiteneditor

Beachten Sie die Befehlsschaltflächen, welche explizit der AdapterCommandGroup hinzugefügt wurden, damit wir die caption-Eigenschaften ändern können, welche in der Originalausführung zu lang sind (verwenden Sie einfach Row in jeder Beschriftung anstatt von DeleteRow, FirstRow, PrevRow, etc.). Sie können natürlich auch jede Beschriftung ind deutsche Worte übersetzen, wenn Sie das wünschen.

Testen
Nun speichern Sie Ihre Arbeit, kompilieren sie und führen das Projekt aus. Dies wird das leere WAD-Formular starten, um anzuzeigen, das Ihre Web-Debugger-Anwendung verfügbar ist, durch den Web App Debugger getested (oder debugged) zu werden. Dieses Tool finden und starten Sie beispielsweise aus dem Tools-Menü. Nachdem Sie den Dialog gestartet haben, müssen Sie auf der Startbutton klicken, um die Beschriftung von dem URL neben dem Button zu aktivieren. Wenn Sie auf die aktive URL-Beschriftung klicken, wird der Defaultbrowser starten und alle verfügbaren Web-Debugger-Anwendungen anzeigen - inklusive WAD.Entwickler.

Selektieren Sie diejenige, die Sie ausführen wollen und Klicken Sie auf Go. Dies wird die Startseite Ihrer WebSnap-Applikation anzeigen - genauso wie die zwei Links zur Jobs- und Employees-Seite. Beide Seite werden ihre Ausgabe genau so präsentieren, wie wir sie diese im Web App Debugger vorbereitet haben. In Abbildung 8 sehen Sie die Jobs-Seite im Browser mit den Seitenbutton.


Abb. 8: WebSnap-Applikation in Browser

Und in Abbildung 9 sehen Sie die Employees-Seite im Editierzustand (nachdem ich auf den Edit-Button geklickt habe). Beachten Sie, dass Sie nach irgendeiner Änderung im Browser diese Änderung nur dann in die InterBase-Datenbank zurückschreiben können, wenn Sie auf den Apply-Button klicken (oder wieder den Browse-Button, welcher implizit Apply zuerst ausführt). Dies wird die Änderungen auf das ClientDataSet (cdsEMP) im WebSnap-Datenmodul anwenden. Nichtsdestotrotz ist das nicht genug, da der ClientDataSet dann sicherstellen muss, dass das Update ebenso auf die Employee-Tabelle in der InterBase-Datenbank angewandt wird.

Für das müssen wir eine Codezeile in den OnAfterPost-Eventhandler der cdsEMP ClientDataSet-Komponente (im WebSnap-Datenmodul) notieren, die die ApplyUpdates-Methode wir folgt aufruft:

procedure TWebDataModule1.cdsEMPAfterPost(DataSet: TDataSet);
begin
(DataSet as TClientDataSet).ApplyUpdates(0)
end;

Beachten Sie, das dies nur dann notwendig ist, wenn dbExpress (oder DataSnap) verwendet wird und nicht, wenn die BDE oder eine lokale ClientDataSet-Komponente, die mit einem lokalen MyBase-File verbunden ist, zum Einsatz kommt.


Abb. 9: WebSnap-Applikation in Browser

Abschließend - bevor Sie die Applikation in der Realität ausliefern wollen - sollten Sie sicherstellen, dass alle Datasets (die zwei TSQLTables ebenso wie die TClientDataSets) zur Designzeit geschlossen sind. Sie werden geöffnet, wenn sie von den Seitenmodulen benötigt werden und zu der Zeit ebenso auf den richtigen Record positioniert. Speziell für Editier- und Anwendungsoperationen ist es essentiell, dass die Datasets nicht bereits offen sind (das mag ein Bug in Delphi seit der Version 6 sein, aber immer noch vorhanden). Mehr der realitätsbezogenen Deployment-Details werden das nächste Mal behandelt.

Next Time
Das nächste Mal will ich die aktuelle WebSnap-Applikation erweitern und Ihnen zeigen, wie wir Master-Detail-Beziehungen realisieren können (welche Angestellten haben welchen bestimmten Job) und wie wir Zugriffsrechte (authorization) in der Applikation setzen können, da es natürlich keine gute Idee wäre, die Gehaltinformation von jedem Angestellten zu veröffentlichen. All das und mehr das nächste Mal - bleiben Sie dabei


    Hat Ihnen dieser Artikel gefallen? Dann abonnieren Sie das Entwickler Magazin direkt über unser Online-Formular.



zur vorherigen Seite
zurück
an den Anfang der Seite
nach oben
Diesen Artikel drucken
drucken
Diesen Artikel weiterempfehlen
empfehlen
Software & Support Verlag GmbH