Getting Started with Delphi DataSnap 2009
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.
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.
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.
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:
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.
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.
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.
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.
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).


Comments
-
Pawel Glowacki Monday, 26 January 2009
@Rick, http://dn.codegear.com/article/39245
@rap, I will have a look:-) -
Erwin Mouthaan Wednesday, 28 January 2009
Thank you for the article.
Quote: "You can also see the name of the active project in the title of the RAD Studio window itself"
Not quite. If the uFormServer unit is active in the Code Editor the title of the server project is displayed in the RAD Studio window, even if you have double-clicked on the client project in the Project Manager to make it active.
Regards,
Erwin -
Hello Pawel,
Thank you for this clear and useful article.
Everything works... until I'm trying to deploy the little server application on my IIS6 server and try to acces it through Internet.
I don't know where to deploy the server application how to configure the IIS.
Do you know where this is explained ?
A local application server is very beautiful but quite useless !
Merci !
Jean-Pierre -
@Jean-Pierre,
DataSnap 2009 servers are not designed to be hosted in the IIS. DataSnap 2009 uses TCP/IP protocol for client/server communication, and internal the "TDSTCPServerTransport" component is built using "TIdTCPServer" Indy component.
I would not say that a standalone server is useless. However it would be nice to have some kind of activation mechanism in place, so the server could be started "on the fly" when a client request arrive (like SmartAgent in CORBA). But this is chiecken and egg problem. There always must be something that is running before clients can talk to it (like INETINFO.EXE). -
Pascal Amani Sunday, 21 June 2009
Hello Pawel
I think yu very much for your article.
But I want to if Intraweb (VCL for the web) matches well with a DataSnap 2009 server application.
Can I use DataSnap 2009 client Components in my Intaraweb application so that my intraweb application can be client for DataSnap 2009 application server?
Because I'll buy RadStudio 2009 for an application i have to create.
Thinks -
@Iwan,
The connection to the server is a plain TCP connection implemented using INDY TIdTcpServer component (member of TDSTCPServerTransport component). I do not think that you would be able to detect if client is still connected. TDSServer component has "OnConnect" and "OnDisconnect" events that are fired when a client connects and disconnects. I hope it helps:-) -
iwan cs Thursday, 16 July 2009
Hi, thanks for the response, i've managed to get deeper into the event fired when a client connection is opened, and i know about the TDSServer.OnConnect event.
But now i have this situation that i need:
- The TDSServer.OnConnect event have properties that stored the IPAddress of the client connected to the server
- I Need that information stored on the TDSServerClass.OnCreateInstance also, so that i can make sure that the client that creating the TDSServerClass instance will be the same as long as the session period. I will save the client connection information on the TDSServerClass class instance.
I hope you get what i mean, and if you don't mind, can i contact you via email? thanks before
Iwan CS -
@Miguel,
The answer to both questions is negative. DataSnap uses its own communication protocol based on JSON, so clients have to be DataSnap (Delphi, C++Builder or Delphi Prism). In Delphi 2010 the support for HTTP protocol was introduced and also possibility to expose server methods as URLs, so it is also possible to have pure HTTP clients.
Regarding CORBA - it is not supported anymore in Delphi. -
Please login first in order for you to submit comments
- Page :
- 1
Nice reading, thank you. What about distributing the server et get it started on host computer, any dll to be included? - I'm looking for similar 'getting started' concerning database connection using DataSnap 2009. Any reference to suggest?