Friday, July 22, 2016

Delphi DataSnap Irritations,Traps and Tips—I

DataSnap is a client/server technology from Embarcadero that permits rapid, secure and efficient transfer of data between the client and the server. It seems that no matter how many times I implement a DataSnap application I make the same mistakes and then have to spend time looking up the fixes or circumventions. What follows is a first attempt to collect some of the recurring problems I have in a single place so that life going forward is a little easier. As I collect more, I'll add additional posts to document what I've found.

Communication filter ZLibCompression is not registered.

You'll get this irritating error message if you specify the use of a ZLib Compression Filter and forget to include the ZLib compression module. The easiest way to fix this is to add the following unit to the client Interface Uses clause:

DbxCompressionFilter

StackOverflow has a more comprehensive answer from Bob Swart at How to Register the ZLib Compression Filter.

DataSnap OpenSSL Access Violation on finalization

This bug occurs because of an order dependency between Indy and DBXOpenSSL. Although it seems like poor programming practice to require specific initialization and finalization sequences to be maintained, this is never-the-less the source of the problem. A description of the problem and the workaround can be found at DataSnap OpenSSL Access Violation on finalization.

According to Marco Cantù, the workaround is quite simply to ensure that the "Indy abstraction unit be the first unit in the uses clause (IPPeerClient on the client side, IPPeerServer on the server side) of their [sic] project." This is a pretty sloppy specification. Just what is the "first unit in the uses clause... of the project?"

Jani Järvinen gives us a more comprehensive explanation at his blog Understanding Delphi Unit initialization order. Here's a quick overview of what you must do to ensure that the Indy abstraction units appear as the first units of a project:
  1. Examine the project file source code. (Right click the project name in the Project Manager and choose View Source.)
  2. Identify the first unit in the Uses clause. For a form-based server this is typically "Server Form in 'ServerForm.pas'." The client is typically simpler and the first unit will be the client form itself. Note: Ignore the VCL units that are included by the New Project Wizards. There is no need to change Delphi's library code. Only change the code you are responsible for maintaining.
  3. Open the identified unit and insert or move the Indy Abstraction unit so that it appears first in the Uses clause. 
This will cause a change in the initialization and finalization order and eliminate the access violation.

Note that the access violation will also probably cause a memory leak to be reported if you have memory leak reporting enabled. This is because the access violation causes some of the code to be bypassed that frees resources. The memory leak should disappear once the access violation is eliminated.