Delphi Labs: DataSnap XE - WebBroker jQueryMobile Boilerplate

By: Pawel Glowacki

Abstract: In this tutorial we are using Delphi XE WebBroker framework for building a standalone web application that is returning to a web browser the jQueryMobile boilerplate.

    A Little Disclaimer

In “Delphi Labs” I’m focusing on Delphi development, but all of the applications described here, could be also built using C++Builder, which is a part of RAD Studio.

Delphi and C++Builder are deeply integrated. Both are different “personalities” of the same underlying Integrated Development Environment (IDE) and they share the Visual Component Library (VCL).

It is just my personal preference to use Delphi Pascal programming language. If you are more comfortable with C++ you should definitely give the C++Builder XE (http://www.embarcadero.com/products/cbuilder) a try!

    Introduction

In this lab exercise we are going to use Delphi XE to build a web application for displaying database data coming from a DataSnap server using jQuery Mobile JavaScript library.

Coding in pure JavaScript can be very tedious and there are plenty of frameworks and libraries to make this task easier. One of the most popular JavaScript libraries is jQuery (http://jquery.com/), which is “a fast and concise” and “simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development”.

One of the most recent projects within the world of jQuery is a “mobile” version of this popular library that is optimized for web browsers available on smartphones, like iPhone, Android and others. It is a layer on top of the jQuery core that is using the latest web standards, like HTML5 and CSS3, for building web pages that have this “mobile” look-and-feel.

At the time of this writing the jQuery Mobile is still in its alpha phase of development, so the functionality available today (March 2011), may differ from the final release.

In this article I am using jQuery Mobile Alpha 3 release available at http://jquerymobile.com/demos/1.0a3/.

The end-result of this two part tutorial is a sample, multitier, scalable DataSnap system consisting of a Delphi XE DataSnap standalone data server providing data from the underlying InterBase XE sample “Employees” database and a client - a WebBroker Delphi XE standalone web application that will use jQuery Mobile for displaying data.

Hide image
Click to see full-sized image

expand view>>

    Understanding WebBroker

There are different types of applications you can build with Delphi. For many developers Delphi is all about building rich Windows clients with fast and sophisticated user interfaces. One of the best examples of such a powerful application written in Delphi could be popular “Skype” communicator. Not so many programmers are aware that you can also build web applications in Delphi. The VCL framework for building web applications in Delphi and C++Builder is called WebBroker.

In addition to building web application as DLLs – that can be deployed to a web server, like IIS – Delphi XE introduced a brand new type of a standalone web application that is a self-contained Windows executable that is both: a web server and a web application. This is informally called “Indy WebBroker” as the web server is implemented using Delphi “Indy” components.

Delphi provides a number of wizards for building different kinds of web applications. The most basic web application can be created using “Web Server Application” wizard. There are also other, more specialized wizards that – in the words of Nick Hodges, former Delphi Product Manager – provide “improved start from scratchability”. For example you can use Delphi “SOAP Server Application” wizard to create a traditional SOAP Web Service or you can use “DataSnap REST Application” wizard to create a web-based DataSnap server with integrated JavaScript client. Technically you could start from an empty WebBroker “Web Server Application” and add all necessary components and code to make it either SOAP or a REST web application. It is just so much more convenient to use a dedicated wizard. At the end that’s the whole idea of “a wizard” – to simplify things!

Select “File -> New -> Other” and from the “New Items” dialog double-click on the “Web Server Application” icon in the “Delphi Projects -> WebBroker” category.

Hide image
New WebBroker app

Select “Indy VCL Application” in the dialog for a type of a web server application and click “OK”.

Hide image
NewWebServerApp_IndyVCLApp

This will create an empty “Indy WebBroker” web application.

Save All. I have created the following new directory for my project file “C:\DataSnapLabs\WebBroker_jQueryMobileBoilerplate”. Let’s call the first unit “FormMainUnit”, the second “WebModuleMainUnit” and the whole project “WebBrokerjQueryMobileBoilerplate”.

This is how my Project Manager looks right now:

Hide image
ProjectMgrForJQueryMobileBoilerplate

The “FormMainUnit” contains the main form class of the application which contains new in Delphi XE Indy web server implementation. The “WebModuleMainUnit” contains the implementation of a “web module class”. WebBroker web module class acts very similarly as DataSnap server methods class. They are not instantiated be a programmer and their lifetime is controlled be the framework.

Select “Project – Options” to display project options dialog for our project options and select “Forms” category in the dialog.

Hide image
Click to see full-sized image

The only auto-created form in our application is “FormMain” and “WebModuleMain” has to be created in code.

expand view>>

Having a look into the source of whole Delphi project explains how this web app implementation lifetime management works.

Select “Project – View Source” and you should see something like this:

program WebBrokerjQueryMobileBoilerplate;

{$APPTYPE GUI}

uses
  Forms,
  WebReq,
  IdHTTPWebBrokerBridge,
  FormMainUnit in 'FormMainUnit.pas' {FormMain},
  WebModuleMainUnit in 'WebModuleMainUnit.pas' {WebModuleMain: TWebModule};

{$R *.res}

begin
  if WebRequestHandler <> nil then
    WebRequestHandler.WebModuleClass := WebModuleClass;
  Application.Initialize;
  Application.CreateForm(TFormMain, FormMain);
  Application.Run;
end.

There is a global anonymous function variable that stores the reference of the web module class used in this particular application. In case of DataSnap we have the possibility to have multiple server classes with different lifetime options available. The WebBroker architecture is simpler as you can have only one web module class type and there is a default lifetime management option.

Keep pressing the “Ctrl” button and hover over the “WebRequestHandler” identifier in the editor and you will be able to transform it for a moment into hyperlink to the actual place in code where it is defined.

“WebRequestHandler” global variable is defined as a reference to an anonymous method that returns a web handler class instance that has a property of type “TWebModuleClass”. This setup effectively implements a class factory design pattern. The application logic of our web app is completely implemented inside the Web Module class.

The web module class is indirectly derived from “TDataModule”, so it can be used as a container for non-visual components for http content generation and data access. Every web module has “Actions” published property, which is a collection of “TWebActionItem” components.

Hide image
Click to see full-sized image

The “Web Server Application” wizard has added for us one, default web action called “DefaultHandler” and implementation of its “OnAction” event.

expand view>>

If you click on “ellipsis” button for the “Actions” property you will display collection editor for this property where you can easily add more web actions.

Hide image
Click to see full-sized image

The wizard has also generated the event handler for the “OnAction” event that returns a chunk of HTML code that displays “Web Server Application” text. This is where the programmer can implement what is returned to the web client. This event has three parameters: “Request: TWebRequest”, “Response: TWebResponse” and “Handled: boolean”. The “Request” parameter contains all information about the HTTP request being processed. The second parameter is the “Response” object that encapsulates all data that are going to be sent back from web server app to the client. The “Handled” boolean parameter indicates if the request was completely processed. In a more generic scenario one http request can be processed by multiple WebActionItems.

expand view>>

It is the programmer task to set “Response” object properties. The wizard generated code to assign to “Response.Content” property. The default content type is “text/html”, but you can also return other types of data like for example images, but then you have to set proper MIME “ContentType”.

For every “TWebActionItem” in the “Actions” collection we can set what is the HTTP method type of the HTTP request and what is the “PathInfo” from the URL sent from the HTTP client.

Instead of implementing the “OnAction” event it is also possible to use “Producer” component to provide content to the “WebActionItem” object.

Let’s change the default implementation of our “OnAction” event to return some dynamic content.

Below is the entire content of the “WebModuleMainUnit”.

unit WebModuleMainUnit;

interface

uses
  SysUtils, Classes, HTTPApp;

type
  TWebModuleMain = class(TWebModule)
    procedure WebModuleMainDefaultHandlerAction(Sender: TObject;
      Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  WebModuleClass: TComponentClass = TWebModuleMain;

implementation

{$R *.dfm}

procedure TWebModuleMain.WebModuleMainDefaultHandlerAction(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
  Response.Content :=
    '<p>"Hello World" from <b>Delphi Labs</b> Delphi WebBroker test app!</p>'
  + '<p>The time at our server is <b>' + DateTimeToStr(Now) + '</b> right now.</p>'
  + '<p>HTTP response content type is: <b>' + Response.ContentType + '</b></p>';
end;

end.

If you run our Delphi WebBroker application now, you should see a similar output:

Hide image
TestWebApp_output

    WebBroker jQueryMobile Boilerplate

If you try to find in Internet examples of jQueryMobile, you will very frequently encounter something called a “boilerplate”. At this URL: http://jquerymobile.com/demos/1.0a3/#docs/pages/page-template.html you can preview the actual boilerplate html page for jQuery Mobile. This is a simple starting point for building more sophisticated jQuery Mobile web pages with all necessary references to style sheets and scripts.

Let’s modify our simple Delphi WebBroker application so it returns a jQueryMobile boilerplate page.

First let’s remove the “TWebModuleMain.WebModuleMainDefaultHandlerAction” event handler. The easiest way is to remove the body of the event and click on “Save”. This is will completely remove the event handler.

Press F12 to toggle between code editor and the form designer of the web module. Drop onto the web module a “TPageProducer” component.

Select “DefaultHandler” web action item and set its “Producer” property to point to the “PageProducer1” component that was just added to web module.

Select “PageProducer1” component and open its “HTMLDoc” property in the Object Inspector.

Copy and paste into the following jQuery Mobile boilerplate template:

<!DOCTYPE html> 
<html> 
<head> 
<title>Page Title</title> 
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.min.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.3.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.min.js"></script>
</head> 
<body> 

<div data-role="page">

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

     <div data-role="content">    
          <p>Page content goes here.</p>          
     </div><!-- /content -->

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

</body>
</html>

If you run the application now, and open the browser, you should see the following page.

This will not work in older browsers. I am using Chrome.

Hide image
Boilerplate

The HTML code has been completely hardcoded inside our application. The alternative to using “HTMLDoc” property would be to use “HTMLFile”. I prefer to use “HTMLDoc” here as the contents of the final application will be generated dynamically, so it does not really matter.

The jQueryMobile make it possible to define multiple “pages” inside one html document. This is what I am planning to use. jQueryMobile uses “data-*” attributes for decorating different html tags. In order to host multiple mobile “pages” you just need to use multiple “div-s” with “data-role=page” attribute. The first one in considered the main page.

The “TPageProducer” component provides “OnHTMLTag” event that can be used to provide dynamic HTML content.

For every special tag marked with the “#” symbol, the “OnHTMLTag” event is fired by the page producer component, so it is possible to programmatically provide correct values.

A good reference how it works is by inspecting the “ReverseString.html” file and its corresponding PageProducer is a project generated by the “DataSnap REST Application” wizard.

I’m going to use two custom tags: one for the html document title (“#doctitle”) and one for the whole body of the jQueryMobile boilerplate template (“#docbody”).

Select “PageProducer1” component again and open its “HTMLDoc” property in the Object Inspector.

“Select All” in the editor and replace with the following code containing transparent tags:

<!DOCTYPE html> 
<html> 
<head> 
<title><#doctitle></title> 
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.min.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.3.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.min.js"></script>
</head> 
<body> 
<#docbody>
</body>
</html>

Select “TPageProducer” component. In the Object Inspector double-click the “OnHTMLTag” event to generate an empty event handler for this event and enter the following code generating jQueryMobile boilerplate dynamically.

procedure TWebModuleMain.PageProducer1HTMLTag(Sender: TObject; Tag: TTag;
  const TagString: string; TagParams: TStrings; var ReplaceText: string);
begin
  if SameText(TagString, 'doctitle') then
    ReplaceText := 'Page Title’

  else if SameText(TagString, 'docbody') then
    ReplaceText :=

 '<div data-role="page">'

+'  <div data-role="header">'
+'       <h1>Page Title</h1>'
+'  </div><!-- /header -->'

+'  <div data-role="content">'
+'       <p>Page content goes here.</p>'
+'  </div><!-- /content -->'

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

+'</div><!-- /page -->'

  else
    ReplaceText := '';
end;

If you rerun the web application you should see that it still displays the same jQueryMobile boilerplate page.

    Refactoring dynamic page creation

Currently all the markup is generated dynamically inside the “OnHTMLTag” event, where we provide replacement markup for “#DocTitle” and “#DocBody” WebBroker transparent tags.

The code to generate the actual body of our web document can be very complex, so what about extracting this functionality to a separate data module? We can create and destroy this data module on the fly and it only needs to have a public method that would return a Delphi string with the dynamic body of our HTML doc and one to return a document title.

Select “File – New – Other” and in the “New Items” dialog select “Delphi Projects – Delphi Files” category and double-click on the “Data Module” icon.

Hide image
NewDataModule

Save the new unit as “DataModuleHtmlUnit” and change the data module name in the Object Inspector to “DataModuleHtml”.

We are going to create and destroy this data module class at runtime just for the duration of the process of generating the dynamic html content for our dynamic page.

Go to “Project Options” and remove the data module just added to the project from the list of auto-created forms as there is no need for the application to instantiate this data module. I like to comment out its global variable in the defining unit, so it is never accidentally used.

Hide image
Click to see full-sized image

Let’s implement on our data module class a public method called “GetHtmlBody” that would return a string for us to use inside the “OnHTMLTag” event handler.

expand view>>

Here is how the our web module implementation looks like right now changing the implementation of the “OnHTMLTag” event handler:

unit WebModuleUnit;

interface

uses
  SysUtils, Classes, HTTPApp, HTTPProd;

type
  TWebModuleMain = class(TWebModule)
    PageProducer1: TPageProducer;
    procedure PageProducer1HTMLTag(Sender: TObject; Tag: TTag;
      const TagString: string; TagParams: TStrings; var ReplaceText: string);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  WebModuleClass: TComponentClass = TWebModuleMain;

implementation

uses DataModuleHtmlUnit;

{$R *.dfm}

procedure TWebModuleMain.PageProducer1HTMLTag(Sender: TObject; Tag: TTag;
  const TagString: string; TagParams: TStrings; var ReplaceText: string);

var 
 dm: TDataModuleHtml;

begin
  dm := TDataModuleHtml.Create(nil);
  try

    if SameText(TagString, 'doctitle') then
      ReplaceText := dm.GetTitle

    else if SameText(TagString, 'docbody') then
      ReplaceText := dm.GetBody

    else
      ReplaceText := '';

  finally
    dm.Free;
  end;
end;

end.

And here is the implementation of the new data module class added to the client project.

unit DataModuleHtmlUnit;

interface

uses
  SysUtils, Classes;

type
  TDataModuleHtml = class(TDataModule)
  private
    { Private declarations }
  public
    function GetTitle: string;
    function GetBody: string;
  end;

//var
//  DataModuleHtml: TDataModuleHtml;

implementation

{$R *.dfm}

{ TDataModuleHtml }

function TDataModuleHtml.GetTitle: string;
begin
  Result := 'WebBroker jQueryMobile Boilerplate';
end;

function TDataModuleHtml.GetBody: string;
begin
  Result :=

 '<div data-role="page">'

+'  <div data-role="header">'
+'       <h1>Page Title</h1>'
+'  </div><!-- /header -->'

+'  <div data-role="content">'
+'       <p>Page content goes here.</p>'
+'  </div><!-- /content -->'

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

+'</div><!-- /page -->'

end;

end.

If you run the web application now, it should still display the same JQueryMobile boilerplate page as before.

The whole idea of refactoring is to modify the underlying structure of code without changing its behavior. Now we are ready to handle the actual complexity of implementing the “GetBody” based on data coming from the DataSnap server.

    Summary

In this DelphiLabs DataSnap tutorial we are looking into practical steps of building a multitier, scalable system for displaying database data on mobile devices.

In the first part we have discussed Delphi WebBroker framework for building web applications and we have also used Delphi to build a WebBroker jQueryMobile Boilerplate page.

After refactoring code responsible for dynamic HTML markup generation we are now ready for the second part of this tutorial where we are going to build a DataSnap server returning customer data from a sample InterBase database, that we are going to use to dynamically build jQueryMobile web frontend.

Note that we are using a pre-release version of jQueryMobile library, so the final functionality may differ from what has been described here.

DataSnap is a feature of Delphi, C++Builder and RAD Studio Enterprise and Architect editions. It is not available in Starter and Professional editions.

    References

Server Response from: ETNASC02