Understanding the key operations within the Morfik Application Framework

As we will see, behind all their simplicity of use, the Morfik compiler and Framework hide a great deal of sophistication and complexity. It is all this backstage, behind the scenes work that empowers you to create simple code. However, this can also mean that it is difficult to understand what is happening behind the scenes when you start using Morfik. The key to understanding the Morfik Application Framework is to understand the boundaries and the sequence of events that take place across these boundaries when key operations are carried out within a Morfik application.


The Morfik Application Framework boundaries

There are two boundaries in a Morfik Web application which divide the application source code into four regions with distinct run-time and compile-time behaviour. Figure 1 shows the regions within an application source created by these two boundaries:


Figure1.jpg
Figure 1 - Morfik Application Framework Boundaries


The most noticeable is the boundary between the server side and the browser side of a web application (vertical dotted line). This boundary divides a Morfik Web application into two distinct run-time environments. The execution of a Web application takes place in two distinct contexts at run-time. The code in the browser side is compiled to JavaScript and runs within the browser while the code in the server side is compiled to native binary and runs directly on the underlying operating system.

A more subtle boundary is between the high-level application framework code and the underlying low-level platform code (horizontal dotted line). This boundary defines what gets compiled by the Morfik compiler and what is left alone (and not seen) by the Morfik compiler. Any code that is compiled by the Morfik compiler is referred to as high level code. Any code that is left untouched by Morfik compiler is referred to as Low-level code.

The high level code in the browser side gets compiled into JavaScript and runs within the browser along with pre-existing low-level JavaScript. The high level code in the server side is compiled into Intermediate code and gets passed on to a secondary compiler (platform compiler) which compiles the intermediate code along with the platform libraries into the final executable.

The high level code is platform independent while the low level code is platform specific. Currently Morfik supports two target platforms, Windows and Linux.

Interactions between the two sides of the framework

The Morfik Application Framework uniquely combines the server side and the browser side of a Web application into a single framework. Due to incompatibilities in programming models most vendors have chosen to develop frameworks for one side or the other, leaving the job of integration to the end developer.

Framework integration brings many benefits. Many low level mundane tasks related to communication between the browser and server can be done at the framework level behind the scenes without any involvement by the developer. It also provides for a better partitioning of tasks between the server side and the browser side. Many tasks are more suitable for one side or the other. Having a unified framework allows these tasks to be assigned to the side of the framework where they are done most efficiently.

One of the consequences of this integration is that most operations in the Morfik application framework involve objects from both sides of the framework. Sometimes these objects have a relationship that can be best characterised as a Client-Server type relationship, such as the objects involved with the implementation of Webmethods. Other times, these objects work together in a peer-to-peer type relationship, such as the objects that are involved with the implementation of Morfik Forms. At run time, it’s the interaction between these objects behind the scenes that make most things happen.

In the following sections we will go through the sequence of events that take place for common operations within the Morfik Application Framework across the boundary between the Browser and Server sides inside a Morfik application.

Start up sequence

The diagram in Figure 2 shows the sequence of activities and events during the start up of a Morfik Web Application. There are two separate start-up sequences. One is when the server side of the application first comes on-line, and the other is every time a browser is directed to load application's home page.


StartUpSequence.jpg
Figure 2 - Start up Sequence


Server Start-up

The start up on the server side takes place only once in the life cycle of the application and without any involvement from the browser side. The server side of the application will go through a number of initialization steps and then enters a “wait state” until a request arrives.

One of the steps involved in the start-up sequence on the server side is the invocation of the OnStart event. This server side event provides an opportunity to do application-specific tasks such as initialization of libraries or the initialization of global variables or objects. This is also a good place to override any default settings in the Framework.

Browser Start-up

The start up on the browser side involves a number of interactions with the server side. The first step in the sequence is the request by the browser to the server for the application’s main HTML file. Once the HTML is loaded the next step is initiated by the browser which is a subsequent request to the server for a copy of the application's main JavaScript file.

While the first step (request for application’s main HTML file) is repeated every time, the second step (downloading the JavaScript file) only happens the first time a browser is directed to the application. All subsequent attempts use a locally cached version of this file.

One thing worth noting is that there is no equivalent of the OnStart event on the browser side. It is, however, possible to achieve the same effect by overriding the constructor of the application’s main object. The code below shows how this can be done:


FX Code

Unit Project1XApp;
 
Interface
 
Type
Project1XApp= Class(TXApp)
    ...
    Constructor Create;
End;
 
Implementation
 
Constructor Project1XApp.Create;
Begin
    Inherited Create;
   //Insert your start-up code here
End;
 
End.


HTML Customization

As part of the start up sequence, while generating the HTML for the home page, the server side of the framework invokes a series of events related to HTML generation. These are:


Event Description
On Print HTML This event is fired on the server just before the start of the process of writing application’s main HTML page.
On Print HTMLBody End This event is fired on the server after the content of the Body tag is written into the application’s main HTML page and just before the closing Body tag is inserted.
On Print HTMLBody Start This event is fired on the server just after the Body tag is inserted and before any content is written into the application’s main HTML page.
On Print HTMLHeader This event is fired on the server when the HTML Header section is being written into the application’s main HTML page.
On Print Loading Message This event is fired on the server when the default loading message is being inserted into the application’s main HTML page.


These events can be used to customize the generated HTML content. For example, using the OnPrintLoadingMessage event the default 'loading...' message can be overridden with something more suitable for a given application. The code below shows how this can be achieved.


FX Code

Unit Project1XApp;
 
Interface
 
Type
Project1XApp= Class(TXApp)
  Published
    { Events }
    Procedure XAppPrintLoadingMessage(Response: THTTPResponse; Var Print: Boolean); Message;
  Private
    { Private declarations }
  Public
    { Public declarations }
End;
 
Implementation
 
Procedure Project1XApp.XAppPrintLoadingMessage(Response: THTTPResponse; Var Print: Boolean);
Begin
    Response.WritelnString('<div id="" style="position:fixed; ' +
                           'left:0px;top:0px;right:0px;bottom:0px;' +
                           'background:url(''/busy.gif?cls=res'') no-repeat center center"></div>');
End;
 
End.


NOTE: One thing to bear in mind is that the timing diagrams in this page do not show the overlapping nature of interactions between the browser and the server sides of the framework. The server receives requests from multiple browsers simultaneously. This combined with the stateless nature of the server framework mean that no assumption can be made about the order (or indeed the existence of any sequence) in which requests are received on the server side.

Although different in nature, the same thing also applies to the Browser side. Many requests to the server are initiated in parallel by the browser. The order in which the results are returned may not match the order with which the requests were sent.

Open Form Sequence

The bulk of the user interface in Morfik applications are made up of forms. Each form is comprised of key elements and some optional parts (such as images) that are retrieved from server and assembled in the browser. The diagram in Figure 3 shows the sequence of activities and events during the process of opening a form.


OpenFormSequence.jpg
Figure 3 - Open Form Sequence


The key tasks performed during the process of opening a Form are:

- Downloading the JavaScript associated with the form. - Creation and the downloading of the HTML snippet associated with the form. - Creation and the downloading of the XML data associated with the form - Requests for optional parts from server.

The tasks above vary depending on the value of the Form’s View Mode property and whether the form is bound to a data source. For example a request for XML data is only sent to the server if the Form’s View mode is set to vmSingle and the form is bound to a data source.

The JavaScript associated with a form is the first thing that needs to be downloaded from the server. This JavaScript is only downloaded the first time the form is opened. Subsequent attempts will use a locally cached version of the JavaScript content. Once the JavaScript is downloaded, the Form object and all the containing controls are created. At this point the OnCreate event of the form is invoked.

Note: while control objects are created they are not linked to the underlying HTML elements. This means that the visual properties of controls will not be accessible in the OnCreate event handler. The Attrs property of a control holds design-time values of control properties any change to control properties during object creation will only affect these values and not the subsequent HTML properties, associated with a given control.

The HTML generation for the form takes place on the server side. The Form server side class is instantiated and is passed on to Form generator. If the View Mode property is set to vmContinuous the associated Data Source is accessed and the data is injected into the HTML. Once the HTML is generated the Form objects is destroyed. It is important to note that the Form object has a very short life span on the server side.

While generating HTML, the server side of the framework invokes a number of events. The OnBeforeExecute is invoked before the HTML generation is started. And the OnAfterExecute is invoked when the HTML generation is completed. For every control during the process of HTML generation the OnBeforePrint and OnAfterPrint events are invoked providing the opportunity to customize control HTML. The table below shows events associated with Form generation.


Event Description
On Before Execute This event is fired by a Form (or Report) on the server after the Form (or Report) is created and before the process of preparing response for a request is begun.
On After Execute This event is fired by a Form (or Report) on the server after the Form (or Report) has completed its part in responding to a request and just before the Form (or Report) is destroyed.
On Before Print This event is fired by a control on the server before control’s HTML (or in the case of Report generation, PDF) content is generated.
On After Print This event is fired on the server by a Control after its HTML (or in the case of Report generation, PDF) content is generated.


Once the HTML is received by the browser side of the framework, it gets inserted into the browser internal page structure and the process of linking Morfik controls to the underlying browser HTML elements begins. The SetupDOMHandle method of every control is called for this purpose.

If the View Mode property is set to vmSingle a request is sent to the server for the associated data. The request is a call to a system-created WebMethod that publishes the content of a table in SOAP XML format.

At this point the OnReady event is invoked providing the opportunity to customize or update certain aspects of the Form environment. The OnReady event is invoked only once when the Form is first constructed. The OnShow event is invoked every time a Form is made visible.

Events invoked on the browser side:


Event Description
On Create This event is fired within the browser when a Form object is being created.
On Ready This event is fired within the browser after a Form has been successfully created and its content is ready for access by other objects within the browser.
On Show This event is fired within the browser immediately before a Form becomes visible (the same as OnBeforeShow event).


Finally requests for associated images are sent to server. This completes the process of opening a Form.

Note: The diagram in Figure 3 only shows request for one Form. In practice there are always multiple Forms that are opened simultaneously. Combined with the fact that the server receives requests from many Browsers, there should be no assumption made about the sequence of these activities.

Opening a form Programmatically

Sometimes it is useful to open a form programmatically so you can pass other than just string data to the form being opened. The object in the framework responsible for opening a form is the TFormOpener class which is defined in the SystemForm module. In order to pass objects to a form being opened, a new descendant of the TFormOpener class needs to be derived and its destroy method needs to be overridden. This is shown in the code example below. This example opens the About form in the Default Project and passes a callback function pointer to the from.


FX Code

Unit Index;
 
Interface
 
Type
Index=Class(Form)
    Container4 : Container;
    Container1 : Container;
    TextLabel3 : TextLabel;
    TextLabel1 : TextLabel;
    TextLabel5 : TextLabel;
    Subform2   : SubForm;
    TextLabel2 : TextLabel;
    Button1    : Button;
    Procedure Button1Click(Event: TDOMEvent); Message;
  Private
    { Private declarations }
  Public
    { Public declarations }
    Procedure MyCallBack;
End;
 
Implementation
 
Uses
   About;
 
Type
TMyFormOpener = Class(TFormOpener)
    Data : Pointer;
    Destructor  Destroy; Override;
End;
 
Destructor TMyFormOpener.Destroy;
Begin
    About(NewForm).CallBack := Data;
    Inherited Destroy;
End;
 
Procedure Index.MyCallBack;
Begin
    //
End;
 
Procedure Index.Button1Click(Event: TDOMEvent);
Var
    FormOpener : TMyFormOpener;
Begin
    FormOpener := TMyFormOpener.Create('About','About',Subform2,0,'',True);
    FormOpener.Data := GetMEthodPointer(Self,@MyCallBack);
End;
 
End.


The Data field of the TMyFormOpener class is set at the time of opening a form and when the form is opened this value is passed on to the form. It is important to note that the data field is not available to the form during the opening process and it's only at the end of the opening process, when the TFormOpener class is being destroyed, is when the value of this field is passed on to the form.

Run WebMethod Sequence

WebMethods combine a function (on the server side) and a method of invocation (on the browser side) in order to provide an easy mechanism for Remote Procedure Call (RPC) from the browser to the server side within a Morfik application. The following diagram in Figure 4 shows steps involved in this process.


RunWebMethodSequence.jpg
Figure 4 - Run Web Method Sequence


The first step involves downloading the WebMethod's client JavaScript. This step only happens the first time a WebMethod is executed. Subsequent calls will use a locally cached version of the JavaScript file.

The second step uses the JavaScript code to initiate a call to the server. The request is first serialized into XML format and then sent to the server. The server deserializes the request XML into a set of objects and makes a local function call to the WebMethod’s main code. Once the local function call is completed, the result is serialised into XML and returned to the browser. Finally, upon arrival, the result gets deserialized into a set of objects and the WebMethod’s HandleResponse method is called.

The XML monitor panel can be used to inspect the request and response in XML format. This is a good debugging tool to ensure correct parameter values are used.

Open Report Sequence

The diagram in Figure 5 shows the sequence of events when opening a report. The PDF for a Report is generated on the server side. A Report object is created and passed on to the Report generator. Once the PDF is generated the Report object is destroyed.


OpenReportSequence.jpg
Figure 5 - Open Report Sequence


While generating PDF, the server side of the framework invokes a number of events. The OnBeforeExecute is invoked before the PDF generation is started. And the OnAfterExecute is invoked when the PDF generation is completed. For every control during the process of PDF generation the OnBeforePrint and OnAfterPrint events are invoked providing the opportunity for PDF customization. The table below shows events associated with Report generation.


Event Description
On Before Execute This event is fired by a Form (or Report) on the server after the Form (or Report) is created and before the process of preparing response for a request is begun.
On After Execute This event is fired by a Form (or Report) on the server after the Form (or Report) has completed its part in responding to a request and just before the Form (or Report) is destroyed.
On Before Print This event is fired by a control on the server before control’s HTML (or in the case of Report generation, PDF) content is generated.
On After Print This event is fired on the server by a Control after its HTML (or in the case of Report generation, PDF) content is generated.


Incremental download of browser side JavaScript code

One aspect of Morfik’s browser side programming that requires a mention is the way in which the JavaScript code is downloaded into the browser. Upon start, the core of the application's AJAX engine is sent to the browser as a single JavaScript. This is enough to get the AJAX user interface up and running. Then the first time a module is being accessed within the browser, the associated JavaScript is downloaded and. This allows for a higher level of scalability but at the same time it means extra programming work before calling functions within other modules. Morfik has a number of functions (OpenForm, RunWebMethod and OpenReport) that hide the code that is responsible for downloading the JavaScript.

By default, the browser side code of WebMethods and standard Modules are always compiled into the application's main JavaScript file, while the code associated with the browser side of Forms are compiled into separate JavaScript files for incremental download. The compiler directive %MA Static can be used in order to make the browser side code of a given Form compiled into the main JavaScript file. This will reduce the number of round trips to the server side. It is recommended that the Forms that are frequently used within an application to be marked as STATIC.

The following code sample shows the browser side code of a Form that will be compiled into the application's main JavaScript file:


FX Code

{%MA STATIC}
Unit Index;
 
Interface
 
Type
Index=Class(Form)
  Private
    { Private declarations }
  Public
    { Public declarations }
End;
 
Implementation
 
End.


Morfik Application Framework folder structure

The Morfik Application Framework source is stored in multiple folders within the Morfik installation folder. Framework’s high level source code is kept in two separate folders, one for the Browser modules and one for Server modules:

[Morfik Installation Folder]\system\Framework\Browser 
[Morfik Installation Folder]\system\Framework\Server

The platform libraries are located in the following folder:

[Morfik Installation Folder]\system\PlatformCompilers\commonlibrary

By default Morfik compilers look for the framework modules within these folders. You can, however, specify different locations for the framework and platform modules by specifying alternative paths in the Morfik Options Compiler preferences dialog. Please refer to Options Compiler preferences dialog for details of how to change these settings.


Related Topics

Back to top