Getting Started with Delphi DataSnap 2009

By: Pawel Glowacki

Abstract: Step-by-step instruction for getting started with Delphi DataSnap 2009 “Hello World” system.

Introduction

One of the main new features of RAD Studio 2009 is DataSnap 2009 framework for building multitier database applications. In fact DataSnap 2009 is more than that. It is a component-based architecture for creating arbitrary applications that communicates over the network. It has never been easier to quickly create server and client applications in Delphi and C++Builder!

The new DataSnap 2009 architecture extends the DBX4 database driver framework introduced in Delphi 2007 and C++Builder 2007. The DBX4 framework abstracted away the concept of a database driver and introduced the notion of extensible command types. DataSnap 2009 takes advantage of the DBX4 extensibility and adds to the portfolio of existing databases drivers the new “DataSnap” driver that - from the perspective of a client application - looks very much like a database, but in reality provides connectivity to a DataSnap server application. Similarly the new “DSServerMethod” command type for invoking methods on server objects has been added to “TDBXCommandTypes” class.

The DataSnap 2009 is part of the Visual Component Library (VCL) that is shared between Delphi and C++Builder. In this article I’m going to focus on Delphi 2009, however almost all of the functionality described in here is also applicable to C++Builder 2009.

DataSnap 2009 “Hello World”

I’m going to walk you through the steps for building a simple “Hello World” DataSnap 2009 system consisting of a server and a client application. The server application will provide the “Echo” function that accepts a string and returns a string that echoes the original value. The client application will provide means for entering an arbitrary string, call the “Echo” function with a string provided and display the string returned from the server. Too simple? Yeah… but a good starting point for more complex things!

Are you ready? Is your Delphi 2009 already installed and started? You do not have Delphi 2009 installed? Shame on you Grab the trial from http://www.codegear.com/products/delphi/win32 and give the best version of Delphi ever a try!

Steps for Building DataSnap 2009 Server Application

Create new Delphi (or C++Builder) ”VCL Forms Application”, click on “Save All” from the “Files” menu. Save the main form’s unit as “uFormServer” and the project as “DelphiDataSnapEchoServer”. In the Object Inspector change the “Name” property of the form to “FormServer” and “Caption” property to “Delphi 2009 DataSnap Echo Server”.

Now we are going to transform this standard Delphi application into a DataSnap server. This is done with components from “DataSnap Server” tab. It contains three different components and we need all of them. Double-click on “TDSServer”, “TDSTCPServerTransport” and “TDSServerClass” components in the Tool Palette to add them to the server form.

Hide image

Figure 1: DataSnap Server Application Main Form

The “DSServer1” component is the logical heart of the DataSnap server application. It contains “Start” and “Stop” methods for starting and stopping the server, and also very handy “AutoStart” property. By default it is set to “True”, so the server starts automatically at the application startup. You only need one “TDSServer” component per server application.

The “DSTCPServerTransport1” component contains “TIdTCPServer” Indy component that implements a multithreaded TCP server listening for incoming client connections on multiple threads. This component does not have any events, but it contains “Server” property that needs to be set to “DSServer1”. It also has “Port” property that indicates TCP port to be used. By default it is set to port 211.

The “DSServerClass1” component represents… yeah… you are right… a server class:-) It also has the “Server” property that needs to be set to “DSServer1”. In this way all three components are linked together. The “TDSServerClass” component contains “OnGetClass” event that must be implemented by the programmer. If you fail to implement this event the application immediately after start will raise a TDBXError event with the “OnGetClass event not set or it did not provide a class reference” message. The “OnGetClass” event has the “PersistentClass” argument that is passed by reference. In the event handler code the programmer needs to assign to “PersistentClass” a class reference to a server class. This is probably one single most important concept to understand about the DataSnap 2009 architecture. We are assigning to “PersistentClass” a class reference and not an object reference.

The DataSnap server will automatically create and destroy instances of server classes. The instancing of a server class is controlled by the “TDSServerClass.LifeCycle” property that can have one of the three possible values: “Server”, “Session” and “Invocation”.

The lifecycle set to “Server” means that the DataSnap server will create one instance of a server class that will be used by all clients connected to the server application. This represents a “singleton” pattern. Be careful when using “Server” lifecycle as your server class implementation needs to be thread-safe, as it is possible that this singleton object will be accessed simultaneously from multiple threads.

The default “LifeCycle” value is “Session”. This means that the DataSnap server will create one instance of a server class for every connected client. This is similar to the concept of a “stateful” session bean in JEE.

The third possible value for “LifeCycle” property is “Invocation”. A server class instance will be created and destroyed for every method call arriving from a client and the state of a server class will not be preserved between method calls.

In order to implement “OnGetClass” event we need to add to our DataSnap server project a server class. Select “File | New | Other” from “File” menu and double-click on the “Server Module” icon from the “Delphi Files” category.

Hide image

Figure 2: New DataSnap 2009 “Server Module” Item

This will add a new server module to the project. Save the new unit as “uServerModule”. At this stage I’m going to do one optional step that aims at highlighting the fact that it is the server that manages the lifecycle of server objects. The server module is ultimately derived from a data module and the Delphi designer automatically added it to a list of auto-created forms in our server application. This is unnecessary, so you can go to “Project | Options” dialog and remove the “DSServerModule1” from the list of auto-created forms in the “Forms” section.

Hide image

Figure 3: DSServerModule1 does not need to be auto-created.

It is also safe to comment out the global “DSServerModule1: TDSServerModule” variable from the server module unit as it is never used.

Now we are going to implement a simple “Echo” function that will accept a string and return a string. I’m going for an enterprise strength echo functionality so my implementation will echo the argument not once, but twice;-) The resulting server module implementation looks like this:

Hide image
Click to see full-sized image

Figure 4: DataSnap Echo server module implementation.

The last step is to implement “DSServerClass1.OnGetClass” event. In the server main form select "DSServerClass1" component and in the Object Inspector double-click on the “OnGetClass” event to generate an empty handler. Add “uServerModule” to the “uses” clause of the main form and implement the event.

Hide image

Figure 5: DSServerClass1.OnGetClass event code.

Our DataSnap Echo server application is now complete.

Client and Server Applications need a piece of shared knowledge to communicate

If you want to have two arbitrary applications to communicate there must be some form of a contract in place that describes what functionality a client can access from a server. Different distributed computing technologies have different ways of solving this problem. In CORBA the contract is described in the form of Interface Definition Language (IDL) document, in DCOM there is a Type Library. In Web Services we have a Web Service Description Language (WSDL) that is used by client applications to generate proxies. DataSnap 2009 does not have any static form of a service description. In order to create a DataSnap client you need to have access to a running server application at design time. This is similar to Web Services where the WSDL document can by typically obtained on-the-fly from a running Web Service application.

Steps for Building DataSnap 2009 Client Application

The DataSnap Server application is already opened in the Delphi IDE and it is the most convenient to add a client application to a project group so we could switch between two projects inside the IDE.

Right-click on the “ProjectGroup1” in the Project Manager, select “Add New Project” from the context menu and go for the new Delphi “VCL Forms Application”. Save all from the “File” menu. Save the main form unit as “uFormClient”, the project as “DelphiDataSnapEchoClient” and the project group as “DelphiDataSnapEchoGrp”. Click somewhere on the form to make sure it is selected in the Object Inspector. Set “Name” property to “FormClient” and “Caption” property to “Delphi 2009 DataSnap Echo Client”.

You can have only one project active at any given point of time in RAD Studio IDE. The Project Manager indicates the active project by displaying the project name with bold font. You can also see the name of the active project in the title of the RAD Studio window itself. Double-click on the project name in the Project Manager to make the project active.

During the development of a DataSnap client application we need to have access to a running instance of the server application. Double-click on the “DelphiDataSnapEchoServer.exe” in the Project Manager to make it active and select “Run | Run Without Debugging” from the main menu to run the server application. We need to have it running while developing the client. You can safely minimize the server application window. Double-click on the “DelphiDataSnapEchoClient.exe” in the Project Manager to switch back to client application.

As discussed earlier DataSnap 2009 extends DBX4 database driver architecture by implementing a special “DataSnap” driver that from the perspective of a client looks like a connection to a database, but in fact provides connectivity to DataSnap servers. That is the reason that we start client development from a “SQLConnection” component. Make sure that the client form is opened in the IDE, go to Tool Palette and double-click on the “TSQLConnection” component from the “dbExpress” category to add it to the form. Go to Object Inspector, expand the “Driver” property and select “Datasnap” driver. Note that the “Driver” property contains now DataSnap specific sub-properties. Make sure that the “HostName” is set to “localhost” (or the DSN name or the IP address of the machine where the server is running) and the “Port” number is set to 211. The “Port” property has to match the value of the “DSTCPServerTransport1.Port” property in the server application.

Additionally change the “SQLConnection1.LoginPrompt” property to “False” to prevent username and password dialog to popup every time we connect to the server.

Right-click on the “SQLConnection1” component on the form and select “Generate DataSnap Client Classes” from the context-menu.

Hide image

Figure 6: Generate DataSnap client classes from SQLConnection1 context menu.

This will add a new unit to the client project. Save it as “uClientClasses”. The generated unit will contain “TDSServerModule1Client” class that can be used to communicate with the server as if it were a local object. DataSnap 2009 uses RTTI (Delphi “reflection” mechanism) for discovering all public and published methods on server classes and generates proxy classes with matching method signatures.

In order to call any method from our server it is necessary to create an instance of “TDSServerModule1Client” and call its “Echo” method that takes and returns a string.

Switch to “FormClient” and add to it “TButton” and “TEdit” components from the Tool Palette. Add “uClientClasses” to the “uses” clause of the “FormClient” (for example using “File | Use Unit” menu). Double click on the “Button1” component and add the following code to the generated “OnClick” event. This will create an instance of a proxy class, call its “Echo” method passing the contents of the edit box and display the result in a dialog box.

Hide image

Figure 7: DataSnap “Echo” client implementation.

Note that the “TDSServerModule1Client” constructor requires a “TDBXConnection” argument that represents the non-visual DBX4 connection object. Luckily “TSQLConnection” class exposes its internal “DBXConnection” as a public property so we can use in our code.

That’s it! Just run the client, enter something into the edit box and click the button to call the “Echo” method on the server and display the result.

Hide image

Figure 8: DataSnap “Echo” client in action.

Summary

The DataSnap 2009 architecture for building multitier database applications is one of the most interesting and innovative new features introduced in RAD Studio 2009. It can be used not only for building database application but also for arbitrary client/server systems that communicate over the network using TCP protocol. RAD Studio 2009 contains Delphi 2009, C++Builder 2009 for building high-performance, native Windows applications and the new Delphi Prism for building .NET applications. DataSnap 2009 technology is available in all of these environments.

The DataSnap 2009 is much more than that. In addition to returning simple types like “string” it is possible to pass more complex types like an array or “TDataSet”. The new “TSqlServerMethod” component can be used to call server methods without generating client classes, and new “TDSProviderConnection” component make it easy to build database applications that can apply database updates from client back to server. With the “ServerConnection” sub-property of the DataSnap “TSQLConnection.Driver” it is even possible to access server-side database connection directly from the client. This functionality is key for building Delphi Prism managed .NET DataSnap clients that communicates with native Delphi 2009 or C++Builder 2009 DataSnap servers.

Note that DataSnap 2009 is a feature of RAD Studio 2009 Enterprise and Architect. It is not available in RAD Studio 2009 Professional.

The electronic version of applications described in this article can be downloaded from the Embarcadero CodeCentral (http://cc.codegear.com/item/26535).



Server Response from: ETNASC01