[See the full index of articles for more information]

Table of Contents:

In this blog post, you’ll learn how to build your first RAD Server service-based applications using Delphi and C++Builder. Before you begin development, you’ll want to make sure that your InterBase database server is running. RAD Server uses an InterBase database for the storage of user information, user groups, analytics, registered devices, version information, registered Edge Modules, push notification messages and more.  


Figure 1: InterBase 2017 Server Manager

1. Using the RAD Server Project Wizard

The fastest way to get started is to use the New Projects menu (File | New | Other…) and choose the RAD Server | RAD Server Package wizard for Delphi or C++Builder.


Figure 2: RAD Server Project Wizard choices for Delphi and C++

Select the RAD Server Package project. A wizard will appear to help create the starting project. On the first page choose how the wizard will create the resources and endpoints that will appear in the RAD Server application. The RAD Server Package Wizard provides two choices to proceed.

Choice 1: Create an empty package that does not register a resource. Choose this option if you are going to add your resources later. Using this choice, a package project will be created with a starting main library.


Figure 3: Create an empty RAD Server package

Clicking the Finish button will create the starting project for additional development work to create the finished RAD Server application.

Choice 2: Create a package with a resource that extends the REST API of for the RAD Server. Click the Next Button and two additional wizard steps will appear to help create the package project, resource and endpoints. To build the first RAD Server project make this choice.


Figure 4: Create a resource based RAD Server package

On the wizard’s second page set the Resource name to “Test”. The File type radio buttons presents two options: 1) create a unit for implementing the resource in code, and 2) create a data module for implementing the resource using the IDE’s designer, components and code editor. For this first RAD Server application chose to use a Data Module.


Figure 5: RAD Server Package Wizard page 2 - set the resource name and file type

Click the Next button to create a starting set of endpoints.


Figure 6: RAD Server Package Wizard page 3 - choose starting EndPoints

On the wizard’s third page choose from a set of predefined EndPoints: Get (REST GET), GetItem (REST GET with a segment at the end of the URL that identifies the item to get) , Post (REST Post), PutItem (REST Put with a segment at the end of the URL that identifies the item to put), and DeleteItem (REST Delete with a segment at the end of the URL that identifies the item to delete). There is also a Select/deselect all check box at the bottom of the EndPoints list.

To create a package project with all of the EndPoints defined, click on all of the starting end points or choose Select All.

You can also step back through the wizard or click on the step links to make changes to the Package, Resource and Endpoints. To create your starting project is to click the Finish button.

After the wizard completes, you are placed back in the IDE. The first thing to do is to save the project. For the C++ and Delphi data module, use the name “MyDMUnit”. For the C++ project and package use the name “MyFirstCppRADServerPackage”. For the Delphi project and package use the name “MyFirstDelphiRADServerPackage”.

2. The Wizard Generated RAD Server Project and Source Code

Here are the projects and source code created by the wizard for Delphi and C++. For the C++ code I have added a couple of lines of code in the Get and GetItem endpoint implementations to set the response (look for the // sample code comment line in MyDMUnit.cpp).

Delphi:


Figure 7: Generated Delphi project
and Figure 8: Generated Delphi resource module

package MyFirstDelphiRADServerPackage;
{$R *.res}
{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO OFF}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION OFF}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES ON}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DEFINE DEBUG}
{$ENDIF IMPLICITBUILDING}
{$RUNONLY}
{$IMPLICITBUILD ON}
requires
  rtl,
  emsserverapi;
contains
  MyDMUnit in 'MyDMUnit.pas' {TestResource1: TDataModule};
end.

MyDMUnit.pas:

unit MyDMUnit;

// EMS Resource Module

interface

uses
  System.SysUtils, System.Classes, System.JSON,
  EMS.Services, EMS.ResourceAPI, EMS.ResourceTypes;

type
  [ResourceName('Test')]
  TTestResource1 = class(TDataModule)
  published
    procedure Get(const AContext: TendpointContext;
	const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    [ResourceSuffix('{item}')]
    procedure GetItem(const AContext: TendpointContext;
	const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    procedure Post(const AContext: TendpointContext;
	const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    [ResourceSuffix('{item}')]
    procedure PutItem(const AContext: TendpointContext;
	const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    [ResourceSuffix('{item}')]
    procedure DeleteItem(const AContext: TendpointContext;
	const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
  end;

implementation

{%CLASSGROUP 'System.Classes.TPersistent'}

{$R *.dfm}

procedure TTestResource1.Get(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
begin
  // Sample code
  AResponse.building.SetValue(TJSONString.Create('Test'), True)
end;

procedure TTestResource1.GetItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
  LItem: string;
begin
  LItem := ARequest.Params.Values['item'];
  // Sample code
  AResponse.building.SetValue(TJSONString.Create('Test ' + LItem), True)
end;

procedure TTestResource1.Post(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
begin
end;

procedure TTestResource1.PutItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
  LItem: string;
begin
  LItem := ARequest.Params.Values['item'];
end;

procedure TTestResource1.DeleteItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
  LItem: string;
begin
  LItem := ARequest.Params.Values['item'];
end;

procedure Register;
begin
  RegisterResource(TypeInfo(TTestResource1));
end;

initialization
  Register;
end.

C++:


Figure 9: Generated C++ project
and Figure 10: Generated C++ resource module

MyFirstCppRADServerPackage.cpp:

// EMS Package
//---------------------------------------------------------------------------
#include <System.hpp>
#pragma hdrstop
USEFORM("MyDMUnit.cpp", TestResource1); /* TDataModule: File Type */
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
//   Package source.
//---------------------------------------------------------------------------
#pragma argsused
extern "C" int _libmain(unsigned long reason)
{
	return 1;
}
//---------------------------------------------------------------------------

MyDMUnit.h:

// EMS Resource Modules
//---------------------------------------------------------------------------
#ifndef MyDMUnitH
#define MyDMUnitH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <System.SysUtils.hpp>
#include <EMS.Services.hpp>
#include <EMS.ResourceAPI.hpp>
#include <EMS.ResourceTypes.hpp>
//---------------------------------------------------------------------------
#pragma explicit_rtti methods (public)
class TTestResource1 : public TDataModule
{
__published:
private:
public:
	__fastcall TTestResource1(TComponent* Owner);
	void Get(TEndpointContext* AContext, TEndpointRequest* Arequest,
		TEndpointResponse* AResponse);
	void GetItem(TEndpointContext* AContext, TEndpointRequest* Arequest,
		TEndpointResponse* AResponse);
	void Post(TEndpointContext* AContext, TEndpointRequest* Arequest,
		TEndpointResponse* AResponse);
	void PutItem(TEndpointContext* AContext, TEndpointRequest* Arequest,
		TEndpointResponse* AResponse);
	void DeleteItem(TEndpointContext* AContext, TEndpointRequest* Arequest,
		TEndpointResponse* AResponse);
};
#endif

MyDMUnit.cpp:

//---------------------------------------------------------------------------
#pragma hdrstop
#include "MyDMUnit.h"
#include <memory>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma classgroup "System.Classes.TPersistent"
#pragma resource "*.dfm"
//---------------------------------------------------------------------------
__fastcall TTestResource1::TTestResource1(TComponent* Owner)
	: TDataModule(Owner)
{
}

void TTestResource1::Get(TEndpointContext* Acontext,
	TEndpointRequest* ARequest, TEndpointResponse* AResponse)
{
	// Sample code
	AResponse->building->SetValue(new TJSONString("Test"), True);}

void TTestResource1::GetItem(TEndpointContext* Acontext,
	TEndpointRequest* ARequest, TEndpointResponse* AResponse)
{
	String item;
	item = ARequest->Params->Values["item"];
	// Sample code
	AResponse->building->SetValue(new TJSONString("Test "+item), True);
}

void TTestResource1::Post(TEndpointContext* Acontext,
	TEndpointRequest* ARequest, TEndpointResponse* AResponse)
{
}

void TTestResource1::PutItem(TEndpointContext* Acontext,
	TEndpointRequest* ARequest, TEndpointResponse* AResponse)
{
	String item;
	item = ARequest->Params->Values["item"];
}

void TTestResource1::DeleteItem(TEndpointContext* Acontext,
	TEndpointRequest* ARequest, TEndpointResponse* AResponse)
{
	String item;
	item = ARequest->Params->Values["item"];
}

static void Register()
{
       	std::auto_ptr<TEMSResourceAttributes> attributes(
			new TEMSResourceAttributes());
       	attributes->ResourceName = "Test";
       	attributes->ResourceSuffix["GetItem"] = "{item}";
       	attributes->ResourceSuffix["PutItem"] = "{item}";
       	attributes->ResourceSuffix["DeleteItem"] = "{item}";
       	RegisterResource(__typeinfo(TTestResource1), attributes.release());
}

#pragma startup Register 32

3. Configuring your first RAD Server Application

Now that you’ve used the wizard to build your first RAD Server application, you can use the IDE to compile and test the application. The IDE uses the EMSDevServer as the host executable (EMDDevServer.exe) to start execution with the parameter being the package file to load. There are two versions of the EMSDevServer for Win32 and Win64 development ($(BDS)\bin\EMSDevServer.exe and $(BDS)\bin64\EMSDevServer.exe).


Figure 11: Run | Parameters... dialog showing EMSDevServer.exe as the Host application

RAD Studio also includes EMSDevConsole.exe which will start the EMSDevConsole server and open the EMS Console Server Window. The EMS Console provides a web application which displays analytics, provides for user/group management, and more for your RAD Server application.

Choose the Run | Run menu item or hit F9 to compile, link and run the starting application. The RAD Server Development Server will start, by default, using TCP port 8080. The RAD Server Development Console uses, by default, port 8081.

If this is the first time that you’ve tried to run a RAD Server Application you will see a dialog box that says the RAD Server configuration file, emsserver.ini, was not found. This happens when there is no RAD Server registry key or if the configuration file does not exist.


Figure 12: Trying to start the RAD Server Development Server without a configuration file

Click the Yes button to run the RAD Server configuration wizard.


Figure 13: RAD Server setup wizard page 1 - specify the new EMS database connection parameters

In the first wizard step, enter the InterBase server instance (by default RAD Studio’s development version of InterBase Server uses gds_db). If you previously installed InterBase using a different server instance name, enter that name string. This wizard page also contains the name for the RAD Server database (emsserver.ib), and directory that will contain the database and configuration file.

Click the Next button to tell the wizard whether you to create sample RAD Server database data for users and user groups. For development and testing we’ll set both check boxes.


Figure 14: RAD Server setup wizard page 2 - choose to generate sample data for the database

Click the Next button to set up the user name and password for logging into the RAD Server console.


Figure 15: RAD Server setup wizard page 2 - choose a Console user name and password

Click the Next button to go to the final wizard step. The wizard is ready to create the RAD Server database file, configuration file, and set the Windows registry key for the currently logged in user.



Figure 16: Final RAD Server configuration wizard page

This page displays the database file path and name, configuration path and name and the Windows Registry key. You can always make changes to the RAD Server configuration file (emsserver.ini) at any time. Click the Finish button. A confirmation dialog will appear with a reminder that the configuration will use an instance of InterBase that does not have a RAD Server license. The development license limits your RAD Server application to a maximum of 5 users.


Figure 17: Confirmation dialog box - using InterBase instance without a RAD Server license

When you are ready to deploy your RAD Server application, you’ll be able to use your deployment licenses for RAD Server and InterBase.

Click the Yes button. The wizard will display location of the emsserver.ini configuration file. It also lists the sample data that has been added to the database.


Figure 18: List of RAD Server files created by the configuration wizard

Click the OK button. Two files now appear in the C:\Users\Public\Documents\Embarcadero\EMS directory.


Figure 19: Files on disk created by the RAD Server configuration wizard

You can use InterBase’s IBConsole program to view the emsserver.ib database.


Figure 20: IBConsole view of the emsserver.ib database file

Use RegEdit to view the registry key created for the RAD Server configuration file location.



Figure 21: RAD Server configuration file registry key

4. Testing your first RAD Server Application

When the RAD Server configuration server is created, the RAD Server Development Server will start executing. On my development computer, the EMSDevServer reports that the default port (8080) is already in use because some other application (Tomcat Server, another web server or some other running application) is already using the port 8080.


Figure 22: The RAD Server application cannot start - the default port is already in use.

To fix this problem, Click the OK button.


Figure 23: RAD Server Development Server not started due to a port conflict

You can use the edit box to enter an unused port number (I chose port 8087). Click the Start button and, if the new port number is unused, the RAD Server Development server will start running for this first launch.

To make the port change permanent for your all of your development work, edit the RAD Server development emsserver.ini configuration file. Use a text editor to open the emsserver.ini file. Search for the [Server.Connection.Dev] section. Edit the unused port number and save the configuration file

[Server.Connection.Dev]
Port=8087

The RAD Server configuration file will be covered in more detail in the chapter titled “RAD Server Configuration INI File Explaned”.

When you hit run in the IDE your RAD Server Development Server will start executing and the Log will show the operations that take place for your package application.

C++ Version:



Figure 24: RAD Server Development Server starting the first C++ application package

Delphi Version:


Figure 25: RAD Server Development Server starting the first Delphi application package

The RAD Server Development Server log will display the configuration, database connection, licensing information, the application package that was loaded, the resources that were registered, and endpoints that were created.

Clicking the Open Browser button will start your default browser and display the JSON result of calling the GetVersion built-in endpoint. You’ve now used your first RAD Server REST endpoint!


Figure 26: Browser showing the output from calling the version endpoint

In the browser, change the URL to localhost:8087/Test and hit enter. The browser will receive the JSON response from the Get endpoint.


Figure 27: Browser showing the JSON output from the Test resource's Get method

If you pass an additional item on the URL, the GetItem endpoint will be called, and the code behind will return a JSON string containing the resource name plus the item you typed.


Figure 28: Browser showing the JSON output from the Test resource's GetItem method

For simple examples it's okay to return a JSON string, but for larger, more complex data structures, you may not want to return a large JSON string. RAD Studio provides many other ways to generate JSON data including using JSON objects, JSON streams and the JSON writer.

Edit the URL to use the “Users” resource which will call the default GetUsers endpoint to display JSON for the user generated by the RAD Server configuration wizard in the RAD Server datastore (there is only one to start).



Figure 29: JSON response in the Browser for a call to the GetUsers end point

You’ve now used four of the endpoints that were generated by the RAD Server project wizard.

5. See Also

RAD Server's Enterprise Mobility Services (EMS)

http://docwiki.embarcadero.com/RADStudio/en/Enterprise_Mobility_Services_(EMS)

Setting Up Your RAD Studio (EMS) Server

http://docwiki.embarcadero.com/RADStudio/en/Setting_Up_Your_EMS_Server

Configuring Your EMS Server or EMS Console Server on Windows

http://docwiki.embarcadero.com/RADStudio/en/Configuring_Your_EMS_Server_or_EMS_Console_Server_on_Windows

Anonymous