Axional Studio HTML Pages is a set of tools that allows creating HTML pages right from the beginning, without the limitations of style and functionalities of the Axional Studio Objects, but with the possibility of accessing and modifying information of system databases.

1 Introduction

1.1 What is it?

Axional Studio HTML Pages is a server scripting implementation for making dynamic and interactive Web pages.

Let's see an example of a simple HTML Page:

Example
Copy
<xsql-script name='sample_1'>
                <body>
                    <return>
            <![CDATA[
                    <!DOCTYPE HTML>
                        <html>
                            <body>
                                  Hi, I'm a Axional Studio HTML Page!
                            </body>
                        </html>
            ]]>
                    </return>
                </body>
            </xsql-script>

Instead of lots of programming code, complex libraries and settings to output an HTML (as seen in JSP or Java), Axional Studio HTML Pages take advantage of the power and simplicity of XSQL Script for embedding the output HTML.

Axional Studio HTML Pages, in opposition of client-side JavaScript, is executed on the server, generating HTML which is then sent to the client. The client would receive the results of running that XSQL Script, but would not know what the underlying code was.

The best thing of Axional Studio HTML Pages is that is very simple for a newcomer, but offers many advanced features for an advanced programmer.

1.2 What can I do?

Axional Studio HTML Pages are mainly focused on the generation of HTML for presenting database information with a custom design, created ad hoc for those situations that Axional Studio Objects are too much restrictive.

  • Create highly user friendly applications for users not familiarized with Axional Studio. Such us polls, news reader, etc.
  • Create awesome graphical applications for the board of directors. Such us interactive data visualizations, dashboards, etc.
  • Create complex web applications. Such us e-commerce, 3D graphics, etc.

1.3 What do I need?

In first place, Axional Studio HTML Pages requires the basic Axional Studio infrastructure, which includes:

  • Axional Studio Server, properly set up.
  • Dictionary database
  • A target database
The previous configuration is explained in detail under the Axional Studio/Setup block.

In second place, Axional Studio HTML Pages definition involves some other technologies which is supposed to be kwon by programmer before start developing Axional Studio HTML Pages:

  • XSQL Script enables database connection and server-side programming for getting and manipulating information from the source DBMS.
  • Apache FreeMarker ( FTL) is a template engine to generate output HTML.
  • Hypertext Markup Language ( HTML) is the standard markup language for creating web pages.
  • Cascading Style Sheets ( CSS) is a style sheet language used for describing the presentation of an HTML document.
  • Javascript which is an scripting language primarily used to enhance the Web and user interaction.

2 Arquitecture

2.1 Architecture pattern

Axional Studio HTML Pages uses a Model View Controller (MVC) pattern. The objective of this pattern is to uncoupling the graphical interface from the rest of the system. In order to achieve this, the application is split in three components:

  • Model: encapsulates the state of the system and implements the business logic. It is represented by the target database definition and the stored procedures.
  • Views: display the information to the user and collect information from it to send it to the controllers. It is basically represented by the FTL Templates (wic_freemarker_templates) and resources (wic_clob_resources, wic_blob_resources).
  • Controller: handles the connection between user actions and system events and decide which views are shown to the user. It is mainly represented by XSQL Pages (wic_html_pages) and other dictionary stuff (XSQL Scripts, Application menu, Roles, ...).

2.2 Enviroment map

The following conceptual map tries to show the relations between all the actors involved in XSQL Pages, from the definition to the final use. The actors include the people, machines, entities and technologies involved.

Loading...

2.3 Dictionary tables

2.3.1 HTML Page

[SOAPException: faultCode=SOAP-ENV:Server; msg=Exception from service object: No row bean PK([rep_code])([wic_html_page]) for table 'wic_jrep_object' in database '[wic]'] at deister.axional.docs.xsl.CMSSOAPClient.__doSOAPCall(CMSSOAPClient.java:113) at deister.axional.docs.xsl.CMSSOAPClient.__doSOAPCall(CMSSOAPClient.java:94) at deister.axional.docs.xsl.CMSSOAPClient.getDictionaryObjectData(CMSSOAPClient.java:207) at jdk.internal.reflect.GeneratedMethodAccessor1131.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at org.apache.xalan.extensions.ExtensionHandlerJavaPackage.callFunction(ExtensionHandlerJavaPackage.java:300) at org.apache.xalan.extensions.ExtensionHandlerJavaPackage.callFunction(ExtensionHandlerJavaPackage.java:440) at org.apache.xalan.extensions.ExtensionsTable.extFunction(ExtensionsTable.java:222) at org.apache.xalan.transformer.TransformerImpl.extFunction(TransformerImpl.java:475) at org.apache.xpath.functions.FuncExtFunction.execute(FuncExtFunction.java:208) at org.apache.xpath.objects.XRTreeFragSelectWrapper.execute(XRTreeFragSelectWrapper.java:69) at org.apache.xpath.XPath.execute(XPath.java:337) at org.apache.xalan.templates.ElemVariable.getValue(ElemVariable.java:280) at org.apache.xalan.templates.ElemVariable.execute(ElemVariable.java:248) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemTemplate.execute(ElemTemplate.java:394) at org.apache.xalan.templates.ElemCallTemplate.execute(ElemCallTemplate.java:248) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemChoose.execute(ElemChoose.java:128) at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemChoose.execute(ElemChoose.java:128) at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemChoose.execute(ElemChoose.java:128) at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemChoose.execute(ElemChoose.java:128) at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376) at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(TransformerImpl.java:2272) at org.apache.xalan.transformer.TransformerImpl.transformNode(TransformerImpl.java:1358) at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:711) at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1275) at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1253) at deister.axional.server.lang.xsl.XSLProcessor.__execute(XSLProcessor.java:866) at deister.axional.server.lang.xsl.XSLProcessor$4.call(XSLProcessor.java:702) at deister.axional.server.lang.xsl.XSLProcessor$4.call(XSLProcessor.java:694) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) at java.base/java.lang.Thread.run(Thread.java:832)
[SOAPException: faultCode=SOAP-ENV:Server; msg=Exception from service object: null] at deister.axional.docs.xsl.CMSSOAPClient.__doSOAPCall(CMSSOAPClient.java:113) at deister.axional.docs.xsl.CMSSOAPClient.__doSOAPCall(CMSSOAPClient.java:94) at deister.axional.docs.xsl.CMSSOAPClient.getDictionaryObjectData(CMSSOAPClient.java:207) at jdk.internal.reflect.GeneratedMethodAccessor1131.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at org.apache.xalan.extensions.ExtensionHandlerJavaPackage.callFunction(ExtensionHandlerJavaPackage.java:300) at org.apache.xalan.extensions.ExtensionHandlerJavaPackage.callFunction(ExtensionHandlerJavaPackage.java:440) at org.apache.xalan.extensions.ExtensionsTable.extFunction(ExtensionsTable.java:222) at org.apache.xalan.transformer.TransformerImpl.extFunction(TransformerImpl.java:475) at org.apache.xpath.functions.FuncExtFunction.execute(FuncExtFunction.java:208) at org.apache.xpath.objects.XRTreeFragSelectWrapper.execute(XRTreeFragSelectWrapper.java:69) at org.apache.xpath.XPath.execute(XPath.java:337) at org.apache.xalan.templates.ElemVariable.getValue(ElemVariable.java:280) at org.apache.xalan.templates.ElemVariable.execute(ElemVariable.java:248) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemTemplate.execute(ElemTemplate.java:394) at org.apache.xalan.templates.ElemCallTemplate.execute(ElemCallTemplate.java:248) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemChoose.execute(ElemChoose.java:128) at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemChoose.execute(ElemChoose.java:128) at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemChoose.execute(ElemChoose.java:128) at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemChoose.execute(ElemChoose.java:128) at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.templates.ElemLiteralResult.execute(ElemLiteralResult.java:1376) at org.apache.xalan.templates.ElemApplyTemplates.transformSelectedNodes(ElemApplyTemplates.java:395) at org.apache.xalan.templates.ElemApplyTemplates.execute(ElemApplyTemplates.java:178) at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(TransformerImpl.java:2402) at org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(TransformerImpl.java:2272) at org.apache.xalan.transformer.TransformerImpl.transformNode(TransformerImpl.java:1358) at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:711) at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1275) at org.apache.xalan.transformer.TransformerImpl.transform(TransformerImpl.java:1253) at deister.axional.server.lang.xsl.XSLProcessor.__execute(XSLProcessor.java:866) at deister.axional.server.lang.xsl.XSLProcessor$4.call(XSLProcessor.java:702) at deister.axional.server.lang.xsl.XSLProcessor$4.call(XSLProcessor.java:694) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) at java.base/java.lang.Thread.run(Thread.java:832)

2.3.2 FTL template

Menu path:
Resources / Freemarker Templates

You can use wic_freemaker_templates as a Freemarker template container Associated with a database dictionary.

The XSQL language allows you to define online templates as

    
<set name='t1'>
    <freemarker.template>


        FreeMarker Template example: ${message}  
        
        =======================
        
        ===  County List   ====
        
        =======================
        
        <#list countries as country>
        
            ${country_index + 1}. ${country}
        
        </#list>

    </freemarker.template>
</set>

Alternatively, you can store the code of a template in this table and get us Content by:

    <set name='t1'>
        <freemarker.template.get name="template1.ftl' />
    </set>

The templates can access the variables of the execution instance in XSQL. Using the above template, you can process it using.

<set name='message'><string>Hello world!</string></set>

<set name='countries'>

<array>

<string>India</string>

<string>United States</string>

<string>Germany</string>

<string>France</string>

</array>

</set>

 

<println>

<freemarker.template.process>

   <t1/>

</freemarker.template.process>

</println>    

The result will be

FreeMarker Template example: Hello world! 
=======================
=== County List ====
=======================
1. India
2. United States
3. Germany
4. France

Full code:

<xsql-script name='freamarker_template'>
<body>
<set name='t1'>
<freemarker.template>

FreeMarker Template example: ${message} 
=======================
=== County List ====
=======================
<#list countries as country>
${country_index + 1}. ${country}
</#list> 
]]>
</freemarker.template>
</set>

<set name='message'><string>Hello world!</string></set>
<set name='countries'>
<array>
<string>India</string>
<string>United States</string>
<string>Germany</string>
<string>France</string>
</array>
</set>

<println>
<freemarker.template.process>
<t1/>
</freemarker.template.process>
</println>
</body>
</xsql-script>    

The FreeMarker Template Language (FTL) form allow inserting a modifying FTL instances. Apache FreeMarker is a template engine: a Java library to generate text output (HTML web pages, e-mails, configuration files, source code, etc.) based on templates and changing data. Templates are written in FTL, which is a simple, specialized language (not a full-blown programming language like PHP). You meant to prepare the data to display in a real programming language, like issue database queries and do business calculations, and then the template displays that already prepared data. In the template you are focusing on how to present the data, and outside the template you are focusing on what data to present.

Within an Axional Studio context, freemarker template instances can be used via an XSQL and the XSQL package freemarker.

In order to deeper information about what Freemaker is, how it works and it's syntax, visit the Free Marker webite.

wic_freemarker_templates
Label Description
Name Template name, which identifies the template univocally
Template code

Template code field contains FTL code to be used in the system through the XSQL package freemaker.

Appart from the functions and variables available by the freemaker syntax, it exists certains usefull constants ready to be used by freemaker templates in an Axional Studio context:

  • ${ runtime["user"]! }. Returns the session user code.
  • ${ runtime["dbms"]! }. Returns the current database code.
  • ${ runtime["import_library"]! }. Returns the HTML code for importing the HTMLPAGE package.
  • ${ runtime["clob_resource"]! }. Returns the prefix URL to access a text resource defined by the wic_clob_resources.
  • ${ runtime["blob_resource"]! }. Returns the prefix URL to access a text resource defined by the wic_blob_resources.
  • ${ runtime["html_page"]! }. Returns the prefix URL for an HTML Page..

In order to get a complete information about freemaker syntax and functionalities visit the Free Marker webite.



Created by

  • Default: USER
Date created

  • Default: CURRENT
Modified by

  • Default: USER
Date updated

  • Default: CURRENT

2.3.3 Text resources

Menu path:
Resources / Text resources
wic_clob_resources
Label Description
Name Resource name. The resource path will depend on this name.
Data Resource text data

Type Resource type which determines if plain text, css, javascript, etc.

  • Values:
    • application/javascript: Javascript.
    • text/css: CSS.
    • text/plain: Plain text.
Size Resource size in bytes

  • Default: size(resource_text)
Created by

  • Default: USER
Date created

  • Default: CURRENT
Modified by

  • Default: USER
Date updated

  • Default: CURRENT

2.3.4 Binary resources

Menu path:
Resources / Binary resources
wic_blob_resources
Label Description
Name Resource name. The resource path will depend on this name.
Data Resource binary data
Type Resource type which determines if is an image, a font, etc.

  • Default: type(resource_byte)
Size Resource size in bytes

  • Default: size(resource_byte)
Created by

  • Default: USER
Date created

  • Default: CURRENT
Modified by

  • Default: USER
Date updated

  • Default: CURRENT

3 Implementation

The following sections show how to create and execute Axional Studio HTML Pages step by step. It starts by simple pages, in the first section, and keep on explaining more complex situations in further sections.

3.1 Simple HTML Page

3.1.1 Page definition

Open your dictionary application and create an HTML Page named simplepage with the following content at Script HTML field:

Example

Simple HTML Page implementation

Copy
<xsql-script>
    <body>
        <return><![CDATA[<!DOCTYPE HTML>
<html>
    <body>
          Hi, I'm a Axional Studio HTML Page!
    </body>
</html>]]></return>
    </body>
</xsql-script>

3.1.2 Add page to menu

Still at the dictonary application create a menu entry indicating service HTML Page, URL simplepage and description "My First Page".

3.1.3 Page execution

Now, go to the target database application and open the item "My First Page" from the application tree menu. As a result, it should appear a simple page:

Example

Hi, I'm a Axional Studio HTML Page!

3.2 Use of templates

The use of templates have the following purposes:

  • Separate the graphical implementation from the rest of the system. Templates would stand for the Views in the MVC pattern.
  • Code reuse, due to a view could be used in more than one HTML Page.
  • Code specialization, by preventing the use of HTML code within the XSQL Script.

3.2.1 Simple template

Template definition

Open your dictionary application and create an FTL template named simpleftl with the following content:

Example

Simple FTL Template

Copy
<!DOCTYPE html>
<html>
    <body>
          Hi, I'm a Freemaker Template!
    </body>
</html>

Apply template

Now, create an HTML Page named as pageftl with the following content at Script HTML field:

Example

FTL applied to an HTML Page

Copy
<xsql-script>
    <body>
        <return>
            <freemarker.template.process>
                <freemarker.template.get name='simpleftl' />
            </freemarker.template.process>
        </return>
    </body>
</xsql-script>

Result

It should return an HTML Page like:

Example

Hi, I'm a Freemaker Template!

3.2.2 Template with variables

Template Definition

Open your dictionary application and create an FTL template named ftlwithvars with the following content:

Example

FTL Template with variables

Copy
<!DOCTYPE html>
<html>
    <body>
          Hi, I'm ${ message }!
    </body>
</html>

Apply template

Now, create a new HTML Page named as pageftlwithvars with the following content at Script HTML field:

Example

FTL applied to an HTML Page

Copy
<xsql-script>
    <body>
        <set name='message'>John Smith</set>
        
        <return>
            <freemarker.template.process>
                <freemarker.template.get name='ftlwithvars' />
            </freemarker.template.process>
        </return>
    </body>
</xsql-script>

Result

It should return an HTML Page like:

Example

Hi, I'm John Smith!

3.2.3 Template include

As it is said before, templates enables code reuse, which is mainly achivied by including predefined templates in other templates.

Include Template Definition

Create an FTL template named footerftl with the following content:

Example

FTL Template which contents a reusable content to be placed as footer in multiple pages

Copy
<div>(C) Copyright 1997, 2018 DEISTER, S.A.</div>

Template Definition

Create another FTL template named includeftl with the following content:

Example

FTL Template with variables

Copy
<!DOCTYPE html>
<html>
<body>
    Hi, I'm a Freemaker Template including footer!
    <#include "footerftl">
</body>
</html>

Apply template

Create an HTML Page defined as includepage with the following content at Script HTML field:

Example

FTL applied to an HTML Page

Copy
<xsql-script>
    <body>
        <return>
            <freemarker.template.process>
                <freemarker.template.get name='includeftl' />
            </freemarker.template.process>
        </return>
    </body>
</xsql-script>

Result

It should return an HTML Page like:

Example

Hi, I'm a Freemaker Template including footer!

(C) Copyright 1997, 2018 DEISTER, S.A.

3.3 Import resources

Previous samples were very simple but an HTML Page can be as complex as the programmer wants. In order to develop more complex applications it is necessary to include some resources such as images, stylesheets, external Javascript libraries, etc.

Concerning to this, Axional Studio enables two different entities for defining text or binary resources. For this purpose FreeMaker processor enables the constants: ${ runtime["clob_resource"]! } and ${ runtime["blob_resource"]! }.

3.3.1 Import text resource

Text resources mainly include Javascript and Cascading Style Sheets ( CSS). These text resources are store in the wic_clob_resources table.

Resource Definition

Create a text resource named mystylesheet.css with the following content:

Example

Sample of an style sheet text resource

Copy
.alert {
    color: red;
}

Include resource

Create an FTL template named textresourceftl with the following content:

Example

FTL Template including text resource

Copy
<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" type="text/css" href="${ runtime["clob_resource"]! }/mystylesheet.css">
    </head>
    <body>
          Hi, I'm <span class='alert'>${ message }</span>!
    </body>
</html>

Result

An HTML Page processing the FTL template textresourceftl should return an HTML Page like:

Example

Hi, I'm John Smith!

3.3.2 Import binary resource

Binary resource could reference to any media type such as images, videos, audio, etc. or other web oriented files such as fonts. These binary resource are stored in the wic_blob_resources table.

Resource Definition

Create a binary resource named iceland.png.

Include resource

Create an FTL template named binaryresourceftl with the following content:

Example

FTL Template including text resource

Copy
<!DOCTYPE html>
<html>
    <body>
          <img src="${ runtime["blob_resource"]! }/iceland.png">
    </body>
</html>

Result

An HTML Page processing the FTL template binaryresourceftl should return an HTML Page like:

3.4 Database access

Communication with the server allows bidirectional communication between the server and client HTML Page. On one hand, XSQL Pages can gather some information from the user and post it to server. On the other hand, XSQL Pages can request some information from the server at any time and show it to the user.

This communication is achieved by performing HTTP Requests from the HTML Page which are processed by the corresponding GET, POST, PUT or DELETE XSQL Script defined in the HTML Page. HTTP Requests can be performed using classic form submitting, which involves synchronous communication, or Ajax techniques to create asynchronous Web applications. The following table summarizes the accepted methods and it's use:

Method Operation Return Sinchronous Asinchronous HTMLPAGE lib
GET Read HTML    
GET Read JSON     HTMLPAGE.executeGet
POST Create HTML/JSON     HTMLPAGE.executePOST
PUT Update/replace JSON     HTMLPAGE.executePUT
DELETE Delete JSON     HTMLPAGE.executeDELETE

3.4.1 Get plain information

The first situation when facing Axional Studio HTML Pages is how can I build an HTML Page to display the information from my database. The easiest way is using FTL templates with variables, as we have seen before, and take advantage of the XSQL Script for accessing the database.

Template Definition

Open your dictionary application and create an FTL template named ftlwithvars with the following content:

Example

FTL Template with variables

Copy
<!DOCTYPE html>
<html>
    <body>
          Hi, I'm ${ message }!
    </body>
</html>

Apply template

Now, create a new HTML Page named as pagefromdbms with the following content at Script HTML field:

Example

FTL applied to an HTML Page

Copy
<xsql-script>
    <body>
        <select first='1'>
            <columns>name message</columns>
            <from table='person' />
        </select>

        <return>
            <freemarker.template.process>
                <freemarker.template.get name='ftlwithvars' />
            </freemarker.template.process>
        </return>
    </body>
</xsql-script>

Result

It should return an HTML Page like:

Example

Hi, I'm Paul!

3.4.2 Iterate table

The current sample is focused on display list of information. It is also achieved by using the FTL syntax and XSQL Script for accessing the database.

Template Definition

Open your dictionary application and create an FTL template named ftlresultset with the following content:

Example

FTL Template with variables

Copy
<!DOCTYPE html>
<html>
    <body>
        <ul>
        <#list v_person.getRows() as row>
            <li>Hi, I'm ${ row["message"] }!</li>
        </#list>
        </ul>
    </body>
</html>

Apply template

Now, create a new HTML Page named as pagelistfromdbms with the following content at Script HTML field:

Example

FTL applied to an HTML Page

Copy
<xsql-script>
    <body>
        <vtable name='v_person'>
            <select>
                <columns>name message</columns>
                <from table='person' />
            </select>
        </vtable>

        <return>
            <freemarker.template.process>
                <freemarker.template.get name='ftlresultset' />
            </freemarker.template.process>
        </return>
    </body>
</xsql-script>

Result

It should return an HTML Page like:

Example
  • Hi, I'm Paul!
  • Hi, I'm Anne!

3.4.3 Form submit

Let's see an example of an HTML Page which present's a form to the user which will be send to server and stored into a table. Broadly, the main execution flow for the current samples is the following:

  1. The browser asks to the server for the page defined by the URL.
  2. The server executes the HTML Script defined in the HTML Page and returns an HTML.
  3. The browser displays the received HTML to the user, which contains a poll with some questions and a "Send" button.
  4. The user answers the questions and clicks the "Send" button.
  5. The browser submits the form and send it to the server via a POST HTTP Request.
  6. The server executes the POST Script defined in the HTML Page, which collects the user answer for storing them into the database and returns another HTML.
  7. The browser displays the received HTML to the user, which contains a succeed message and a "Back" button.
  8. The user reads the message and click the "Back" button.
  9. Returns to the point 1.

The sections bellow explains how this sample must be defined using the Axional Studio HTML Pages configuration.

Form template

Create an FTL template named poll_form with the following content:

Example

FTL Template introducing a poll

Copy
<!DOCTYPE html>
<html>
    <head>
        <style>
            label { display: block; }
        </style>
    </head>
    <body>
        <form method="POST">
            <p>
                Thank you for using our services!<br>
                Please, take a moment for answering a few questions about the
                service you have received in order to improve it for future uses.
            </p>
            
            <label>Are you satisfied with the service elapsed time?</label>
            <input type="radio" name='question1' value='0'>No</input>
            <input type="radio" name='question1' value='1'>Yes</input><br>
            
            <label>The tone of the person who attended you was friendly?</label>
            <input type="radio" name='question2' value='0'>No</input>
            <input type="radio" name='question2' value='1'>Yes</input><br>
            
            <label>The person who attended you provided correct information?</label>
            <input type="radio" name='question3' value='0'>No</input>
            <input type="radio" name='question3' value='1'>Yes</input><br>
            
            <label>Would you recomend this service to any familiar or friend?</label>
            <input type="radio" name='question4' value='0'>No</input>
            <input type="radio" name='question4' value='1'>Yes</input><br>
            
            <label>Please, introduce any comment you consider relvant regarding to the service:</label>
            <textarea name='question5' rows='3' cols='50'></textarea><br/>
            
            <button type="submit">Send</button>
        </form>
    </body>
</html>

Success template

Create another FTL template named poll_succeed with the following content:

Example

FTL Template showing a message when a poll is completed

Copy
<!DOCTYPE html>
<html>
    <body>
        <p>
            Many thanks for you time!
            You opinion is very valuable for us.
        </p>

        <button type="button" onclick="window.location.assign('${ runtime["html_page"]! }/form_submit');">Back</button>
    </body>
</html>

HTML Page definition

Now, create an HTML page named poll_request. It contains an HTML Script for displaying the initial HTML and an POST Script for handling the form submit.

Script HTML
Example

HTML Script which returns HTML code for displaying the poll.

Copy
<xsql-script>
    <body>
        <return>
            <freemarker.template.process>
                <freemarker.template.get name='poll_form' />
            </freemarker.template.process>
        </return>
    </body>
</xsql-script>
POST Script
Example

POST Script which handles POST request and returns HTML code with the success message.

Copy
<xsql-script>
    <body>
        <set name='quest_user'><system.user.getCode /></set>
        <set name='quest_question1'><http.request.getParameter name='question1' /></set>
        <set name='quest_question1'><http.request.getParameter name='question1' /></set>
        <set name='quest_question2'><http.request.getParameter name='question2' /></set>
        <set name='quest_question3'><http.request.getParameter name='question3' /></set>
        <set name='quest_question4'><http.request.getParameter name='question4' /></set>
        <set name='quest_question5'><http.request.getParameter name='question5' /></set>
        
        <!-- <insert table='poll_answer' prefix='quest_' /> -->
        
        <return>
            <freemarker.template.process>
                <freemarker.template.get name='poll_succeed' />
            </freemarker.template.process>
        </return>
    </body>
</xsql-script>

3.4.4 Asynchronous query

It is also interesting how to implement an asynchronous communication; that is, an HTML Page which initially displays static content and change its content due to an user interaction, without reloading the page. Broadly, the main execution flow for the current samples is the following:

  1. The browser asks to the server for the page defined by the URL.
  2. The server executes the HTML Script defined in the HTML Page and returns an HTML.
  3. The browser displays the received HTML to the user, which basically contains an input text field with the label "Enter search pattern".
  4. The user introduces some pattern in the input field.
  5. The browser sends an GET HTTP Request with the pattern introduced by the user as param.
  6. The server executes the GET Script defined in the HTML Page, which executes an SQL query considering the input pattern and returns the resultSet.
  7. The browser processes the received resultSet as JSON using Javascript to show the result of the search to the user.
  8. Returns to the point 4.

The sections bellow explains how this sample must be defined using the Axional Studio HTML Pages configuration.

Template definition

Create an FTL template named async_query with the following content:

Example

FTL Template introducing a poll

Copy
<!DOCTYPE html>
<html>
    <head>
        <!-- html_user.js library -->
        ${ runtime["import_library"] }
        
        <script>
            function executeSearch(filter) {
                HTMLPAGE.executeGET(
                    { q: filter },
                    // Success function
                    function(response) {
                        var rows = HTMLPAGE.convertResultSetResponse(response);
                        var list = document.getElementById('search_result');
                        
                        var listContent = '';
                        
                        for (var irow = 0; irow < rows.length; irow++) {
                            listContent += '<li>' + rows[irow].product_name + '</li>';
                        }
                        
                        list.innerHTML = listContent;
                    }
                );
            }
        </script>
    </head>
    <body>
        <input type="text" name='q' size='100' placeholder='Enter search pattern...' oninput='executeSearch(this.value)'>
        <ul id='search_result'>
        </ul>
    </body>
</html>

HTML Page definition

Now, create an HTML page named async_query. It contains an HTML Script for displaying the initial HTML and an GET Script for handling the asynchronous query.

Script HTML
Example

HTML Script which returns the initial HTML code..

Copy
<xsql-script>
    <body>
        <return>
            <freemarker.template.process>
                <freemarker.template.get name='async_query' />
            </freemarker.template.process>
        </return>
    </body>
</xsql-script>
GET Script
Example

GET Script which handles GET request and returns a resultset with the result of executing the query.

Copy
<xsql-script>
    <body>
        <set name='m_filter'><http.request.getParameter name='q' /></set>

        <return>
            <sql.toResultSet>
                <select first='20'>
                    <columns>
                        product_name
                    </columns>
                    <from table='product' />
                    <where>
                        <length>'${m_filter}'</length> > 0 AND
                        UPPER(product_name) LIKE UPPER('%${m_filter}%')
                    </where>
                </select>
            </sql.toResultSet>
        </return>
    </body>
</xsql-script>

4 Samples

Current section shows some useful examples with the most common uses of Axional Studio HTML Pages. However, this technology is totally open and highly expandable, so feel free for using your own implementation and not be limited by this samples.

4.1 Use different FTL on the same page

It could be interesting to have a web page which completely changes its content with the user interaction. This implementation could be achieved by using a single HTML Page where the POST Script dispatches different FTL depending on the state of the page. For example, imagine a page showing poll divided in blocks of questions; the main execution flow for the current samples is the following:

  1. The browser asks to the server for the page defined by the URL.
  2. The server executes the HTML Script defined in the HTML Page and returns an HTML.
  3. The browser displays the received HTML to the user, which contains an introduction to the poll and a "Start" button.
  4. The user reads the introduction and clicks the "Start" button.
  5. The browser submits a form containing a flag indicating that is the introduction page and send it to the server via a POST HTTP Request.
  6. The server executes the POST Script defined in the HTML Page, returns an HTML corresponding to the first block of questions.
  7. The browser displays the received HTML to the user, which contains a poll with some questions and a "Send" button.
  8. The user answers the questions and clicks the "Send" button.
  9. The browser submits the form and send it to the server via a POST HTTP Request.
  10. The server executes the POST Script defined in the HTML Page, stores the answers into the database and returns an HTML corresponding to the second block of questions.
  11. The browser displays the received HTML to the user, which contains a poll with some other questions and a "Send" button.
  12. The user answers the questions and clicks the "Send" button.
  13. The browser submits the form and send it to the server via a POST HTTP Request.
  14. The server executes the POST Script defined in the HTML Page, stores the answers into the database and returns an HTML with a concluding message.
  15. The browser displays the received HTML to the user, which contains a succeed message and a "Back" button.
  16. The user reads the message and click the "Back" button.
  17. Returns to the point 1.

Notice that the key of this implementation recalls on the POST Script which executes different actions and dispatches one or other HTML depending on the POST params.

The sections bellow explains how this sample must be defined using the Axional Studio HTML Pages configuration.

4.1.1 Introduction template

Create an FTL template named poll_parts_init with the following content:

Example

FTL Template introducing the poll

Copy
<!DOCTYPE html>
<html>
    <body>
        <form method="POST">
            <p>
                Thank you for using our services!<br>
                Please, take a moment for answering a few questions about the
                service you have received in order to improve it for future uses.
            </p>
            <input type="hidden" name='part' value='0'>
            <button type="submit">Start</button>
        </form>
    </body>
</html>

4.1.2 First block of questions template

Create an FTL template named poll_parts_part1 with the following content:

Example

FTL Template containing the first block of question

Copy
<!DOCTYPE html>
<html>
    <head>
        <style>
            label { display: block; }
        </style>
    </head>
    <body>
        <form method="POST">
            <h1>Service block</h1>
            
            <label>Are you satisfied with the service elapsed time?</label>
            <input type="radio" name='question1' value='0'>No</input>
            <input type="radio" name='question1' value='1'>Yes</input><br>
            
            <label>The tone of the person who attended you was friendly?</label>
            <input type="radio" name='question2' value='0'>No</input>
            <input type="radio" name='question2' value='1'>Yes</input><br>
            
            <label>The person who attended you provided correct information?</label>
            <input type="radio" name='question3' value='0'>No</input>
            <input type="radio" name='question3' value='1'>Yes</input><br>
            
            <label>Would you recomend this service to any familiar or friend?</label>
            <input type="radio" name='question4' value='0'>No</input>
            <input type="radio" name='question4' value='1'>Yes</input><br>
            
            <input type="hidden" name='part' value='1'>
            
            <button type="submit">Send</button>
        </form>
    </body>
</html>

4.1.3 Second block of questions template

Create an FTL template named poll_parts_part1 with the following content:

Example

FTL Template containing the second block of question

Copy
<!DOCTYPE html>
<html>
    <head>
        <style>
            label { display: block; }
        </style>
    </head>
    <body>
        <form method="POST">
            <h1>
                Personal block
            </h1>
            
            <label>Does the service provided you a solution for your issue?</label>
            <input type="radio" name='question5' value='0'>No</input>
            <input type="radio" name='question5' value='1'>Yes</input><br>
            
            <label>Are you happy with the service?</label>
            <input type="radio" name='question6' value='0'>No</input>
            <input type="radio" name='question6' value='1'>Yes</input><br>
            
            <label>Will you user the service again?</label>
            <input type="radio" name='question7' value='0'>No</input>
            <input type="radio" name='question7' value='1'>Yes</input><br>

            <label>Please, fell freee to introduce any comment you consider relevant regarding to the service:</label>
            <textarea name='question8' rows='3' cols='50'></textarea><br/>
            
            <input type="hidden" name='part' value='2'>
            
            <button type="submit">Send</button>
        </form>
    </body>
</html>

4.1.4 Conclusion template

Create another FTL template named poll_parts_end with the following content:

Example

FTL Template showing a message when a poll is completed

Copy
<!DOCTYPE html>
<html>
    <body>
        <p>
            Many thanks for you time!
            You opinion is very valuable for us.
        </p>

        <button type="button" onclick="window.location.assign('${ runtime["html_page"]! }/poll_parts');">Back</button>
    </body>
</html>

4.1.5 HTML Page definition

Now, create an HTML page named poll_parts. It contain an HTML Script for displaying the initial HTML and an POST Script for handling the form submit.

Script HTML

Example

HTML Script which returns HTML code for displaying the poll.

Copy
<xsql-script>
    <body>
        <!-- Close pending polls -->
        <update table='poll_parts'>
            <column name='poll_end'><date.current /></column>
            <where>
                poll_user = <system.user.getCode /> AND
                poll_end IS NULL
            </where>
        </update>
        
        <return>
            <freemarker.template.process>
                <freemarker.template.get name='poll_parts_init' />
            </freemarker.template.process>
        </return>
    </body>
</xsql-script>

POST Script

Example

POST Script which handles POST request and returns the proper HTML code depending on the POST params.

Copy
<xsql-script>
    <body>
        <set name='poll_part'><http.request.getParameter name='part' /></set>
        <null name='ftlname' />
        
        <switch name='poll_part'>
            <case value='0'>
                <set name='ftlname'>poll_parts_part1</set>

                <insert table='poll_parts'>
                    <column name='poll_user'><system.user.getCode /></column>
                    <column name='poll_begin'><date.current /></column>
                </insert>
            </case>
            <case value='1'>
                <set name='ftlname'>poll_parts_part2</set>
                
                <update table='poll_parts'>
                    <column name='poll_q1'><http.request.getParameter name='question1' /></column>
                    <column name='poll_q2'><http.request.getParameter name='question2' /></column>
                    <column name='poll_q3'><http.request.getParameter name='question3' /></column>
                    <column name='poll_q4'><http.request.getParameter name='question4' /></column>
                    <where>
                        poll_user = <system.user.getCode /> AND
                        poll_end IS NULL
                    </where>
                </update>
            </case>
            <case value='2'>
                <set name='ftlname'>poll_parts_end</set>
                
                <update table='poll_parts'>
                    <column name='poll_q5'><http.request.getParameter name='question5' /></column>
                    <column name='poll_q6'><http.request.getParameter name='question6' /></column>
                    <column name='poll_q7'><http.request.getParameter name='question7' /></column>
                    <column name='poll_q8'><http.request.getParameter name='question8' /></column>
                    <column name='poll_end'><date.current /></column>
                    <where>
                        poll_user = <system.user.getCode /> AND
                        poll_end IS NULL
                    </where>
                </update>
            </case>
        </switch>

        <return>
            <freemarker.template.process>
                <freemarker.template.get name='${ftlname}' />
            </freemarker.template.process>
        </return>
    </body>
</xsql-script>

5 Annex

5.1 FTL runtime constants

Apart from the functions and variables provided by freemaker syntax, it exists certain useful constants ready to be used by freemaker templates in an Axional Studio context:

  • ${ runtime["user"]! }. Returns the session user code.
  • ${ runtime["dbms"]! }. Returns the current database code.
  • ${ runtime["import_library"]! }. Returns the HTML code for importing the HTMLPAGE package.
  • ${ runtime["clob_resource"]! }. Returns the prefix URL to access a text resource defined by the wic_clob_resources.
  • ${ runtime["blob_resource"]! }. Returns the prefix URL to access a text resource defined by the wic_blob_resources.
  • ${ runtime["html_page"]! }. Returns the prefix URL for an HTML Page.

5.2 XSQL Tags

  • The http.request XSQL Script package is very useful for collecting the HTTP paramers from the defined Scripts used in Axional Studio HTML Pages.
  • The freemarker.template XSQL Script package is very useful for parsing FTL templates and generating HTML for the page.

5.3 HTMLPAGE Javascript library

Axional Studio HTML Pages are independent from the rest of the application libraries, and the programmer could implement their own libraries for handling Ajax connections, websockets, etc. However, we offer the useful library HTMLPAGE with a few set of functions in order to ease basic funcionalities.

Function Params Return Description
convertResultSetResponse
  • response. JSON Object standing for a ResultSet returned from an HTML Page HTTP request.
Array of rows. Converts the JSON Object standing for a ResultSet got from Axional Studio Server into an array of objects where the keys of each rows corresponds to column names.
executeDELETE
  • params. JSON Object with params to send to the server.
  • sucess. Function executed if the HTTP Request success. It receives the response JSON.
  • error. Function executed if the HTTP Request fails. It receives the error message and the response JSON.
  • complete. Function executed after the HTTP Request responses, even if it success or not.
  • scope. Scope for the success, error and complete functions.
Executes an asynchronous HTTP Request via the DELETE method, which cause the execution of the DELETE Script from the HTML Page.
executeGET
  • params. JSON Object with params to send to the server.
  • success. Function executed if the HTTP Request success. It receives the response JSON.
  • error. Function executed if the HTTP Request fails. It receives the error message and the response JSON.
  • complete. Function executed after the HTTP Request responses, even if it success or not.
  • scope. Scope for the success, error and complete functions.
Executes an asynchronous HTTP Request via the GET method, which cause the execution of the GET Script from the HTML Page.
executePOST
  • params. JSON Object with params to send to the server.
  • success. Function executed if the HTTP Request success. It receives the response JSON.
  • error. Function executed if the HTTP Request fails. It receives the error message and the response JSON.
  • complete. Function executed after the HTTP Request responses, even if it success or not.
  • scope. Scope for the success, error and complete functions.
Executes an asynchronous HTTP Request via the POST method, which cause the execution of the POST Script from the HTML Page.
executePUT
  • params. JSON Object with params to send to the server.
  • success. Function executed if the HTTP Request success. It receives the response JSON.
  • error. Function executed if the HTTP Request fails. It receives the error message and the response JSON.
  • complete. Function executed after the HTTP Request responses, even if it success or not.
  • scope. Scope for the success, error and complete functions.
Executes an asynchronous HTTP Request via the PUT method, which cause the execution of the PUT Script from the HTML Page.

5.3.1 Include URLs

In order to have access to HTMLPAGE Javascript package HTML libraries must be include on the FTL.

Copy
<!-- html_user.js library -->
${ runtime["import_library"] }
Example

FTL Template including necessary libraries

Copy
<!DOCTYPE html>
<html>
    <head>
        <!-- html_user.js library -->
        ${ runtime["import_library"] }
        
        <script>
            function executeSearch(filter) {
                HTMLPAGE.executeGET(
                    ...
                );
            }
        </script>
    </head>
    <body>
        ...
    </body>
</html>