DBX Parameter Caching

From RAD Studio
Jump to: navigation, search

Go Up to DataSnap REST


DBX parameter caching in REST sessions allows the execution of a server method with multiple output or return parameters, without needing to return the complex type results such as Tables, Objects, and so on formatted as JSON. To make this possible, the caching of complex types on the server is introduced. Further, the client is provided with a URL (Uniform Resource Locator) to access each of the return types, individually.

Further Details

Take as an example this method on the server:

function GetImage(Name: String; out Stream: TStream): TStream;

Note that the GetImage function returns two streams. Before the introduction of parameter caching, the only option for executing this server method was through a URL of this type: http://host:port/datasnap/rest/Classame/GetImage/Name.

This URL executes the function correctly, but both streams would be returned as JSON Arrays of bytes. When only a single stream is being returned, you would be able to control the output format with the json URL parameter (true/false). However, this is ignored if there are multiple results being returned, to avoid data loss.

Now you are able to execute that same function (for example, GetImage) using the URL given above, passing in application/rest as the Accept header value of the request. In this way, the server knows that you want to use the current session's cache to handle complex parameters. This is how data loss problems are solved, but the user is required to hit the server once for the method call, and one additional time for each complex parameter he wants to read.

An Example

The following code is an example that would execute the GetImage sample function. It is assumed that both streams are images. The example populates a web page, containing two images, with the cached images.


 function PopulateImages()
 {
   var exec=new ServerFunctionExecutor("ClassName");
   var resultObj=exec.executeMethod("GetImage", null, "GET", ["Key"], null, true, null, "application/rest");
   // returns: {"result":["0/0/0", "0/0/1"],"cacheId":0,"cmdIndex":0}
   document.getElementById("image1").src=exec.getCacheURL(resultObj.result[0],true);
   document.getElementById("image2").src=exec.getCacheURL(resultObj.result[1],true);
 }


The code presented above makes several assumptions about the web page it is loaded with, but should illustrate the basic idea. There are two major changes to the ServerFunctionExecutor that can be seen. First, the executeMethod function takes an optional parameter at the end, which will be the value used in the Accept header of the request. Secondly, a new function called getCacheURL has been added, which returns the full URL to the cached object, based on the partial URL provided in the execution result. The true passed in as the second parameter instructs to add the session ID to the returned URL, so that the URL can work as stand-alone, without the ServerFunctionExecutor.

Result Format

As mentioned above, when specifying application/rest as the Accept type, the result you get back will be slightly different. The main difference is that for each of the complex data types such as Table, Object, Stream, and so on the result you get back is a URL fragment instead of the actual value. The fragment can be understood as follows:

[Cache Item ID]/[Command Index]/[Parameter Index]

where Cache Item ID is the unique identifier for the method invocation you executed. However, note that only executions that store results in the cache get unique identifiers. Command Index identifies the command of the execution to which the result refers to. It is a nonzero value only if you ran a batch execution involving multiple server methods at once. Parameter Index is the index of the complex parameter to return. This is zero-based, and is based only on the command's complex parameters, excluding the others.

Aside from this difference, you will also notice that the result object has two new properties, CacheId and CmdIndex. These properties are the same values as the first two parts of the URL fragment mentioned above, and exist only so their values can be retrieved without parsing the URL fragment.

Interacting with the Cache

Cache URLs support GET and DELETE request types.

When issuing a GET command, the following URLs are available:

URL Meaning

http://host:port/datasnap/cache

Returns a JSON object describing the contents of the cache.

http://host:port/datasnap/cache/[CacheID]

Returns a JSON object describing the cache object with the given ID.

http://host:port/datasnap/cache/[CacheID]/[CmdIndex]/

Returns a JSON representation of the given command.

http://host:port/datasnap/cache/[CacheId]/[CmdIndex]/[ParameterIndex]

Returns the actual parameter, as JSON or stream.


When issuing a DELETE command, the following URLs are supported:

URL Meaning

http://host:port/datasnap/cache

Deletes all cached items.

http://host:port/datasnap/cache/[CacheID]

Deletes the cached items and all of its commands and/or parameters.

Request Filters

When not using the cache, request filters work exactly how they used to. When you are using the cache, a GET request that specifies a specific parameter (for example, CacheId/CmdIndex/ParameterIndex) supports the same request filters. However, there are a few things to note when using them:

  • The initial call to the server method will ignore any request filters on complex types. The filters for these parameters will not be applied on the complex types and will not be remembered for later use when retrieving the parameters from the cache.
  • When using request filters on a cached Stream, you must add the parameter json=false. Otherwise, the filters will be ignored and the stream will be returned directly as the content stream of the response.
  • The parameter index for the filter is the original parameter index, not the index of the complex parameter in the cache. In other words, the index is the same as what you would have specified if you used the filter in the original method invocation.

JS Proxy Changes

The generated JS proxy functions now support an additional optional parameter after callback and filter that does not appear in the function signature. This parameter is treated as a string, and is used directly as the value of Accept in the request header.

See Also