Delphi Labs DataSnap XE - Callbacks

7
EDN» Delphi Delphi Labs: DataSnap XE - Callbacks By: Pawel Glowacki Abstract: "Delphi Labs" DataSnap XE "Callbacks" demo shows the most simple use of callbacks. Both client and server are Delphi VCL Forms applications. This tutorial covers broadcasting to a channel and notifying a specific callback. Introduction The objective of this tutorial is to create the simplest possible DataSnap Delphi client and server applications that use callbacks for communication. In this lab exercise, we are going to use Delphi XE to build a simple callbacks demo system consisting of server and client applications. The server application will serve as a communication hub for multiple client applications running in the network. It is a more realistic scenario as compared to sending notifications directly from server application user interface to clients. In most scenarios, a server application will not have any user interface, so callbacks are a great mechanism for clients to communicate with each other. Message Exchange Patterns The most common message exchange pattern in client/server applications is “request-response”. One application (“a client”) is sending a message (“a request) to another application running in the network (“a server”) and the server sends back a message (“a response"). Hide image In many real world applications, it would also be useful to have the opposite situation, where it is a server application that sends a message (“a notification”) to a client application. A server application may want to inform a client that something interesting has happened on the server. This is called “a callback” – a situation when server “calls back” the client. expand view>> Hide image Imagine a chat application where multiple client applications connected to the server can communicate with each other. One client sends a message to the server and then the server forwards this message to one or more connected client applications. expand view>> Hide image The possibility for the server to asynchronously send a notification to one or more clients is very useful in many scenarios. expand view>> DataSnap Callbacks and Channels In order to use callbacks in DataSnap applications, you need to define a custom callback class that is inherited from the abstract “TDBXCallback” class and override one of its virtual, abstract “Execute” methods which are called by the server and executed on the client. The “TDBXCallback” class is defined in the “DBXJSON” unit as follows (some members striped out for readability): unit DBXJSON; interface // … type TDBXCallback = class abstract public function Execute(const Arg: TJSONValue): TJSONValue; overload; virtual; abstract; function Execute(Arg: TObject): TObject; overload; virtual; abstract; // … end; In the previous version of DataSnap that came with RAD Studio 2010 it was only possible to use so-called “lightweight” callbacks. A callback instance was passed to a long running server method as a parameter from a client, so the server could call its “Execute” method within the duration of a method call – for example to notify the client about the progress of a long running operation. In RAD Studio XE, the latest version available, so called “heavyweight” callbacks have been introduced. They can be used throughout the whole lifetime of a client application and not only during a server method call. This opens a lot of new possibilities for building different types of applications. In the remaining part of this tutorial we are going to focus on “heavyweight” callbacks and for simplicity we are going to refer to them as just “callbacks”. In DataSnap architecture callbacks are associated with “channels”. In general there could be multiple client applications connected to the server and each of these clients can contain zero or more callbacks. The server can “broadcast” to the channel, so all callbacks on every client that are registered with a specific channel are going to receive this notification. It is also possible to notify a specific callback using its unique identifier used during registering the callback with the server. In this way it is possible to achieve peer-to-peer communication model. We are going to try both approaches: broadcasting to a channel and notifying a specific callback. The server application calls “Execute” method on the client callback asynchronously. This is a very important point to realize. Every Delphi VCL Forms application has its main thread of execution and in case of multithreaded applications any calls from other threads that manipulates graphical user interface of the applications need to be synchronized. This is exactly the situation with using callbacks. The callback “Execute” method is called on a different thread then the main thread of the VCL application. There are different ways of synchronizing calls, but probably the easiest option is to use “TThread.Queue” class method, which asynchronously executes a block of code within the main thread. COMMUNITIES ARTICLES BLOGS RESOURCES DOWNLOADS HELP IN THIS ARTICLE Introduction Message Exchange Patterns DataSnap Callbacks and Channels Implement the Callback Server Create the Client Application Implementing a callback Broadcasting to the Channel Notifying Callbacks The Bigger Picture Summary TRANSLATIONS RATING Download Delphi XE6 now! Get Free Trial Webinars on demand! Delphi 15,314 people like Delphi. Facebook social plugin Like Like More social media choices: Delphi on Google+ @RADTools on Twitter Download Trial Buy Now LOG ON | | EMBARCADERO HOME ENGLISH LOCATION Share This Watch, Follow, & Connect with Us Delphi Labs: DataSnap XE - Callbacks 5/14/2014 http://edn.embarcadero.com/article/41374 1 / 7

description

Delphi Labs" DataSnap XE "Callbacks" demo shows the most simple use of callbacks. Both client and server are Delphi VCL Forms applications. This tutorial covers broadcasting to a channel and notifying a specific callback

Transcript of Delphi Labs DataSnap XE - Callbacks

  • EDN Delphi

    Delphi Labs: DataSnap XE - CallbacksBy: Pawel Glowacki

    Abstract: "Delphi Labs" DataSnap XE "Callbacks" demo shows the most simple use of callbacks. Both client and server are Delphi VCL Forms applications. This tutorial covers broadcasting to a channel andnotifying a specific callback.

    IntroductionThe objective of this tutorial is to create the simplest possible DataSnap Delphi client and server applications that use callbacks for communication.

    In this lab exercise, we are going to use Delphi XE to build a simple callbacks demo system consisting of server and client applications. The server application will serve as a communication hub for multipleclient applications running in the network. It is a more realistic scenario as compared to sending notifications directly from server application user interface to clients. In most scenarios, a server application willnot have any user interface, so callbacks are a great mechanism for clients to communicate with each other.

    Message Exchange PatternsThe most common message exchange pattern in client/server applications is request-response. One application (a client) is sending a message (a request) to another application running in the network(a server) and the server sends back a message (a response").

    Hide image

    In many real world applications, it would also be useful to have the opposite situation, where it is a server application that sends a message (a notification) to a client application. A server application maywant to inform a client that something interesting has happened on the server. This is called a callback a situation when server calls back the client.

    expand view>>

    Hide image

    Imagine a chat application where multiple client applications connected to the server can communicate with each other. One client sends a message to the server and then the server forwards this messageto one or more connected client applications.

    expand view>>

    Hide image

    The possibility for the server to asynchronously send a notification to one or more clients is very useful in many scenarios.

    expand view>>

    DataSnap Callbacks and ChannelsIn order to use callbacks in DataSnap applications, you need to define a custom callback class that is inherited from the abstract TDBXCallback class and override one of its virtual, abstract Executemethods which are called by the server and executed on the client. The TDBXCallback class is defined in the DBXJSON unit as follows (some members striped out for readability):

    unit DBXJSON;

    interface

    //

    type TDBXCallback = class abstract public function Execute(const Arg: TJSONValue): TJSONValue; overload; virtual; abstract; function Execute(Arg: TObject): TObject; overload; virtual; abstract; // end;

    In the previous version of DataSnap that came with RAD Studio 2010 it was only possible to use so-called lightweight callbacks. A callback instance was passed to a long running server method as aparameter from a client, so the server could call its Execute method within the duration of a method call for example to notify the client about the progress of a long running operation.

    In RAD Studio XE, the latest version available, so called heavyweight callbacks have been introduced. They can be used throughout the whole lifetime of a client application and not only during a servermethod call. This opens a lot of new possibilities for building different types of applications. In the remaining part of this tutorial we are going to focus on heavyweight callbacks and for simplicity we are goingto refer to them as just callbacks.

    In DataSnap architecture callbacks are associated with channels. In general there could be multiple client applications connected to the server and each of these clients can contain zero or more callbacks.The server can broadcast to the channel, so all callbacks on every client that are registered with a specific channel are going to receive this notification. It is also possible to notify a specific callback using itsunique identifier used during registering the callback with the server. In this way it is possible to achieve peer-to-peer communication model.

    We are going to try both approaches: broadcasting to a channel and notifying a specific callback.

    The server application calls Execute method on the client callback asynchronously. This is a very important point to realize. Every Delphi VCL Forms application has its main thread of execution and in case ofmultithreaded applications any calls from other threads that manipulates graphical user interface of the applications need to be synchronized. This is exactly the situation with using callbacks. The callbackExecute method is called on a different thread then the main thread of the VCL application. There are different ways of synchronizing calls, but probably the easiest option is to use TThread.Queue classmethod, which asynchronously executes a block of code within the main thread.

    COMMUNITIES ARTICLES BLOGS RESOURCES DOWNLOADS HELP

    IN THIS ARTICLE

    IntroductionMessage Exchange PatternsDataSnap Callbacks andChannelsImplement the Callback ServerCreate the Client ApplicationImplementing a callbackBroadcasting to the ChannelNotifying CallbacksThe Bigger PictureSummary

    TRANSLATIONS

    RATING

    Download Delphi XE6 now!Get Free Trial

    Webinars on demand!

    Delphi

    15,314 people like Delphi.

    Facebook social plugin

    LikeLike

    More social media choices:

    Delphi on Google+

    @RADTools on Twitter

    Download Trial

    Buy Now

    LOG ON | |EMBARCADERO HOME ENGLISHLOCATION

    Share This

    Watch, Follow, & Connect with Us

    Delphi Labs: DataSnap XE - Callbacks 5/14/2014

    http://edn.embarcadero.com/article/41374 1 / 7

  • Implement the Callback ServerOur server application is going to be super simple. The callback functionality is built into the DSServer component, which is the central point of every DataSnap server application. In this demo we do not evenneed to create any server methods, because we are only going to communicate between client applications using callbacks.

    The first step is to create a new DataSnap server application using DataSnap Server wizard.

    Select File -> New -> Other and from the New Items dialog double-click on the DataSnap Server icon in the Delphi Projects -> DataSnap Server category.

    Hide image

    In the first tab keep the default DataSnap Project type which is VCL Forms Application.

    expand view>>

    Hide image

    On the second tab we keep TCP/IP as the communication protocol and we can uncheck the option for generating server methods class, because it is not needed for this simple callbacks demo. If you leavethe default option to generate server methods, it is not a problem. We are just not going to use them.

    expand view>>

    Hide image

    On the third screen we keep the default value 211 for the TCP/IP Port. It is always a good idea to click on the Test Port to make sure that it is available.

    expand view>>

    Because we have unchecked the option to generate a server class earlier in the wizard, we are not presented with the screen to select a base class for our server method class.

    Click on Finish and the wizard should create a new project with just two units: main form and server container. There is no server methods unit this time.

    Click on File -> Save All.

    Create a new directory for all files in this lab for example C:\DataSnapLabs\SimpleCallbacks.

    Save main application form as FormServerUnit and keep the default name for the server container unit typically ServerContainerUnit1.

    Save project as SimpleCallbacksServer.

    Select the main form in the Object Inspector and change its Name property to FormServer and its Caption property to Delphi Labs: DataSnap XE - Simple Callbacks Server.

    Hide image

    @RADTools on Twitter

    Delphi Labs: DataSnap XE - Callbacks 5/14/2014

    http://edn.embarcadero.com/article/41374 2 / 7

  • Open the server container unit and verify that there are only two components there: DSServer1 and DSTCPServerTransport1 components.

    Hide image

    Thats it. Our server is ready and we do not need to implement anything special on the server, because the support for callbacks is built into the DSServer1 component. We also have a transport componentso that external clients can communicate with the DSServer1 instance in the server.

    Save All, Run without Debugging and minimize the server application. It should be running for the rest of this tutorial.

    Create the Client ApplicationNow it is the time to create a client. Just right click on the Project Group node in the Project Manager window and select Add New Project.

    Hide image

    From the New Items dialog select VCL Forms Application from Delphi Projects category.

    Hide image

    Click OK. A new project will be added to the existing project group.

    Click on File -> Save All.

    Locate the folder where the server project has been saved and save there the main form unit of the client application as FormClientUnit, the new project as SimpleCallbacksClient and the project group asSimpleCallbacksGrp.

    Implementing a callbackThe next step is to define a new callback class derived from TDBXCallback and implement its Execute method. This method will be called asynchronously by the server to notify the client.

    Add DBXJSON unit to the uses clause of FormClientUnit, because this is where TDBXCallback class is defined.

    Define TMyCallback class and override its virtual abstract Execute method. There are two variants of the Execute method you could override. One that takes and returns a TObject and the second thattakes and returns TJSONValue. Im going to use the second option, because at the end both methods use JSON as the underlying format for sending messages.

    At this stage the client unit source code looks like this:

    unit FormClientUnit;

    interface

    uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DBXJSON;

    type TMyCallback = class(TDBXCallback) public function Execute(const Arg: TJSONValue): TJSONValue; override; end;

    TFormClient = class(TForm) private { Private declarations } public { Public declarations } end;

    var FormClient: TFormClient;

    Delphi Labs: DataSnap XE - Callbacks 5/14/2014

    http://edn.embarcadero.com/article/41374 3 / 7

  • implementation

    {$R *.dfm}

    { TMyCallback }

    function TMyCallback.Execute(const Arg: TJSONValue): TJSONValue;begin // ...end;

    end.

    So what should happen when our callbacks Execute method is called? This is really up to the programmer and depends on the application logic. To keep this example simple, we are going to add a memocomponent to the client form and when the callback Execute method is called we are going to add a text line to the memo with the contents of the Arg parameter converted to a text string.

    Lets define a public method on the form class called LogMsg that will take a string parameter with a message to display in the memo. We are also going to add a timestamp.

    Drop TMemo component on the client form. Change its name in the Object Inspector to MemoLog.

    Add to TFormClient class a public procedure LogMsg(const s: string) and implement it in the following way:

    procedure TFormClient.LogMsg(const s: string);begin MemoLog.Lines.Add(DateTimeToStr(Now) + ': ' + s);end;

    Now is the tricky part. We need to make a thread-safe call to the TFormClient.LogMsg procedure from our TMyCallback.Execute method.

    Lets define the thread-safe version of our LogMsg method, so it could be called from a different thread.

    procedure TFormClient.QueueLogMsg(const s: string);begin TThread.Queue(nil, procedure begin LogMsg(s) end );end;

    The syntax for using anonymous methods may seem to be exotic at first, but think about it like treating code as data. You just pass a block code as the second parameter to TThread.Queue method. Thismethod is a class method of the TThread class, so we do not need to instantiate TThread object in order to be able to call it.

    Now we can call the thread-safe version of our LogMsg method directly from the TMyCallback.Execute method.

    function TMyCallback.Execute(const Arg: TJSONValue): TJSONValue;begin FormClient.QueueLogMsg(Arg.ToString); Result := TJSONTrue.Create;end;

    We can return anything from our Execute method, as long as we do return something, so we just return JSON true value.

    Now we need to register our callback with the server, so it is informed about what to call back.

    There is a special class designed for managing client callbacks called TDSClientCallbackChannelManager and it is defined in the DSHTTPCommon unit.

    Drop a TDSClientCallbackChannelManager component on the form and set its properties in the Object Inspector.

    We need to select a name for a channel on the server that we want to associate our callback with. Lets call our channel DelphiLabsChannel.

    We also need to specify CommunicationProtocol, DSHostname and DSPort properties.

    Hide image

    The next thing we are going to do is to clear the ManagerId property, because we are going to generate this value at runtime.

    This is a very important thing to do. We want every client application instance to be treated by the server differently. The ManagerId value is used at the server to identify clients, so this value has to be differentfor every client instance.

    We are going to use TDSClientCallbackChannelManager.RegisterCallback method to register our callback instance with the server. This method takes two parameters: the name of the callback the uniquelyidentifies it on the server and the reference to the callback instance, in our case this will be FMyCallback.

    If you look into the constructor of the TDSClientCallbackChannelManager class you will see that the value for ManagerId is generated by a call to TDSTunnelSession.GenerateSessionId method thatreturns a random string made of three numbers. We are going to use this functionality to generate a unique name for our callback instance.

    Add FCallbackName: string private field to the form class and add code to initialize it in the forms OnCreate event. You will also need to add DSService unit to the uses clause, because this is where theTDSTunnelSession class is defined.

    We also need to add code to initialize DSClientCallbackChannelManager1.ManagerId property.

    uses DSService; // for TDSTunnelSession

    //

    procedure TFormClient.FormCreate(Sender: TObject);begin DSClientCallbackChannelManager1.ManagerId := TDSTunnelSession.GenerateSessionId;

    FMyCallbackName := TDSTunnelSession.GenerateSessionId;

    DSClientCallbackChannelManager1.RegisterCallback( FMyCallbackName, TMyCallback.Create );end;

    The callback reference that we pass to the RegisterCallback method is owned by the DSClientCallbackChannelManager1, so we do not need to keep this reference.

    At this point we are ready to receive callbacks. The next step is to implement a functionality to broadcast to a channel. All callbacks registered with a specified channel are going to be notified by the server.

    Broadcasting to the ChannelNote that we could now create a completely different client application for broadcasting to the channel, and our client application, as it is implemented now, would be able to receive the notifications.

    To keep things simple, we are going to add broadcasting to channel functionality to our demo client application, and later we are going to run two instances of the same client application to see if we can sendmessages from one client to another.

    The first thing to do on the client is to add a TSQLConnection component to the form in order to be able to connect to the server. Probably the easiest way to do it is with IDE Insight. Just press F6 and starttyping TSQLConnection to search for it and then select to add to the form.

    Set the Driver property of SQLConnection1 component on the form to DataSnap.

    Set LoginPrompt property to False.

    Set the Connected property to True to verify that the client is able to connect to the server.

    In a typical scenario, at this stage we would need to generate DataSnap client proxy code in order to be able to call server methods. In this case, however, this step is not necessary, since there are no customserver methods on the server! The Delphi DataSnap proxy generator uses TDSAdminClient class as a base class for client proxy classes. This class already contains quite a lot of functionality that can beused on its own, including broadcasting to channels and notifying callbacks. We are going to use TDSAdminClient class directly as the way to interact with the server.

    We need to extend our client application user interface a bit to support broadcasting to a channel.

    Add TButton component to the form. Set its Name property to ButtonBroadcast and its Caption property to Broadcast to Channel.

    Add a TEdit component. Set its Name property to EditMsg and optionally enter some default message into it.

    Delphi Labs: DataSnap XE - Callbacks 5/14/2014

    http://edn.embarcadero.com/article/41374 4 / 7

  • You can also add a label next to the message edit, to indicate that this is the place to enter messages.

    Double-click on the button and add the following code to be able to broadcast to messages to a channel. Note that we could pass arbitrary complex data encoded as JSON, so it could be something morecomplex than just a string.

    uses DSProxy; // >

    What about pure peer-to-peer communication? Maybe I do not want to send message to all callbacks in the channel?

    It would be much better if a given client could send message to one and only one callback instance on a different client.

    This is also possible, but and we need to extend our client application to support notifying specific callbacks.

    Notifying CallbacksStop both clients, but keep the server running.

    The TDSAdminClient class also contains NotifyCallback method that could be used to achieve peer-to-peer communication model. This method has the following signature:

    function TDSAdminClient.NotifyCallback(ChannelName: string; ClientId: string; CallbackId: string; Msg: TJSONValue; out Response: TJSONValue): Boolean;

    The ChannelName parameter specifies the name of the communication channel the destination client callback is associated with. ClientId and CallbackId are values that were passed toRegisterCallback method of the DSClientCallbackChannelManager1 at the destination client instance. They were both generated randomly. Msg is the JSON value that contains information that we want tosend to the destination callback and Response is an out parameter and contains JSON value with encoded response.

    There is also TDSAdminClient.NotifyObject that takes similar parameters, but instead of using TJSONValue for input and output parameters, it is using a TObject-descendant that is automatically serializedand deserialized from its JSON representation.

    The process of notifying individual callbacks is going to be a little bit manual that will involve copying and pasting ClientId and CallbackId values from one running instance to another.

    Lets add to our client application four additional TEdit components, four TLabel components and a TButton.

    Change Caption property of the button to Notify Callback and rename edits to: EditLocalClientId, EditLocalCallbackId, EditDestinationClientId, EditDestinationCallbacksId.

    In the OnCreate event of the client form add code to initialize edits:

    EditLocalClientId.Text := DSClientCallbackChannelManager1.ManagerId;EditLocalCallbackId.Text := FMyCallbackName;EditDestinationClientId.Text := '';EditDestinationCallbackId.Text := '';

    Double-click on the Notify Callback button and enter the following code to notify remote callback:

    procedure TFormClient.ButtonNotifyClick(Sender: TObject);var AClient: TDSAdminClient; aResponse: TJSONValue;begin AClient := TDSAdminClient.Create(SQLConnection1.DBXConnection); try AClient.NotifyCallback( DSClientCallbackChannelManager1.ChannelName, EditDestinationClientId.Text, EditDestinationCallbackId.Text, TJSONString.Create(EditMsg.Text), aResponse ); finally AClient.Free; end;end;

    Now start two or more client application instances and copy ClientId and CallbackId from a client that you would like to receive notifications to destination edits of the client you want to send notification.

    Hide image

    Thats it! We have implemented peer-to-peer communication between Delphi DataSnap client applications!

    expand view>>

    The Bigger PictureThe idea behind this Delphi Labs demo was to make it as simple as possible.

    It is also possible to use callbacks with the HTTP protocol in addition to TCP/IP. Similarly in this demo we have used DataSnap DBX architecture, but the callbacks are also available with DataSnap REST.

    Delphi Labs: DataSnap XE - Callbacks 5/14/2014

    http://edn.embarcadero.com/article/41374 5 / 7

  • RAD Studio XE comes with a very interesting demo project that demonstrates all these possibilities.

    You can open this demo directly from inside the IDE using new Subversion integration.

    Select File -> Open from Version Control and enter the following URL in the URL or Repository text box:

    https://radstudiodemos.svn.sourceforge.net/svnroot/radstudiodemos/branches/RadStudio_XE/Delphi/DataSnap/CallbackChannels

    In the Destination text box enter a folder that you want to download the demo to. In my case I have created a local C:\DataSnapLabs\CallbackChannelsDemo folder.

    Hide image

    Just click on OK and be patient. You will see initially empty window with Updating title. After a while it will show the names of all files checked out from the radstudiodemos public repository onSourceForge.

    Hide image

    There are three projects there. ChannelsServerProject is the main server application. DBXClientChannels and RESTClientChannels are two client applications. One based on DataSnap DBX architectureand one based on the new DataSnap REST architecture introduced in RAD Studio XE.

    Keep the server project selected and click OK to open it in the IDE.

    Hide image

    Click OK to close the Updating window. At this stage only the server project is opened in the IDE.

    expand view>>

    Now we need to add both client projects to a project group, so we have all three demo projects available inside the IDE.

    Right click on the Project Group node in the Project Manager window, select Add Existing Project and choose DBXClientChannels project.

    Right click again on the Project Group, select Add Existing Project and this time choose RESTClientChannels project.

    Select File -> Save All or just click on the Save All icon.

    Give the project group a name. I have chosen for CallbackChannelsDemo.

    At this stage my Project Manager looks like this:

    Hide image

    I will leave you here. There is plenty to explore in this demo

    SummaryIn this Delphi Lab we have used Delphi XE for building a system consisting of server and client native Win32 applications communicating with each other using TCP/IP protocol and using callbacks.

    Callbacks represent a very useful alternative to a traditional request/response message exchange pattern in distributed applications.

    With callbacks the server application is able to send asynchronous notifications to one or more registered callback instances inside connected client applications.

    Delphi Labs: DataSnap XE - Callbacks 5/14/2014

    http://edn.embarcadero.com/article/41374 6 / 7

  • Copyright 1994 - 2013 Embarcadero Technologies, Inc. All rights reserved. Site Map

    The full source code for this article is available from Embarcadero Code Central http://cc.embarcadero.com/item/28288

    The video version of steps described in this article can be found on YouTube. There are three parts of the video demonstration:

    http://www.youtube.com/watch?v=5zO3_g9Z-wchttp://www.youtube.com/watch?v=geEzwg8XX8khttp://www.youtube.com/watch?v=Hwode7a8O5k

    More information about Delphi can be found on the Delphi home page http://www.embarcadero.com/products/delphi

    Move mouse over comment to see the full text

    Reply Posted by admzhen admzhen on Aug 19 2013

    C++ Labs: DataSnap XE2 - CallbacksWe desperately need illustrations for DataSnap XE2 - Callbacks written in C++. Thank you

    Reply Posted by Fellipe Henrique on Oct 11 2012

    Delphi Labs: DataSnap XE - CallbacksHo can send this Broadcast message from Server?

    Reply Posted by Cleidson Barbosa on Mar 22 2012

    Delphi Labs: DataSnap XE - CallbacksCongratulations, Pawel. Very interesting article.

    Reply Posted by Lena Ilicheva on Apr 16 2011

    Delphi Labs: DataSnap XE - CallbacksThank you for the article. Where on Embarcadero site can one find articles about DataSnap application in C++Builder XE? We desperately need illustrations for DataSnap written in C++. Thank you.

    Server Response from: ETNASC04

    LATEST COMMENTS

    Delphi Labs: DataSnap XE - Callbacks 5/14/2014

    http://edn.embarcadero.com/article/41374 7 / 7

    Delphi Labs: DataSnap XE - CallbacksIN THIS ARTICLE

    IntroductionMessage Exchange PatternsTRANSLATIONSRATING

    DataSnap Callbacks and ChannelsImplement the Callback ServerCreate the Client ApplicationImplementing a callbackBroadcasting to the ChannelNotifying CallbacksThe Bigger PictureSummaryLATEST COMMENTS