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