0% found this document useful (0 votes)
447 views

Introduction To DelphiMVCFramework

This document discusses DelphiMVCFramework, a framework for building RESTful web services and dynamic web pages with Delphi. It provides an overview of the framework's main features, which include support for RESTful APIs, server-side page generation using eLua, and load balancing. Examples are given of defining controllers, actions, and routing within the framework. The request/response cycle and techniques for reading and rendering response parameters and objects are also outlined.

Uploaded by

Vlad
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
447 views

Introduction To DelphiMVCFramework

This document discusses DelphiMVCFramework, a framework for building RESTful web services and dynamic web pages with Delphi. It provides an overview of the framework's main features, which include support for RESTful APIs, server-side page generation using eLua, and load balancing. Examples are given of defining controllers, actions, and routing within the framework. The request/response cycle and techniques for reading and rendering response parameters and objects are also outlined.

Uploaded by

Vlad
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 27

25/11/2013

RESTful interfaces and dynamic


web pages with Delphi

Daniele Teti
R&D Director & Educational

What is DelphiMVCFramework?

• Powerful XE3, XE4 and XE5 framework for web


solutions
• Built in WebServer
• HTTP/HTTPS support
• It use Embarcadero WebBroker but is not tied to it
• Inspired to Java JAX-RS
• It is simple
• You can be productive in few minutes

1
25/11/2013

DMVCFramework main features

• RESTful
– Richardson Maturity Model Level 3
• Designed with services and web client app in mind
• Server side generated pages using eLua (Embedded
Lua)
• Can be used in load balanced environment using
memcached (memcached.org)
• Fancy URL with parameter mappings
• Integrated Delphi RESTClient
• Messaging extension using STOMP
• Experimental support for IOCP

What kind of applications can be build with


DMVCFramework?

• Application Servers
• RESTful web services
• Classic web application
• Web Client Applications
• Messaging solutions
– based on Apache ActiveMQ or Apache Apollo
• Delphi thin clients
• Mobile and Web backends
• Scalable (Load balanced) web systems
• Secure servers with HTTPS

2
25/11/2013

Simple architecture, multiple clients

DATABASE

Full Network, real world, many users

Reverse Proxy (nginx, Apache httpd, etc)

State Server1 State Server2


DATABASE

3
25/11/2013

Request/Response Cycle

Your first DMVCFramework

type
TWebModule1 = class(TWebModule)
procedure WebModuleCreate(Sender: TObject);
private
DMVC: TMVCEngine;
end;

. . .

procedure TWebModule1.WebModuleCreate(
Sender: TObject);
begin
DMVC := TMVCEngine.Create(self);
end;

4
25/11/2013

Richardson Maturity Model Level 3

DMVCFramework

http://martinfowler.com/articles/richardsonMaturityModel.html

Controllers, Actions and Routing

DelphiMVCFramework

5
25/11/2013

Architecture of DMVCFramework Server

• One Application
• Many Controllers
– Classes inherited from TMVCController
• Many Actions for each controller
– Controller Actions are its methods instrumented with a
specific attribute
• Controller is addresses using a piece of URL
• Actions are selected using the second part of the URL

Architecture of DMVCFramework Server

• One Application
• Many Controllers
– Classes inherited from TMVCController
• Many Actions for each controller
– Controller Actions are its methods instrumented with a
specific attribute
• Controller is addresses using a piece of URL
• Actions are selected using the second part of the URL
Server Name Controller Action
www.myserver.com/people/rome/danieleteti

6
25/11/2013

Controllers and Routing

type
[MVCPath(‘/blog’)]
TBlog = class(TMVCController)
public
[MVCPath(‘/posts/($year)/($month)/($title)’)]
procedure GetArticle(CTX: TWebContext);
end;

Matching URI Samples


/blog/posts/2011/05/a-brand-new-framework
/blog/posts/2013/05/rest-rest-for-delphi
/blog/posts/1/5/thisAndThat
/blog/posts/2013/05/123

DMVCFramework Attributes

Name Scope Optional Used for routing?


MVCPath Class No Yes
Method
MVCHTTPMethod Method Yes Yes

MVCConsumes Method Yes Yes

MVCProduces Method Yes No

7
25/11/2013

Controllers and Routing (1)

[MVCPath(‘/blog’)]
TBlog = class(TMVCController)
public
[MVCHttpMethod([httpGET])]
[MVCPath(‘/posts/($year)/($month)/($title)’)]
procedure GetArticle(CTX: TWebContext);

[MVCHttpMethod([httpPOST])]
[MVCPath(‘/posts/($year)/($month)/($title)’)]
procedure CreateArticle(CTX: TWebContext);
end;

Controllers and Routing (2)

[MVCPath(‘/blog’)]
TBlog = class(TMVCController)
public
[MVCHttpMethod([httpDelete])]
[MVCPath(‘/posts/($year)/($month)/($title)’)]
procedure DeleteArticle(CTX: TWebContext);

[MVCHttpMethod([httpPOST, httpPUT])]
[MVCPath(‘/posts/($year)/($month)/($title)’)]
procedure UpdateArticle(CTX: TWebContext);
end;

8
25/11/2013

Controllers and Routing (3)

[MVCPath(‘/blog’)]
TBlog = class(TMVCController)
public
[MVCProduce(‘application/json’, UTF8)]
[MVCHTTPMethod([httpGET])]
[MVCPath(‘/posts/($year)/($month)’)]
procedure GetArticleByMonth(
CTX: TWebContext);
end;

Controllers and Routing (4)

[MVCPath(‘/blog’)]
TBlog = class(TMVCController)
public
[MVCProduce(‘application/json’, UTF8)]
[MVCConsumes(‘application/json’)]
[MVCHTTPMethod([httpPOST])]
[MVCPath(‘/posts/($year)/($month)’)]
procedure CreateArticle(
CTX: TWebContext);
end;

9
25/11/2013

Request parameters

• Query String
– GET, POST, PUT, DELETE, HEAD, OPTIONS

• URL Mapped
– GET, POST, PUT, DELETE, HEAD, OPTIONS

• Request Body
– POST, PUT, OPTIONS

• Cookies
– GET, POST, PUT, DELETE, HEAD, OPTIONS

HTTP Safe Methods

• The convention has been established that the GET


and HEAD methods SHOULD NOT have the
significance of taking an action other than retrieval.
• These methods ought to be considered "safe".
– It is not possible to ensure that the server does not
generate side-effects as a result of performing a GET
request (eg. Logging, audit, tracing). However, the
important distinction here is that the user did not request
the side-effects, so therefore cannot be held accountable
for them.

10
25/11/2013

HTTP Idempotent Methods

• With IDEMPOTENT methods the side-effects of N > 0


identical requests is the same as for a single request.
• The methods GET, HEAD, PUT and DELETE share this
property. Also, the methods OPTIONS and TRACE
SHOULD NOT have side effects, and so are inherently
idempotent.

Reading Parameters

Context.Request.Params[‘ParamName’]

Reads Parameters in the following order


• URL Mapped parameters
• Query String parameters
• FORM parameters (eg. HTML Form Submit)
• Cookie fields

11
25/11/2013

URL mapped parameters

GET /blog/posts/danieleteti/2013/11

[MVCPath(‘/posts/($user)/($year)/($month)’)]
[MVCHTTPMethod([httpGET])]
procedure GetArticles (CTX: TWebContext);
. . .
procedure GetArticles (CTX: TWebContext);
var
year,month: Integer; user: String;
begin
user := CTX.Request.Params[‘user’];
year := CTX.Request.Params[‘year’].ToInteger;
month := CTX.Request.ParamsAsInteger[‘month’];
end

QueryString mapped parameters

GET /blog/posts/danieleteti?year=2013&month=11

[MVCPath(‘/posts/($user)’)]
[MVCHTTPMethod([httpGET])]
procedure GetArticles (CTX: TWebContext);
. . .
procedure GetArticles (CTX: TWebContext);
var
year,month: Integer; user: String;
begin
user := CTX.Request.Params[‘user’];
year := CTX.Request.Params[‘year’].ToInteger;
month := CTX.Request.Params[‘month’].AsInteger;
end

12
25/11/2013

DEMO

• Routing

Renders

DMVCFramework

13
25/11/2013

Using Renders

• «Renders» are a set of controller methods that actually


produces the response stream
• There are a lot of Render methods with oveload for many
types of data
• Renders can set the HTTP Status Code and the ContentType
• Currently you can render
– Text
– DataSets
– JSONValues
– Delphi Objects
– List of Delphi Objects
– Exceptions
– HTML pages using eLua
– Raw Streams

Render a TObject

procedure TPeople.GetPerson(CTX: TWebContext);


var
P: TPerson;
begin
P := TPerson.Create;
P.FirstName := 'Daniele';
P.LastName := 'Teti';
P.DOB := EncodeDate(1975, 5, 2);
P.Married := True;
Render(P);
end;

14
25/11/2013

Render a TJSONValue

procedure TPeople.GetPerson(CTX: TWebContext);


var
J: TJSONObject;
begin
J := TJSONObject.Create;
J.AddPair('FirstName', 'Daniele');
J.AddPair('LastName', 'Teti');
J.AddPair('DOB',
ISODateToString(EncodeDate(1975, 5, 2)));
J.AddPair('Married', TJSONTrue.Create);
Render(J);
end;

Render a TDataSet

procedure TCustomersController.GetAll(
CTX: TWebContext);
var
wm: TWebModule1; //the main WebModule
begin
wm := GetCurrentWebModule as TWebModule1;
wm.qryCustomers.Open;
//dataset is rendered as json array of objects
Render(wm.qryCustomers);
end;

15
25/11/2013

DEMO

• Renders

Filtering Action Requests

• Each action call (aka controller method) can


intercepted and handled
• Controllers initialization methods are also available

• DEMO
– ActionsFilter

16
25/11/2013

Session and Application Session

• DMVCFramework supports session for each request


• Session is a key/value structure private for each user
• Application Session is similar but it is shared to all users (WARNING!!!)
• Session is alive for Config[‘session_timeout’] minutes

procedure TTestServerController.Login(ctx: TWebContext);


begin
Session['username'] := ctx.Request.Params['username'];
end;

procedure TTestServerController.Logout(ctx: TWebContext);


begin
//destroy session with
SessionStop(false);
end;

Server Side Views with eLua

• Server side views uses the Lua language just like PHP
pages use PHP (code into text)
• eLua (Embedded Lua) has been specifically designed
for DMVCFramework in its brother project called
LuaDelphiBinding
• It is similar to PHP for HTML, JSP for Java and erb for
Ruby

<?lua= 3*8 ?> EXPRESSION


<?lua arbitrary_lua_code ?> SCRIPTLET

17
25/11/2013

Why Lua?

• Lua is small, fast and simple


– The whole implementation is less than 6000 lines of ANSI C
– Requires only one dll on Windows

• Has been designed as extension language


• Dynamic and not strongly typed
• Clear, simple and familiar syntax
• Great extensibility
• Functions as first-class values
• Tables a.k.a Associative arrays
• Garbage collection
• Allows extension of the semantics of the language.
• Widely used even outside the Delphi world

Is Lua popular?
• Lua is the most popular scripting language for game programming
• Adobe Photoshop Lightroom uses Lua for its user interface.
• Apache HTTP Server can use Lua anywhere in the request process
• Cisco uses Lua to implement Dynamic Access Policies within the Adaptive
Security Appliance.
• Damn Small Linux uses Lua to provide desktop-friendly interfaces
• FreePOPs, an extensible mail proxy, uses Lua to power its web front-end.
• MySQL Workbench uses Lua for its extensions & add-ons.
• Nginx has a powerful embedded Lua module that provides an API
• nmap network security scanner uses Lua as the basis for its scripting
language
• Vim has Lua scripting support
• VLC media player uses Lua to provide scripting support.
• Since March 2013, Lua is used as a new template scripting language on
Wikipedia and other Wikimedia Foundation wikis.
• WinGate proxy server allows event processing and policy to execute lua
scripts with access to internal WinGate objects.
• Wireshark network packet analyzer allows protocol dissectors and post-
dissector taps to be written in Lua

18
25/11/2013

eLua sample (expressions and code)

This is text but this is <?lua= ″Lua″ ?>


And now, Good <?lua
if isMorning() then
?>
Morning
<?lua
else
?>
Evening
<?lua
end
?> to all the people

Getting Started with eLua

• eLua files in the document_root are executed directly


• Actions can use eLua views using
LoadView(‘viewname’)
• Lua Helpers helps to create html page faster
• Similar to the RubyOnRails form helpers

19
25/11/2013

DEMO

• Simplewebapplication

Serve static files

• Use the «document_root» to serve static files


– HTML, Images, javascripts, binary…
• This allows to use Web Client javascript framework
– jQuery
– AngularJS
– Ember.js
– Backbone.js
– etc

20
25/11/2013

Web Client App DEMOS

• WineCellarServer
• WineCellarServerWITHDORM
• AngularJS\WebClientSample

Embedded Logging system

procedure Log(AMessage: string);


procedure LogW(AMessage: string);
procedure LogE(AMessage: string);
procedure LogEx(
AException: Exception;
AMessage: string);
procedure Log(LogLevel: TLogLevel;
const AMessage: string);
procedure LogEnterMethod(AMethodName: string);
procedure LogExitMethod(AMethodName: string);

Configurable LogLevel using Config

21
25/11/2013

Load Balancing

• DMVCFramework has been designed with clustering


in mind
• Session factory allows 2 kind of sessions
– Memory
• Do not support load balancing
• Sessions do not survives to restart
– State Server
• Support load balancing
• Sessions survive to restart
• Require a memcached daemon

Messaging estensions

• A specific system controller support Messaging


Extensions
• TMVCBUSController mapped to /messages
• Provides the following routes
[MVCPath('/subscribe/($name)')]
[MVCPath('/unsubscribe/($name)')]
[MVCPath('/receive')]
[MVCPath('/enqueue/($topic)')]
[MVCPath('/topics')]
• Method to enqueue message available
– EnqueueMessageOnTopic(topicname, jsonobject);

22
25/11/2013

Messaging Extensions DEMO

• CallbackDemo

RESTClient

DMVCFramework

23
25/11/2013

RESTClient

• Simple Delphi client for DMVCFramework


• Completely integrated with the Mapper

var
rest: TRESTClient;
response: IRESTResponse;
Person: TPerson;
begin
rest := TRESTClient.Create('localhost', 3000);
response := rest.doGET('/people', ['1']);
Person := Mapper.
JSONObjectToObject<TPerson>(response.BodyAsJSONObject);
ShowMessage(Person.FullName);
Person.Free;
rest.Free;
end;

RESTClient Asynch

RESTClient.Asynch(
procedure(Response: IRESTResponse)
begin
//do something with response
end,
procedure(E: Exception)
begin
//do something with exception
end).
doPOST('/echo', [‘one', ‘two'],
‘Hello World’);

24
25/11/2013

RESTClient Asynch

RESTClient.Asynch(
procedure(Response: IRESTResponse) begin
//do something with response
end,
procedure(E: Exception) begin
//do something with exception
end,
procedure begin
//when finished (success or failure)
end).
doPOST('/echo', [‘one', ‘two'],
‘Hello World’);

DMVCFramework SubProjects

DMVCFramework

25
25/11/2013

Mapper

• Powerful converter for Delphi Objects, JSONValues and


DataSets
• Some notable conversions
– ObjectToJSONObject
– JSONObjectToObject<T>
– ObjectListToJSONArray
– JSONArrayToObjectListOf<T>
– DataSetToJSONArray
– JSONArrayToObjectListOf<T>

LuaDelphiBinding

• Lua bind for Delphi


• Uses Lua 5.1
• Helper methods to push Delphi dictionaries and Delphi
Object as Lua Tables
• Helper to publish functions
• LuaTextFilter to handle eLua even outside the
DMVCFramework

26
25/11/2013

Thank You

Daniele Teti
[email protected]
www.danieleteti.it
@danieleteti

27

You might also like