Synopse

To content | To menu | To search

2012, Sunday May 20

Recursive calls and private objects

In a Stack Overflow question, someone asked about some nested procedure call he found out. That is, a procedure inside another procedure.

He found out this coding style to be messy, which sounds like a reasonable opinion. But his alternative proposal of putting the internal procedure outside the main one, i.e. making it global, is IMHO even worse.

In some case, a private class, or even record or object with methods is an handy and maintainable implementation pattern.

Continue reading...

2012, Thursday May 3

Custom JSON serialization of records

By default, during interface-based service call, any record parameter or function result will be serialized with our proprietary binary (and optimized layout) - i.e. RecordLoad and RecordSave functions - then encoded in Base-64, to be stored as plain text within the JSON stream.

But custom record JSON serialization can be defined, as with any class - see this article - or dynamic array - see this article.

Continue reading...

2012, Wednesday April 25

The mORMot attitude

In a discussion with Henrick Hellström, in Embarcadero forums, I wrote some high-level information about mORMot.

It was clear to me that our little mORMot is now far away from a simple Client-Server solution.

The Henrick point was that with Real Thin Client (RTC), you are able to write any Client-Server solution, even a RESTful / JSON based one.

He is of course right, but it made clear to me all the work done in mORMot since its beginning.
From a Client-Server ORM, it is now a complete SOA framework, ready to serve Domain-Driven-Design solutions.

Continue reading...

2012, Friday April 20

WCF, mORMot and Event Sourcing

Our latest mORMot feature is interface-based service implementation.

How does it compare with the reference of SOA implementation (at least in the Windows world) - aka WCF?

"Comparaison n'est pas raison", as we use to say in France.
But we will also speak about Event Sourcing, and why it is now on our official road map.
Comparing our implementation with WCF is the opportunity to make our framework always better.

Continue reading...

2012, Thursday April 19

Smart: mORMot, from Delphi to JavaScript

Did you hear from the great Smart project?

It is an IDE and some source runtime able to develop and compile an Object-Pascal project into a HTML 5 / CSS 3 / JavaScript embedded application.
It does target AJAX Mobile application creation (i.e. Android and iPhone/iPad apps running Web-Kit).
You'll get an unique .html file containing the whole client-side application: it won't need any server side implementation. Using a third-party tool like PhoneGap, you'd be able to supply your customers with true native applications, running without any network, and accessing the full power of any modern Smart Phone.

Smart is a great candidate for implementing rich client-side AJAX applications, to work with our client-server mORMot framework.

In order to interface Smart code with mORMot, we started implementing some low-level code to work with our RESTful authentication scheme.

So we'll need to implement some Smart dedicated Open Source code implementing crc32 and SHA-256 hashing.

Continue reading...

2012, Friday April 13

Custom JSON serialization of any class

By default, our mORMot framework is able to serialize any class into a true JSON object.

All published properties will be written as JSON object members.

In some cases, it may be handy to have a custom serialization, for instance if you want to manage some third-party classes, or to adapt the serialization scheme to a particular purpose, at runtime.

Continue reading...

2012, Thursday April 12

Custom JSON serialization of any dynamic array content

One nice feature of the TDynArray wrapper and its associated methods, as defined and used in our framework, is the ability to serialize any dynamic array as JSON content.

By default, only "standard" dynamic arrays (like TIntegerDynArray) are serialized as true JSON array: other not known kind of arrays are serialized as binary content, within a Base64 encoding.

This is a very efficient solution for a pure Delphi application, since it will be fast and always works, but won't be easy to deal with from an AJAX client.

Applications can now supply a custom JSON serialization for any other dynamic array, via the TTextWriter.RegisterCustomJSONSerializer() class method.
Two callbacks are to be supplied for a dynamic array type information, in order to handle proper serialization and un-serialization of the JSON array.

Continue reading...

2012, Tuesday April 10

How function results are allocated

One potential issue with Delphi coding, is about how the result of a functions are implemented.

If you forget to set a result value to a function, you'll get a compiler warning.
Never underestimate such warning: IMHO this is not a warning, but an error.

And you should better be aware of the handling of reference-counted types (e.g. string) in a function results: those are passed the stack as var parameters, so the result of a function may be set even if an exception is raised during function execution!

Continue reading...

2012, Wednesday March 28

Return custom content from an interface-based service

As stated by this previous article, the default answer format is a valid JSON object.

In some cases, it may be useful to have a service operation (i.e. an interface method) returning any content, e.g. some plain TEXT, HTML or binary data (like a picture).

Continue reading...

2012, Wednesday March 7

Interface based services - sample code

In addition to the other related blog articles, you can find in the "SQLite3/Samples/14 - Interface based services" folder of the supplied source code distribution, a dedicated sample about this feature.

Purpose of this code is to show how to create a client-server service, using interfaces, over named pipe communication.

Continue reading...

Interface based services - Implementation details

You will find out in SQLite3Commons.pas all classes implementing this interface communication.

There are two levels of implementation:
- A services catalog, available in TSQLRest.Services property, declared as TServiceContainer (with two inherited versions, for each side);
- A service factory for each interface, declared as TServiceFactory (also with two inherited versions, for each side).

In fact, TServiceFactory.Create constructor will retrieve all needed RTTI information of the given interface, i.e. GUID, name and all methods (with their arguments). It will compute the low-level stack memory layout needed at execution. And the corresponding "contract" will be computed, to validate that both client and server expect the exact same interface.

On the server side, TServiceFactoryServer.ExecuteMethod method (and then a nested TServiceMethod.InternalExecute call) is used to prepare a valid call to the implementation class code from a remote JSON request.

On the client side, a TInterfacedObjectFake class will be created, and will emulate a regular Delphi interface call using some on-the-fly asm code generated in the TServiceFactoryClient.Create constructor.

Continue reading...

Interface based services - Using services on the Client or Server sides

Once the service is registered on the server side, it is very easy to use it in your code.

In a complex Service Oriented Architecture, it is pretty common to have services calling each other. Code re-usability is a key here. So you'll have to consume services on the server side. According to the SOLID design principles, you'd better rely on abstraction in your code, i.e. not call the service implementation, but the service abstract interface.

You can use the following method of your TSQLRest.Services instance (note that this method is available on both client and server sides, so is the right access point to all services):

 function TServiceFactory.Get(out Obj): Boolean;

Continue reading...

Interface based services - Server side

In order to have an operating service, you'll need to implement a Delphi class which matches the expected interface.

Continue reading...

Interface based services - defining a data contract

In a Service Oriented Architecture, services tend to create a huge list of operations.
In order to facilitate implementation and maintenance, operations shall be grouped within common services.

The data contract is to be defined as a plain Delphi interface type.
In fact, the sample type as stated in a previous blog article can be used directly:

type
  ICalculator = interface(IInvokable)
    ['{9A60C8ED-CEB2-4E09-87D4-4A16F496E5FE}']
    /// add two signed 32 bit integers
    function Add(n1,n2: integer): integer;
  end;

This ICalculator.Add method will define one "Add" operation, under the "ICalculator" service (which will be named internally 'Calculator' by convention).
This operation will expect two numbers as input, and then return the sum of those numbers.

Continue reading...

Interface based services

The Client-Server services via methods implementation (our DataSnap-like feature) gives full access to the lowest-level of the mORMot's core, so it has some advantages:
- It can be tuned to fit any purpose (such as retrieving or returning some HTML or binary data, or modifying the HTTP headers on the fly);
- It is integrated into the RESTful URI model, so it can be related to any table/class of our ORM framework (like DataAsHex service above), or it can handle any remote query (e.g. any AJAX or SOAP requests);
- It has a very low performance overhead, so can be used to reduce server workload for some common tasks.

But this implementation pattern has some drawbacks:
- Most content marshaling is to be done by hand, so may introduce implementation issues;
- Client and server side code does not have the same implementation pattern, so you will have to code explicitly data marshaling twice, for both client and server;
- The services do not have any hierarchy, and are listed as a plain list, which is not very convenient;
- It is difficult to synchronize several service calls within a single context, e.g. when a workflow is to be handled during the application process (you have to code some kind of state machine on both sides);
- Security is handled globally for the user, or should be checked by hand in the implementation method (using the aParams.Context values).

You can get rid of those limitations with the interface-based service implementation of mORMot. For a detailed introduction and best practice guide to SOA, you can consult this "classic" article.

According to this document, all expected SOA features are now available in the current implementation of the mORMot framework (including service catalog aka "broker").

Continue reading...

2012, Wednesday February 29

Delphi and interfaces

No, interface(-book) is not another social network, sorry.

In Delphi OOP model, an interface defines a type that comprises abstract virtual methods.
The short, easy definition is that an interface is a declaration of functionality without an implementation of that functionality. It defines "what" is available, not "how" it is made available. This is the so called "abstraction" benefit of interfaces (there are another benefits, like orthogonality of interfaces to classes, but we'll see it later).

In its upcoming 1.16 revision, our mORMot framework is able to use interface for its service definition.

So we'll discuss and introduce this gem available in all modern languages - including Delphi: interfaces.

Continue reading...

2012, Tuesday February 14

ORM cache

Here is the definition of "cache", as stated by Wikipedia:

In computer engineering, a cache is a component that transparently stores data so that future requests for that data can be served faster. The data that is stored within a cache might be values that have been computed earlier or duplicates of original values that are stored elsewhere. If requested data is contained in the cache (cache hit), this request can be served by simply reading the cache, which is comparatively faster. Otherwise (cache miss), the data has to be recomputed or fetched from its original storage location, which is comparatively slower. Hence, the greater the number of requests that can be served from the cache, the faster the overall system performance becomes.

To be cost efficient and to enable an efficient use of data, caches are relatively small. Nevertheless, caches have proven themselves in many areas of computing because access patterns in typical computer applications have locality of reference. References exhibit temporal locality if data is requested again that has been recently requested already. References exhibit spatial locality if data is requested that is physically stored close to data that has been requested already.

In our ORM framework, since performance was one goal since the beginning, cache has been implemented at four levels:

  • Statement cache for reuse of SQL prepared statements, and bound parameters on the fly - note that this cache is available not only for the SQlite3 database engine, but also for any external engine; 
  • Global JSON result cache at the database level, which is flushed globally on any INSERT / UPDATE
  • Tuned record cache at the CRUD/RESTful level for specified tables or records on the server side; 
  • Tuned record cache at the CRUD/RESTful level for specified tables or records on the client side.

Continue reading...

2012, Thursday February 9

Using SetLength or SetString

Some Delphi users even do not know the existence of the SetString function.

As stated by the official documentation:

procedure SetString(var S: String; Buffer: PChar; Length: Integer);

For a long string variable, SetString sets S to reference a newly allocated string of the given length. If the Buffer parameter is not nil, SetString then copies Len characters from Buffer into the string; otherwise, the content of the new string is left uninitialized. If there is not enough memory available to create the string, an EOutOfMemory exception is raised. Following a call to SetString, S is guaranteed to reference a unique string (a string with a reference count of one).

Some have noticed that in our libraries, I sometimes use SetString instead of SetLength.
When the string is already allocated, it could be faster to use SetString, if you are sure that you will overwrite the string content.

Continue reading...

2012, Monday February 6

Modification of TSQLRestServerCallBack method prototype (bis)

In order to implement some RESTful Services, a callback has to be defined on the server side.

The prototype of these methods has been modified one more time, to supply an unique parameter:
This is a CODE BREAK change and you shall refresh ALL your server-side code to match the new signature.

This unique parameter will let the signature remain untouched in your code implementation, even if the framework evolves (like adding a new parameter).

Continue reading...

2012, Sunday January 29

Microsoft states: OleDB out - enjoy ODBC!

For our native connection to any DB, we developed a set of classes and several units.

We implemented at first OleDB, then native Oracle direct access and SQlite3 static engine.

Now, Microsoft is officially deprecating OleDB, and urge all developers to switch to the open and cross-platform ODBC API for native connection.

Continue reading...

- page 1 of 8