Delphi XE2 Boilerplate DataSnap Server and jQueryMobile Client

By: Pawel Glowacki

Abstract: In this article we are going to build a "hello world" client/server system consisting of Delphi XE2 DataSnap REST Application server and jQueryMobile web client

    Introduction

In this article we are going to build a sample system consisting of a Delphi DataSnap REST server application and jQuery Mobile web client.

We are going to use Delphi XE2 and jQueryMobile 1.0.1, which is the latest versions available at the time of writing this article (January 2012).

    Architecture

Embarcadero DataSnap is an enterprise framework; very much like JEE, CORBA, SOAP and similar client/server, distributes, multitier architectures. DataSnap is a feature of enterprise and higher versions of Embarcadero Delphi, C++Builder and RAD Studio. With DataSnap it is possible to build scalable, fault-tolerant, multitier systems with native, compiled server application and wide variety of native, managed and web clients communicating with server using different communication protocols.

In this particular example we are going to focus on a server application implemented as native Delphi XE2 Windows standalone web server REST application and web browser-based client running inside of the HTML web page using popular jQueryMobile JavaScript library which makes it easy to create interactive web pages optimized for web browser running on smartphones.

    Building Delphi REST server web application with the wizard

Delphi XE2 provides special “DataSnap REST Application” wizard that generates a boilerplate project consisting of the following parts:

  • Server: native Delphi Windows DataSnap REST web server application
  • Client: JavaScript code embedded in HTML pages

Start Delphi XE2. Click on the “File/New/Other…” menu item. Inside the “New Items” dialog go to “Delphi Projects/DataSnap Server” category and “DataSnap REST Application” icon. Click on OK.

Hide image
Fig_NewItems_NewDelphiXE2_DataSnapRESTApp_Icon

In the first step of the “New DataSnap REST Application” wizard we need to decide how our web application must be implemented: as a standalone VCL/Console-based web server application that is a self-contained Windows executable containings both a web server and a web application, or as a DLL to be deployed to an ISAPI combatible web server. We are going to go for the first, default option which is a standalone WebBroker application.

Hide image
Click to see full-sized image

In the second step of the wizard we need to decide which HTTP port number we want to use and if we want to support the HTTPS. We are going to leave the default port “8080” and leave “HTTPS” option unchecked. It is always a good idea to click on a “Test Port” button to verify that it is not already in use on your machine. Click “OK” and “Next”.

expand view>>

Hide image
Click to see full-sized image

The third screen of the wizard is for choosing server features. Keep the features selected by default and also select “Server Module” feature.

expand view>>

Hide image
Click to see full-sized image

On the following wizard screen we can choose the base class for our server methods class. If you keep the default option of inheriting directly from “TComponent” you cannot really use the non-visual components like data base connections, queries or datasets.

expand view>>

Select “TDSServerModule” to inherit also the implementation of IAppServer interface on the server for DataSnap TClientDataSet-based clients.

Hide image
Click to see full-sized image

The last screen is the projection location. The last part of the name will be used as both a new folder and also the actual project name.

expand view>>

You can put this project anywhere. Enter “C:\Demos\DelphiJQueryMobileApp1” and click finish button.

Hide image
Click to see full-sized image

Select “Save All” and keep all default names for different units in the project.

expand view>>

Run the project now. It will first display the main form of the VCL Forms application that acts as a standalone web server and listens on a specified port.

Hide image
Fig_VCLWebServer_Form

Click on “Open Browser” button to start the web application and open it in the default web browser. I’m using Chrome, but it might be a different default web browser, like Internet Explorer or Firefox.

Hide image
Click to see full-sized image

We have selected “Authentication” and “Authorization” options in the wizard. This is the reason that we are presented with username and password text boxes. Currently there is no username or password check implemented, so we can just press on the “LOG IN” button to hide login controls and display “Reverse String” text box and button.

expand view>>

Hide image
Click to see full-sized image

Click on the button and notice that the contents of the edit box has been reversed and that the “page loaded at” information does not change.

expand view>>

Hide image
Click to see full-sized image

Pressing on the “ReverseString” button makes the JavaScript code embedded in the “ReverseString.html” code to invoke the “ReverseString” method implemented in Delphi code in the “TServerMethods1.ReverseString” method. The web page is not reloaded because the call to the server method has been made asynchronously using AJAX.

expand view>>

We can verify that clicking on the button in the web browser calls server side functionality implemented in native Delphi code by placing a breakpoint inside the “ReverseString” method and re-running the web application with debugging.

Close the web browser and close the web server application.

Open “ServerMethodsUnit1” unit and click in the gutter just in the line 30, where the reverse string functionality is implemented.

Now press F9 or just click on the green arrow “run” button with a little red-black bug on it to run the application with debugging.

Open the browser window and click on the “LOG IN” button. When you click on “Reverse String” button you should see that your breakpoint stopped the execution of the program. Click on “Run” button again to resume the program.

The ability to debug our server-side Delphi logic is very powerful. You can implement your application server and data access logic in powerful Delphi code and you can use HTML5, CSS3 and jQuery to implement the client side user interface and server access logic.

Hide image
Click to see full-sized image

The “REST Web Application” wizard has created for us a complete system made of the HTML and JavaScript client and Delphi server.

expand view>>

Writing Delphi code is easy and full of fun. Writing a client in JavaScript is more involving and more error prone. This is why we are going to focus on improving the client side of our system.

In order to simplify our web client JavaScript code we are going to use the “jQuery” – one of the most popular libraries for JavaScript programming. On top of the jQuery library we are also going to use “jQuery Mobile” library that is making sure that our web pages are optimized for all major web browsers running on contemporary smartphones.

There are two ways to reference jQuery in our web application. We can put a reference to jQuery sources hosted in the cloud by many vendors including Google, or we can physically add jQuery JavaScript source files to our project. For performance reasons you might want to use the first option, but for demontration reasons it could be a good idea to add referenced files physically to be able to use them while offline.

You can download the jQueryMobile from http://jquerymobile.com/. At the time of this writing the latest version of jQueryMobile is 1.0.1.

The next step is to start using jQuery in our JavaScript client code. With jQuery the JavaScript source code can be more compact and readable.

The goal of this article is to create a standard, boliler-plate “Delphi REST Application” with a simple jQueryMobile-enabled web client.

To keep this article simple, I’m not going to modify the server implementation, and will provide a very simple jQueryMobile web page that is going to use the server side functionality – our “Echo” and “ReverseString” test methods generated by the wizard.

    Understanding “ReverseString” web page code

Before doing any changes to the web application that was generated by the wizard, let’s have a look how the client side logic is currently implemented.

Our web page consists primarily of HTML markup and some JavaScript code. Before we can fully understand this code, we need to pay special attention to identifiers in code with the “#” prefix. These are so called “transparent tags” and are replaced with a dynamically generated content inside the “TWebModule1.ServerFunctionInvokerHTMLTag” event that is fired for every transparent tag encountered during the preprocessing of the web page.

If we check the implementation of this method inside the “WebModuleUni1” file, we can see for example that “serverfunctionjs” transparent tag is replaced in code with “js/serverfunctions.js”. There are also other tags that are being replaced.

Let’s first have a look at the JavaScript code that is executed when the “Reverse String” button is pressed.

With the authorization and authentication code stripped out for readability, this JavaScript code looks like this.

function onReverseStringClick()
{
  var valueField = document.getElementById('valueField');
  var s = serverMethods().ReverseString(valueField.value);
  valueField.value = s.result;
}

In the first line of code we assign the contents of the input element with a class “valueField” attached to it. The contents of this input control will be sent to the server side method as a parameter to “ReverseString” server method call.

The second line of code is where the actual call to the Delphi server-side code is made. The “serverMethods()” is a utility function that is defined in the same script as the following and it returns - configured with connection information – a client-side JavaScript object that implements the same functions as the server-side class.

function serverMethods()
{
  return new <#classname>(connectionInfo);
}

The transparent tag “classname” is resolved before this call happens with the actual name of a server methods class using a call to “ServerMethodsUnit1.TServerMethods1.ClassName”, which is in our case “TServerMethods1” string.

The JavaScript definition of this class is located in the “ServerFunctions.js” source file, which is generated automatically with the DataSnap proxy generator from a running Delphi DataSnap server in the “TWebModule1.WebFileDispatcher1BeforeDispatch” event handler.

The automatically generated JavaScript unit contains references to a couple of “Delphi DataSnap Framework“ JavaScript library files that needs to be deployed with the JavaScript client code.

This class looks like this. I have stripped out calls to “EchoString” for readability.

function TServerMethods1(connectionInfo)
{
  this.executor = new ServerFunctionExecutor("TServerMethods1",connectionInfo);
  /*
   * @param Value [in] - Type on server: string
   * @return result - Type on server: string
   */
  this.ReverseString = function(Value) {
    var returnObject = this.executor.executeMethod("ReverseString", "GET", [Value], arguments[1], true, arguments[2], arguments[3]);
    if (arguments[1] == null) {
      if (returnObject != null && returnObject.result != null && isArray(returnObject.result)) {
        var resultArray = returnObject.result;
        var resultObject = new Object();
        resultObject.Value = Value;
        resultObject.result = resultArray[0];
        return resultObject;
      }
      return returnObject;
    }
  };

  this.ReverseString_URL = function(Value) {
    return this.executor.getMethodURL("ReverseString", "GET", [Value], arguments[1])[0];
  };
} 

The “TServerMethods1” class acts as a proxy to the remaining JavaScript code and hides the actual implementation of the HTTP GET call to a remote DataSnap server application that knows how to talk HTTP.

The actual implementation of the “ServerFunctionExecutor” is not the most important now. It comes with the “Delphi DataSnap Framework” JavaScript library files and is implemented in “ServerFunctionExecutor.js” source file.

It is important to notice that the “TServerMethods1” constructor expects as a parameter a “connectionInfo” object that is later passed to “ServerFunctionExecutor” constructor.

The “connectionInfo” variable is defined in the “connection.js” source file and it is initialized in the web page “onLoad()” event with the call to “setConnection” method.

// “ReverseString.html”

function onLoad()
{
  // …
  setConnection('<#host>', '<#port>', '<#urlpath>');
  // …
}

The “setConnection” function is a simple utility function defined like this in the “connection.js” file

 
// “connection.js”

var connectionInfo;

function setConnection(host, port, urlPath)
{
  connectionInfo = {"host":host,"port":port,"authentication":null,"pathPrefix":urlPath};
}

Transparent tags “host”, “port” and “urlpath” are replaced before this html page is dispatched with the actual server-side values from in the Delphi server code from the “Request” object that encapsulates current HTTP request.

procedure TWebModule1.ServerFunctionInvokerHTMLTag(Sender: TObject; Tag: TTag;
  const TagString: string; TagParams: TStrings; var ReplaceText: string);
begin
  if SameText(TagString, 'urlpath') then
    ReplaceText := string(Request.InternalScriptName)
  else if SameText(TagString, 'port') then
    ReplaceText := IntToStr(Request.ServerPort)
  else if SameText(TagString, 'host') then
    ReplaceText := string(Request.Host) 

// …

Summarizing, in order to call server-side function implemented in Delphi code from our JavaScript we need to call “serverMethods” function that returns properly initialized “TServerMethods1” instance that can be used to call the server side functionality.

Let’s move back to the “onReverseStringClick” event hander code. With jQuery there is no need to use built-in JavaScript function “document.getElementById”, we can simplify the code by using jQuery “$” reference.

jQuery also helps to make a cleaner separation between the HTML markup that defines how the web page looks from the JavaScript code that controls what the web page does.

Currently the body of our web page looks like this:

<body onload="onLoad()">
 // … 
    <div id="contentdiv" class="contentdiv" style="display:none">
      <table>
        <tr>
          <td><input id="valueField" class="loginField" type="text" value="A B C" /></td>
          <td><button onclick='javascript:onReverseStringClick();'>ReverseString</button></td>
        </tr>
      </table>
    </div>
</body>
</html>

Notice that the “button” tag has a “onReverseStringClick()” event handler assigned to its “onclick” event.

The jQuery library uses the “$(document).ready” event handler for centralizing all the event handling code, we can remove the code that assigns JavaScript code to button’s “onclick” event and move it to he “ready” function, so the resulting code is cleaner. In order to be able to reference the button tag in code, we need to add an identifier to it. For example “btn_Reverse”.

<body onload="onLoad()">
 // … 
    <div id="contentdiv" class="contentdiv" style="display:none">
      <table>
        <tr>
          <td><input id="valueField" class="loginField" type="text" value="A B C" /></td>
          <td><button id="btn_Reverse">ReverseString</button></td>
        </tr>
      </table>
    </div>
</body>
</html>

Now that we understand what’s going on in this code, we can start with implementing our own, jQueryMobile-enabled, version of this page.

    Adding a boilerplate jQueryMobile page to our application

The jQueryMobile documentation comes with an example of a “boilerplate” page that represents a “hello world” starting point for any other, more complex page.

The contents of this page - as of version 1.0.1 - is the following:

<!DOCTYPE html> 
<html> 
    <head> 
    <title>My Page</title> 
    <meta name="viewport" content="width=device-width, initial-scale=1"> 
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" />
    <script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
    <script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.js"></script>
</head> 
<body> 

<div data-role="page">

    <div data-role="header">
         <h1>My Title</h1>
    </div><!-- /header -->

    <div data-role="content">    
         <p>Hello world</p>          
    </div><!-- /content -->

</div><!-- /page -->

</body>
</html>

In this step I’m going to add to the main web module of our Delphi REST application an additional “TPageProducer” component that is going to be responsible for generating the contents of a jQueryMobile boilerplate code.

Open “WebModuleUnit1” unit and drop a new instance of “TPageProducer” component to the main web module of our application. Rename it to “ppBoilerplate”.

Open the “HTMLDoc” property of the “ppBoilerplate” component and paste the HTML boilerplate markup into the editor. Click OK.

Hide image
Click to see full-sized image

expand view>>

This is the alternative way of providing the page markup. You can either use “HTMLFile” property to point to a physical HTML file, like the two other producer components, or directly enter the markup into the HTMLDoc property, so it is stored inside the DFM file and there is no need for an actual HTML file. This two properties are mutually exclusive, so setting one, automatically clears the other.

If we run the application now, we can see that it still displays the “ReverseString” page and not the contents from our new page producer.

We need to change the default page producer for our application, so the our jQueryMobile boilerplate markup is served to a browser.

In order to do this we need to change the implementation of the web module default action handler.

Click somewhere on the surface of the “WebModule1” to make sure that it is selected in the Object Inspector.

Hide image
WebActionItems prop of WebModule1

Select the “DefaultAction” item from the list of actions. Click on “Events” tab in the Object Inspector. When you click on the “OnAction” event you will see the following code in the editor:

procedure TWebModule1.WebModuleDefaultAction(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
  if (Request.InternalPathInfo = '') or (Request.InternalPathInfo = '/')then
    Response.Content := ReverseString.Content
  else
    Response.SendRedirect(Request.InternalScriptName + '/');
end;

We can see from this code that for every HTTP request arriving to our Delphi web application, the contents of the “ReverseString” page producer component is assigned to the “Content” property of the “Response” object that encapsulates the HTTP response that is eventually going to be sent to the web browser.

Let’s just replace “ReverseString” with the name of our page producer “ppBoilerplate”.

procedure TWebModule1.WebModuleDefaultAction(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
  if (Request.InternalPathInfo = '') or (Request.InternalPathInfo = '/')then
    Response.Content := ppBoilerplate.Content
  else
    Response.SendRedirect(Request.InternalScriptName + '/');
end;

Click on “Save All” and run the web application.

Now we should see the jQueryMobile 1.0.1 boilerplate page in the web browser.

Hide image
Click to see full-sized image

The next step is to add interactions between the jQuery code in the web page and our Delphi server methods.

expand view>>

    Calling DataSnap server methods from jQueryMobile code

Now we are going to enhance our boilerplate jQueryMobile web page and add to it a possibility to call server-side functions implemented in Delphi code.

That would only require modifying the value of the “HTMLDoc” property. You can conventiently open this property in the code editor clicking on the “Code Editor…” button in the bottom left corner of the string list editor.

Just replace the contents of the “HTMLDoc” property with the following code:

<!DOCTYPE html>
<html>
<head>
<title>Delphi DataSnap jQueryMobile Template</title>

<meta name="viewport" content="width=device-width, initial-scale=1">

<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" />
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.js"></script>
<script type="text/javascript" src="js/base64.js"></script>
<script type="text/javascript" src="js/json2.js"></script>
<script type="text/javascript" src="js/serverfunctionexecutor.js"></script>
<script type="text/javascript" src="js/connection.js"></script>
<script type="text/javascript" src="js/serverfunctions.js"></script>

<script type="text/javascript">

function serverMethods()
{
  return new TServerMethods1(connectionInfo);
}

$(document).ready(function() {

    $('#btn_reverse').click (function (){
      var value = $('#valueField').val();
      var value = serverMethods().ReverseString(value).result;
      $('#valueField').val(value);
    });

    $('#btn_echo').click (function (){
      var value = $('#echoField').val();
      var value = serverMethods().EchoString(value).result;
      $('#echoField').val(value);
    });

});

</script>
</head>

<body>

<div data-role="page" id="main_page" data-theme="a">

  <div data-role="header">
    <h1>Delphi and jQueryMobile</h1>
  </div><!-- /header -->

  <div data-role="content">
    <p>Click "Reverse" button to invoke Delphi REST server method to reverse the content of the edit box</p>
    <input id="valueField" type="text" value="A B C" />
    <a href="#" data-role="button" id="btn_reverse">Reverse</a>
    <p>View the second <a href="#second_page">page</a></p>
  </div><!-- /content -->

  <div data-role="footer">
    <h4>Page Footer</h4>
  </div><!-- /footer -->

</div><!-- /page -->

<!-- Start of second page -->
<div data-role="page" id="second_page">

  <div data-role="header">
    <h1>This is the second page</h1>
  </div><!-- /header -->

  <div data-role="content">
    <p>I'm the second in the source order so I'm hidden when the page loads. I'm just shown if a link that references my ID is beeing clicked.</p>
    <p>Click button</p>
    <input id="echoField" type="text" value="Hi" />
    <a href="#" data-role="button" id="btn_echo">Echo</a>
    <p><a href="#main_page">Back to main page</a></p>
  </div><!-- /content -->

  <div data-role="footer">
    <h4>Second Page Footer</h4>
  </div><!-- /footer -->

</div><!-- /page -->

</body>
</html>

Save all and run the application. Depending on your browser you should see a page that contains a “Reverse String” button. There is also a link that makes it possible to jump to the second page with “echoing” functionality.

Hide image
Click to see full-sized image Hide image
Click to see full-sized image

That’s it. The source code for this template application can be downloaded from Embarcadero Code Central.

expand view>>

expand view>>

You can optionally remove from this boilerplate applications all the unused code, but that’s something I’m leaving to the reader.

    Summary

In this article we have seen how to start building enterprise, multitier systems using Embarcadero Delphi XE2 and jQueryMobile.

RAD Studio XE2 includes many interesting and powerful features like 64-bit native Delphi compilation and the new FireMonkey framework for building great looking native application on multiple operating systems. The DataSnap framework is often overlooked by Delphi and C++Builder developers. The DataSnap architecture is the perfect choice for building server-side applications for any clients. Currently there are two main kinds of client applications that can work with DataSnap servers: native applications and web applications.

For native clients I would choose Delphi FireMonkey, for web clients I would go for the pure HTML5 solution. jQuery and jQueryMobile are great choices to simplify the process of writing web clients in JavaScript code.

    References

Server Response from: ETNASC03