Cloud Server

Q:

Is there a way to log the detailed http activity on the Lianja cloud server?

I’m in the process of writing and testing a Lianja authentication module in Angular 2 and I’m having problems getting access.

I have been able to use the Login() in LianjaCloudDataServer.js to login via a standard html page with no problems however I can’t seem to translate the process into Angular 2.

I format my headers and send using an http get and I get a valid OK response but no auth token is set. I’ve even modified the authenticate.rsp to include the contents of the _SERVER array in the response and it shows the AUTHTYPE, REMOTE_USER and REMOTE_PASSWORD fields have been updated, so the server thinks I’m logged in, but no token is set in the browser.

I’ve done some checking and the http headers I’m sending from Angular 2 appear to be the same as those sent by the LianjaCloudDataServer Login(). The only difference I can see if that there appears to be a query string being appended to the URL from Login() but I can’t seem to track down where that’s coming from.

A:

If you set the HKEY_LOCAL_MACHINE\SOFTWARE\Lianja\Lianja Server\NetServer\DB_WWWDEBUG Registry value to true, you will get firecat_debugXXXX.txt files under \lianja\debug\ reporting server activity.

(On 64 bit this will be HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Lianja\Lia nja Server\Netserver\DB_WWWDEBUG).

Q2:

I’ve worked out my Angular 2 Lianja login problem.

Enabling logging allowed me to see that my Http headers were missing the Accept and X-Requested-With headers.

I added the missing headers, which made my headers look identical to those generated by the LianjaCloudDataService.js Login(), but I was still unable to get authenticated.

Then, pretty much by accident, I cleared my browser cookies and sent my request and, will wonders never cease, it worked.

I did a bit more digging and found that the LianjaCludDataService.js Login() removes browser cookies before attempting to authenticate so, apparently, it was the presence of these cookies preventing me from getting authenticated.


on Windows you can integrate Lianja Cloud Server with IIS using the Lianja ISAPI Extension for IIS.


Q:

my question about individual databases of items…each customer I sell the application to (even if they use a cloud option) will have their databases residing on their own pc?

A:

Yes, individual database (i.e. table of items) of each customer you sell your application to will reside on his PC.
If it is LAN, then database will reside on one PC in that LAN.
In cloud, databases will be all together somewhere (e.g.Amazon Cloud) , but separated as “tenants” – and not aware of each other.

In Lianja folder you will find the table CUSTOMERS.DBF in 3 folders.
C:\lianja\cloudserver\tenants\public\data\southwind\
C:\lianja\data\southwind\
C:\lianja\server\data\southwind\

As you can see, there is the same structure where the database southwind (and the table customers.dbf) is located for development, app center, cloud.
About mapping the drives
https://www.lianja.com/doc/index.php…_Line_Switches
–runtimedatadir
–networkshare

–runtimedir
–tenancy


you can use Lianja Cloud Server to handle OData CRUD operations from other third party UI frameworks if that is a requirement. To use these OData functions on the client (no server side coding required) you should include the following files in your App:

/library/jquery-1.10.2/jquery-1.10.2.min.js
/library/LianjaWebFramework/LianjaCloudDataServices.js

This provides core javascript client side functionality for working with the LIanja Cloud Server. It is not required with Lianja Apps as they have the full framework included.


Q:

We are looking at using Lianja’s OData interface for our non-Lianja web and mobile clients.

Our specification calls for us to secure the interface using web tokens requiring clients to include a valid token in the header of every request which Lianja will have to validate prior to transmitting any data. Does Lianja include any mechanism’s for this type of security ? If not, do you have any suggestions as to how we should address this requirement?

A:

Lianja cloud server requires authentication and it uses a similar technique that you mention using an API KEY that is created as a server side session cookie. Once created on the server the cookie cannot be modified on the client.

We do not enforce this when using odata but we could, so I suggest you submit an enhancement request and we can add a setting for cloud server that requires login authentication before issuing odata calls.

in fact there is a Lianja.login() method in LianjaCloudServices.js already.

Also, I should mention that authentication can be via the Lianja users table or with AD/LDAP.

There is no state maintained on the server.

If you use OData calls you cannot inspect the http headers. OData is a RESTful interface.

If you write your own RESTful API you can do whatever you want at the expense of time and effort.

This has now been implemented in Lianja 3.2.1.

Name: Screen Shot 2017-02-10 at 10.56.44 AM.jpg Views: 34 Size: 61.7 KB

So if you check “Authenticated OData service” all OData RESTful API calls should be authenticated first. The user can be setup in Lianja or AD/LDAP. If the optional APIKEY is specified then no authentication is required but the HTTP headers must contain “lianjaOdataApiKey:yourkey” and your key must match the specified APIKEY.

As I mentioned earlier you need to include jquery and LianjaCloudDataServices.js which has methods for:

Lianja.login()
Lianja.isLoggedIn()
Lianja.logout
Lianja.OData_Create()
Lianja.OData_Read()
Lianja.OData_Update()
Lianja.OData_Delete()
Lianja.evaluate()
Lianja.getUrl()
Lianja.json_encode()
Lianja.json_decode()
Lianja.base64_encode()
Lianja.base64_decode()

and other useful methods.

Q2:

If I were hitting the page from a non-Lianja application, how would I authenticate initially? Is there a way to use User and UserRoles in this scenario?

I am imagining something like the initial oData call from the external app either passing a username and password assuming https or a vpn or a call to a method passing an encrypted username and password where other encryption isn’t in place.

A2:

You need to specify credentials in the HTTP headers and the client needs to be able to handle session cookies. If the client is not a browser it needs to be able to read the HTTP headers sent back by the cloud server and resend the session cookies for each request.

The cloud server does more than check the username and password. It also creates an authentication token as well as determine the roles assigned to the specified user.

These roles are used not only to control permissions in web and mobile apps but also (in 3.4 as stated in the roadmap) provide row level security and column masking.

So you need to go through the proper authentication mechanism.

http or https is the same technique. You just need to read the login() code in LianjaCloudDataServices.js and you will see how to send the authentication username and password. If you are not running in a browser you need to read the raw http response header and send the cookies it contains back on future requests. That’s how browsers work so you just have to look like a browser to the remote Lianja Cloud Server. In other words use the http protocol.

Q:

If you enable an option to require users to login prior to using the OData service, how would the server determine if a request comes from a logged in user?

A:

We create an encrypted session cookie. The details of this are internal and I would not like to explain for security reasons.

Any cookie created on the server and included in the http headers sent back to the client cannot be modified on the client. These are known as session cookies.

We inspect the http headers and check for the encrypted session cookie. It contains information to allow us to determine who the user is and what machine authenticated. We can then verify this authentication for each request made to the server.

I’m testing Beta7 with my server configured as so…
Name: configuration.png Views: 20 Size: 48.7 KB

I’m finding that I am unable to access http:\localhost:8001/login.rsp.
Name: authreq.PNG Views: 20 Size: 14.3 KB

This also appears to be preventing non-local access to the login.rsp as well…
Name: remoteauthreq.PNG Views: 20 Size: 15.3 KB

This might be down to my being confused about how these new settings are meant to work together but, as it currently stands, with this configuration, Lianja clients wouldn’t be able to authenticate if they can’t get to the login page.

ADDENDUM: I’ve now tested the the system with the server configured with Allow unauthenticated local access ENABLED and…
Name: configuration.png Views: 20 Size: 56.8 KB
both local and remote unauthenticated users are allowed to access login.rsp as well as other pages and odata resources. Authenticated users have full access.

ADDENDUM: I’ve now tested the system with the server configured with Allow unauthenticated local access, Authenticate OData requests and Authenticate Page requests all enabled and…
Name: configuration.png Views: 20 Size: 43.5 KB
both local and remote unauthenticated users are allowed to access login.rsp but are prevented from accessing any active pages or OData resources. Authenticated users are allowed full access.

A:

Allow unauthenticated local access should be left checked. It’s only relevant to Lianja SQL server.

The other settings you have screenshots of are working as expected.


Q:

Does the Lianja Cloud Server provides any means of tracking active sessions, active connections, active users etc?

A:

On windows, the Lianja server manager does that and displays the active connections.

Bear in mind though, when using the IIS plugin on Windows, connections may timeout and be kept alive and reused. The IIS plugin creates a bunch of connections when it starts up and allocates these when a connection request is made. If the number of connection requests exceeds the number of available connections new ones are created. Only when connections that are kept alive for a period of time timeout are they destroyed. This provides optimum throughput on a heavily loaded system.


Lianja Cloud will provide integrated Continuous Delivery using Amazon CodePipeline from an Amazon CodeCommit or GitHub git repository.

Amazon CodeCommit

Anyone with an AWS account can get started with AWS CodeCommit for free. Your account gets 5 active users per month for free (within limits), after which you pay $1 per additional active user per month. There are no upfront fees or commitments.

This AWS Free Tier offer for AWS CodeCommit is available to both new and existing AWS customers indefinitely, and does not expire at the end of the standard 12 month Free Tier term.

https://aws.amazon.com/codecommit/

We will provide more information about configuration when Lianja Hosted Cloud is available.

Amazon CodeDeploy

AWS CodeDeploy is a service that automates code deployments to any instance, including Amazon EC2 instances and instances running on-premises. AWS CodeDeploy makes it easier for you to rapidly release new features, helps you avoid downtime during application deployment, and handles the complexity of updating your applications. You can use AWS CodeDeploy to automate software deployments, eliminating the need for error-prone manual operations, and the service scales with your infrastructure so you can easily deploy to one instance or thousands.

One of the things we are also looking at is continuous database schema updates as part of the continuous delivery pipeline.

Amazon CodePipeline

AWS CodePipeline is a continuous integration and continuous delivery service for fast and reliable application and infrastructure updates. CodePipeline builds, tests, and deploys your code every time there is a code change, based on the release process models you define. This enables you to rapidly and reliably deliver features and updates. You can easily build out an end-to-end solution by using our pre-built plugins for popular third-party services like GitHub or integrating your own custom plugins into any stage of your release process. With AWS CodePipeline, you only pay for what you use. There are no upfront fees or long-term commitments.



 

 

 

 

 

Cloud Server

Q:
 I am using the cloud server as I am running everything on my desktop as per a standard install – or do all web apps use the cloud server?
A:
If you install a apass developer the cloud server is also installed on your development machine. Please open the web examples, view as web app then preview. Once you are familiar with these steps proceed to experiment with calling server side JavaScript if that’s your server side scripting kanguage of choice.

Lianja Cloud Server incorporates an embedded database and Lianja SQL Server. If you have Lianja cloud server installed you do not need (and should not) install LuanhaLianja SQL server.

Q;
I have a wedding application (for my son) that guests will be using during the wedding.
I would like them to not have to type in the entire url.

Meaning – to get there now, you need to type in.
Samswedding.online/apps/wedding/index.html

I would like them to only type samswedding.online and have it re-directed.
A:
you can create a QR code for a URL. There are several free sites. Then print the QR code on folding cards, and put them on each table.
you need to obtain a domain from someone like network solutions or setup a CNAME in DNS.
I use easydns.com for my domains and DNS. They have Forward and Stealth options (the latter continues to show the original entered URL).

If you’re using the IIS plug-in then you will have actual rewrite capabilities, of course. http://nicolas.guelpa.me/blog/2015/0…irect-iis.html I haven’t tried a rewrite with the LCS, so let us know if you try it. <s>

Because Lianja uses the .dbo files, a cloud server app can be upgraded on-the-fly.

The Lianja Cloud Server includes the following features/functionality:

— An embedded version of the Lianja database engine
— Lianja SQL Server for ODBC data access
— Lianja OData Server
— Lianja WebSockets Server
— Lianja/VFP Server Pages (.rsp files)
— Lianja/JavaScript Server Pages (.jssp files)
— Handles interaction with Lianja HTML5/JavaScript Web Apps
— Handles interaction with Lianja HTML5/JavaScript PhoneGap Mobile Apps

Dynamic server pages contain HTML5 and directives that tell the Cloud Server how to process the contents of the page.

<%@ Language=VFP %>
or
<%@ Language=JavaScript %>

Let’s see some example code.
<%@ Language=JavaScript %>
<!--
    Lianja/VFP Server pages (.rsp) have the complete Lianja scripting engine embedded in them.
    ---------------------------------------------------------------------------------------------
    When a Lianja/VFP Server Page is executed the following are available to the script
    in addition to the complete VFP compatible cross-platform scripting language 
    implemented in Lianja.
    
    Global associative arrays:
    
         _REQUEST[]
         _SERVER[]
         _ARGS[]
         _GET[]
         _POST[]
         _FILES[]
         _COOKIE[]
         _SESSION[]
    
    Global objects:
    
        Response
            write( text )
            writeFile( filename )
            addCookie(name, value)
            addHeader(name, value)
            clear()
            flush()
            redirect( url )
            authenticate( [message] )
            appendToLog( message )
            include( filename )
            
    Built-in commands/functions:
    
        ? cExpression 
        echo cExpression 
        move_uploaded_file(tofilename, fromfilename)
        die(message)
        include( cExpression )
        object = require( cExpression )
        odata_Create( url, jsondatastring )
        odata_Read( url [, filename] )
        odata_Update( url, jsondatastring )
        odata_Delete( url, jsondatastring )
    
    JavaScript Server Pages are modelled on PHP Server Pages. 
    ---------------------------------------------------------
    When a JavaScript Server Page is executed the following are available to the script
    in addition to the built-in JavaScript functions. These will be familiar to PHP 
    Web developers.
    
    Global associative arrays(objects):
    
        $_REQUEST[]
        $_SERVER[]
        $_ARGS[]
        $_GET[]
        $_POST[]
        $_FILES[]
        $_COOKIE[]
        $_SESSION[]
    
    Global objects:
    
        Lianja.
            execute( vfp_command )
            evaluate( vfp_expression )
            openDatabase( databasename )
                openRecordSet( table_or_sqlselect )
                    moveFirst()
                    moveNext()
                    movePrevious()
                    moveLast()
                    move()
                    moveRelative()
                    moveBookmark()
                    findFirst( condition )
                    findNext( condition )
                    findPrevious( condition )
                    findLast( condition )
                    edit()
                    update()
                    delete()
                    requery()
                    field( name_or_number )
                        .name
                        .type
                        .width
                        .decimals
                        .value
                    close()
                    bof
                    eof
                    found
                    nomatch
                    recno
                    reccount
                    fieldcount
                    index
                    filter
                close()
        Response
            write( text )
            writeFile( filename )
            addCookie(name, value)
            addHeader(name, value)
            clear()
            flush()
            redirect( url )
            authenticate( [message] )
            appendToLog( message )
            include( filename )
    
    Built-in functions:
    
        print( cExpression );
        echo( cExpression );
        move_uploaded_file(tofilename, fromfilename);
        die(message);
        debugout(message);
        include( cExpression );
        object = require( cExpression );
        odata_Create( url, jsondatastring );
        odata_Read( url [, filename] );
        odata_Update( url, jsondatastring );
        odata_Delete( url, jsondatastring );
        tmpnam()
        objectType( object_fieldname )
        objectRead( from_filename, object_fieldname )
        objectWrite( to_filename, object_fieldname )
        base64_encode_object( object_fieldname, width, height)
        unlink( filename )


    The following is an example Lianja JavaScript Server Page.
            
-->
<html>
<body>
<%
    // Note that just as in PHP, JavaScript Server Pages can use include_once( filename) and include(filename)
    // The path of the filename is relative to the directory containing this script.
    include_once("library_example.jssp");


    // The Lianja global object provides embedded database access
    db = Lianja.openDatabase("southwind");
    print("db=" + typeof db); 
    print("<br>");
    
    // Lianja.openDatabase() returns a Database object so now we can open a RecordSet
    rs = db.openRecordSet("select * from customers");
    print("rs=" + typeof rs); 
    print("<br>");
    print("Fieldcount="+rs.fieldcount);
    print("<br>");
%>
<table>
<%
    print("<tr>");
    for (i=0; i<rs.fieldcount; ++i)
    {
        print("<td>"+rs.field(i).name+"</td>");
    }
    print("</tr>");
    rs.moveFirst();
    for (j=0; j<rs.reccount; ++j)
    {
        print("<tr valign='top'>");
        for (i=0; i<rs.fieldcount; ++i)
        {
            print("<td>"+rs.field(i).value+"</td>");
        }
        print("</tr>");
        rs.moveNext();
    }
    rs.close();
    db.close();
%>
</table>
</body>
</html>

PS. There are many examples in the examples directory. Run them like this.

http://localhost/examples/example_request.rsp

Reading these examples will show you how to upload files, handle authentication and much more.

Question:

Do you need to write code like this to run Lianja Web and Mobile Apps.

Answer:

If you follow best practices no you don’t but if you want to format a custom WebView section or use a third party JavaScript framework this is when you would use dynamic server pages.

And by the way, they are *very* fast. HTTP web connections and ODBC connections to MSSQL / MySQL / PostgreSQL etc are pooled internally.

Q:
I am wanting to set Lianja Cloud Server,
follow the instructions in the documentation,
but want to connect to http: //localhost/login.rsp
I get browser error “HTTP Error 404.0 – Not Found”
is this is something of the IIS configuration, but still the steps and it does not work.
A:
try this.

Was a bad IIS Configuration,

Sorry by my English, but i try

ISS Default directory, was originally C:\INETPUT\WWWROOT
and change to:

C:\lianja\cloudserver\tenants\public\wwwroot
You do not need to change the IIS default directory. That would interfere with existing web configuration.

The Lianja extension takes care of all that based on how it is configured.

I run with IIS and did not change the IIS default directory.

Some clients do not like the idea of using mapped network drives.

That doesn’t seem to be an issue.

In my testing, I create the public folder shared on the cloudserver (it is installed on the server as C:\Lianja\cloudserver\tenants\public\.

Then in the client desktop shortcut, I just set the target to the runtime library, and then use \\myservername\public\apps\myapp

like so.

Code:
C:\Lianja\bin\lianjaruntime.exe -a \\myserver\public\apps\<appname> –nosplashscreen

Cloud Server

Q:

I have set up an EC2 Windows Virtual Server instance on Amazon, opened port 8001 and installed Lianja Cloud Server. I deployed the app in the Web App View which generated the index.html file. I then copied the C:\lianja\cloudserver\tenants\public\wwwroot\apps\ myappfolder folder to the EC2 server and the database to C:\lianja\cloudserver\tenants\public\data.

When I try to run the app from a browser http://xxx.xxx.xxx.xxx:8001/apps/myappfolder/index.htm or http://xxx.xxx.xxx.xxx:8001/login.rsp I get the “This page can’t be displayed” error. How do I run the app from a browser or tablet?
A:

If you are using a desktop browser and you have enabled the app with guest access in the app settings then your URL is correct.

you need to make sure that the firewall is allowing access to port 8001.

Right click on the browser page and look for errors in the JavaScript console.

if your app works in your dev machine and you have deployed the app, library files and data it should be working on a remote server.

Check the permissions in the files that you uploaded.

Lianja Cloud Server is a very functional and scaleable means of performing CRUD operations on data in any type of database.If you build Web and/or Mobile Apps using Lianja best practices (Pages, Sections, Fields and Gadgets) all of the heavy lifting for adding, updating, deleting and querying data is done for you. Lianja uses JSON extensively for this purpose.

There can be no doubt that JSON is the modern and most commonly used data interchange format for Web and Mobile apps.

Lianja Cloud Server has built in support for OData. This provides a wide range of data formats that can output based on a very simple and easy REST API.

Let’s take a look at some of these output formats.

For the purposes of these examples I will be using the OData_Read() function from the Lianja App Builder console but the same REST URI can be types into the browser address bar (Google Chrome recommended as it does not prompt you to download the results of the query). If you are typing these REST URIs into the browser address bar prefix /odata/ to them.

In the following examples I have added $top=1 to select only the first record. OData handles a wide range of parameters such as $filter, $orderby etc. See the following link for details.

http://www.lianja.com/resources/blog…ja-sql-server-

OData Command:

Code:
odata_read("/southwind/customers?$format=json&$top=1")

OData Output:

Code:
{"d" : {
        "results": [
                {"customerid":"ALFKI","contactname":"Maria Anders","companyname":"Alfreds Futterkiste","contacttitle":"Sales Representative","address":"21 State Street","region":"East","city":"Boston","postalcode":"01943","country":"USA","phone":"617-342-8976","fax":"617-567-9876","notes":"
The last time this customer was contacted she was going on vacation.

"} ], "__database": "southwind", "__table": "customers", "__primarykey": "", "__tabletype": "table", "__datatypes": "CCCCCCCCCCCM", "__href": "/odata/southwind/customers?$format=json&$top=1", "__querytime": "18ms", "__count": 91, "__page": 1 }}

OData Command:

Code:
odata_read("/southwind/customers?$format=jsongrid&$top=1")

OData output:

Code:
{
        "rows": [
                {"customerid":"ALFKI","contactname":"Maria Anders","companyname":"Alfreds Futterkiste","contacttitle":"Sales Representative","address":"21 State Street","region":"East","city":"Boston","postalcode":"01943","country":"USA","phone":"617-342-8976","fax":"617-567-9876","notes":"
The last time this customer was contacted she was going on vacation.

","__rowid":1} ], "database": "southwind", "table": "customers", "__tabletype": "table", "__primarykey": "", "__datatypes": "CCCCCCCCCCCMN", "__href": "/odata/southwind/customers?$format=jsongrid&$top=1", "__querytime": "13ms", "total": 91, "page": 1 }

OData Command:

Code:
odata_read("/southwind/customers?$format=jsonarray&$top=1")

OData output:

Code:
[
        {"customerid":"ALFKI","contactname":"Maria Anders","companyname":"Alfreds Futterkiste","contacttitle":"Sales Representative","address":"21 State Street","region":"East","city":"Boston","postalcode":"01943","country":"USA","phone":"617-342-8976","fax":"617-567-9876","notes":"
The last time this customer was contacted she was going on vacation.

"} ]

OData Command:

Code:
odata_read("/southwind/customers?$format=excel&$top=1")

OData output:

 

<?xml version=”1.0″?> <?mso-application progid=”Excel.Sheet”?> <Workbook xmlns=”urn:schemas-microsoft-com:office:spreadsheet” xmlns:o=”urn:schemas-microsoft-com:office:office” xmlns:x=”urn:schemas-microsoft-com:office:excel” xmlns:ss=”urn:schemas-microsoft-com:office:spreadsheet” xmlns:html=”http://www.w3.org/TR/REC-html40″&gt; <Worksheet ss:Name=”Sheet1″> <ss:Table ss:ExpandedColumnCount=”12″ ss:ExpandedRowCount=”92″ x:FullColumns=”1″ x:FullRows=”1″ ss:DefaultRowHeight=”15″> <Row> <Cell><Data ss:Type=”String”>CUSTOMERID</Data></Cell> <Cell><Data ss:Type=”String”>CONTACTNAME</Data></Cell> <Cell><Data ss:Type=”String”>COMPANYNAME</Data></Cell> <Cell><Data ss:Type=”String”>CONTACTTITLE</Data></Cell> <Cell><Data ss:Type=”String”>ADDRESS</Data></Cell> <Cell><Data ss:Type=”String”>REGION</Data></Cell> <Cell><Data ss:Type=”String”>CITY</Data></Cell> <Cell><Data ss:Type=”String”>POSTALCODE</Data></Cell> <Cell><Data ss:Type=”String”>COUNTRY</Data></Cell> <Cell><Data ss:Type=”String”>PHONE</Data></Cell> <Cell><Data ss:Type=”String”>FAX</Data></Cell> <Cell><Data ss:Type=”String”>NOTES</Data></Cell> </Row><ss:Row><ss:Cell><ss:Data ss:Type=”String”>ALFKI</ss:Data></ss:Cell><ss:Cell><ss:Data ss:Type=”String”>Maria Anders</ss:Data></ss:Cell><ss:Cell><ss:Data ss:Type=”String”>Alfreds Futterkiste</ss:Data></ss:Cell><ss:Cell><ss:Data ss:Type=”String”>Sales Representative</ss:Data></ss:Cell><ss:Cell><ss:Data ss:Type=”String”>21 State Street</ss:Data></ss:Cell><ss:Cell><ss:Data ss:Type=”String”>East</ss:Data></ss:Cell><ss:Cell><ss:Data ss:Type=”String”>Boston</ss:Data></ss:Cell><ss:Cell><ss:Data ss:Type=”String”>01943</ss:Data></ss:Cell><ss:Cell><ss:Data ss:Type=”String”>USA</ss:Data></ss:Cell><ss:Cell><ss:Data ss:Type=”String”>617-342-8976</ss:Data></ss:Cell><ss:Cell><ss:Data ss:Type=”String”>617-567-9876</ss:Data></ss:Cell><ss:Cell><ss:Data ss:Type=”String”><p>The last time this customer was contacted she was going on vacation.</p></ss:Data></ss:Cell></ss:Row>

OData Command:

Code:
odata_read("/southwind/customers?$format=ado&$top=1")

OData Output:

 

<xml xmlns:s=”uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882″ xmlns:dt=”uuid:C2F41010-65B3-11d1-A29F-00AA00C14882″ xmlns:rs=”urn:schemas-microsoft-com:rowset” xmlns:z=”#RowsetSchema”> <s:Schema id=’RowsetSchema’> <s:ElementType name=’row’ content=’eltOnly’ rs:updatable=’true’> <s:AttributeType name=’CUSTOMERID’ rs:number=’1′ rs:nullable=’true’ rs:write=’true’ rs:basetable=’_ODATA’ rs:basecolumn=’CUSTOMERID’> <s:datatype dt:type=’string’ rs:dbtype=’str’ dt:maxLength=’5′ rs:fixedlength=’true’ /> </s:AttributeType> <s:AttributeType name=’CONTACTNAME’ rs:number=’2′ rs:nullable=’true’ rs:write=’true’ rs:basetable=’_ODATA’ rs:basecolumn=’CONTACTNAME’> <s:datatype dt:type=’string’ rs:dbtype=’str’ dt:maxLength=’30’ rs:fixedlength=’true’ /> </s:AttributeType> <s:AttributeType name=’COMPANYNAME’ rs:number=’3′ rs:nullable=’true’ rs:write=’true’ rs:basetable=’_ODATA’ rs:basecolumn=’COMPANYNAME’> <s:datatype dt:type=’string’ rs:dbtype=’str’ dt:maxLength=’40’ rs:fixedlength=’true’ /> </s:AttributeType> <s:AttributeType name=’CONTACTTITLE’ rs:number=’4′ rs:nullable=’true’ rs:write=’true’ rs:basetable=’_ODATA’ rs:basecolumn=’CONTACTTITLE’> <s:datatype dt:type=’string’ rs:dbtype=’str’ dt:maxLength=’30’ rs:fixedlength=’true’ /> </s:AttributeType> <s:AttributeType name=’ADDRESS’ rs:number=’5′ rs:nullable=’true’ rs:write=’true’ rs:basetable=’_ODATA’ rs:basecolumn=’ADDRESS’> <s:datatype dt:type=’string’ rs:dbtype=’str’ dt:maxLength=’60’ rs:fixedlength=’true’ /> </s:AttributeType> <s:AttributeType name=’REGION’ rs:number=’6′ rs:nullable=’true’ rs:write=’true’ rs:basetable=’_ODATA’ rs:basecolumn=’REGION’> <s:datatype dt:type=’string’ rs:dbtype=’str’ dt:maxLength=’15’ rs:fixedlength=’true’ /> </s:AttributeType> <s:AttributeType name=’CITY’ rs:number=’7′ rs:nullable=’true’ rs:write=’true’ rs:basetable=’_ODATA’ rs:basecolumn=’CITY’> <s:datatype dt:type=’string’ rs:dbtype=’str’ dt:maxLength=’15’ rs:fixedlength=’true’ /> </s:AttributeType> <s:AttributeType name=’POSTALCODE’ rs:number=’8′ rs:nullable=’true’ rs:write=’true’ rs:basetable=’_ODATA’ rs:basecolumn=’POSTALCODE’> <s:datatype dt:type=’string’ rs:dbtype=’str’ dt:maxLength=’10’ rs:fixedlength=’true’ /> </s:AttributeType> <s:AttributeType name=’COUNTRY’ rs:number=’9′ rs:nullable=’true’ rs:write=’true’ rs:basetable=’_ODATA’ rs:basecolumn=’COUNTRY’> <s:datatype dt:type=’string’ rs:dbtype=’str’ dt:maxLength=’15’ rs:fixedlength=’true’ /> </s:AttributeType> <s:AttributeType name=’PHONE’ rs:number=’10’ rs:nullable=’true’ rs:write=’true’ rs:basetable=’_ODATA’ rs:basecolumn=’PHONE’> <s:datatype dt:type=’string’ rs:dbtype=’str’ dt:maxLength=’24’ rs:fixedlength=’true’ /> </s:AttributeType> <s:AttributeType name=’FAX’ rs:number=’11’ rs:nullable=’true’ rs:write=’true’ rs:basetable=’_ODATA’ rs:basecolumn=’FAX’> <s:datatype dt:type=’string’ rs:dbtype=’str’ dt:maxLength=’24’ rs:fixedlength=’true’ /> </s:AttributeType> <s:AttributeType name=’NOTES’ rs:number=’12’ rs:nullable=’true’ rs:write=’true’ rs:basetable=’_ODATA’ rs:basecolumn=’NOTES’> <s:datatype dt:type=’Memo’ rs:dbtype=’Memo’ dt:maxLength=’8′ rs:fixedlength=’true’ /> </s:AttributeType> </s:ElementType> </s:Schema> <rs:data> <z:row CUSTOMERID = ‘ALFKI’ CONTACTNAME = ‘Maria Anders’ COMPANYNAME = ‘Alfreds Futterkiste’ CONTACTTITLE = ‘Sales Representative’ ADDRESS = ’21 State Street’ REGION = ‘East’ CITY = ‘Boston’ POSTALCODE = ‘01943’ COUNTRY = ‘USA’ PHONE = ‘617-342-8976’ FAX = ‘617-567-9876’ NOTES = ‘<p>The last time this customer was contacted she was going on vacation.</p>’ /> </rs:data> </xml>

 

Code:

OData Command:

Code:
odata_read("/southwind/customers?$format=csv&$top=1")

OData output:

Code:
"customerid","contactname","companyname","contacttitle","address","region","city","postalcode","country","phone","fax","notes"
"ALFKI","Maria Anders","Alfreds Futterkiste","Sales Representative","21 State Street","East","Boston","01943","USA","617-342-8976","617-567-9876","
The last time this customer was contacted she was going on vacation.

"

all built-in. Nothing to write, just reference the REST URIs and the data will be returned in the format you requested.

The odata REST API works against any type of database.

The examples I gave are just for querying but the cloud server handles full CRUD through the REST API. I will be posting examples of how to perform inserts, updates and deletes also.
The Lianja Cloud Server is not solely for use by Lianja Web and Mobile Apps. It can be used to serve up OData data, web services (written in Lianja/VFP or JavaScript) and dynamic HTML5/JavaScript using Lianja/VFP Server Pages (.rsp pages) and/or JavaScript Server Pages (.jssp pages). So it can be used as a web/mobile application server for other web development tools and even .net / Java if required.

 Lianja Cloud Server can generate JSON directly from OData also without the need to write any server-side code or rsp pages. The $format=jsonarray argument was added in v2.0. Here is an example of querying a table in a database and fetching the results as a JSON array.
Screen Shot 2015-07-21 at 6.32.33 PM.jpg

Q:

I have installed as a trial Cloud Server on a Windows server and a Linux Server.

I can enter the IP address in my local browser and I get the Lianja App Center Login.

I now want to deploy the Lianja Tablet Web UI Demo and the Lianja Web UI Demo to these 2 servers. I suspect I would also need to deploy database.

Couple questions:

1. Is there any way to know exactly what pieces should be selected when I am in the Deploy process? For example, which libraries, etc are needed?
2. What is the proper sequence of steps to generate everything and then get it to the Cloud Server?
A:
The answer is to use projects. When you select a project in the deploy workspace. It will check off all the files in the project and deploy them.
So create a project and add the files to the project. You can add multiple apps too so they all get deployed.
The only library files you need to deploy are custom ones you have written yourself. Normally all files specific to an app are in the app directory and will be copied automatically when you deploy.
Custom library files that you share across multiple apps should be in the library workspace and should be added to your project. 
Yes you need to deploy your database. 
I normally develop then deploy to my local cloud server for testing. This I treat as my staging and testing server.
When I’m ready to put on a remote server I choose the project and upload using the built-in sftp support.

Cloud Server

Enabling Port 80
If you do not have an existing web server and want to run the Lianja Cloud Server on port 80 as well as port 8001:
Linux
=====
Edit the text configuration file /etc/lianja.d/lianja.conf and change the line
DB_PORT80_ENABLED=”false” ;export DB_PORT80_ENABLED

to
DB_PORT80_ENABLED=”true” ;export DB_PORT80_ENABLED

Then restart the Lianja Server.
Windows
=======
Check the ‘Enable HTTP requests on port 80’ Setting in the Lianja Server Manager:

enable_port_80

Then restart the Lianja Server.


Amazon AppStream Update – Access Windows Apps on Chromebooks, MacBooks, Kindle Fires, and More
http://aws.amazon.com/blogs/aws/apps…pps-on-devices
We will be testing this out running Lianja Desktop Apps in the Amazon Cloud and will report back our findings.


implemented in the Cloud Server.
– Cursoradaptor
– NetworkRequest
– COM/ActiveX
– Virtual tables


In the v1.2.4 release we have now made the Lianja ISAPI Extension for IIS available in the distribution.
This provides seamless integration with IIS and the ability to use https/SSL encryption.
Performance is almost as good as the native Lianja Cloud Server as we have implemented it using intelligent connection pooling.


Q:
how to bypass the login screen for the cloud server
A:
There is an app setting to run as guest. That should prevent the login screen. If it doesn’t let me know.

Screen Shot 2014-08-15 at 1.14.23 PM


Just to make you all aware of a few changes in the Lianja v1.2 Cloud Server distribution.
1. No sample apps are included so that it can be installed for live use.
2. Port 80 is disabled by default. Port 8001 is enabled. This prevents any conflict with IIS and/or Apache.
The App Builder automatically detects what port the server is running on.
This has been done to make it easier to upgrade existing sites without having to remove the example apps.
Any Apps needing deployed should be done in the “Web App View”, “Tablet App View” or “Phone App View”.
The “Save” button in the Web App View has now been renamed to “Deploy”.
The Lianja App Builder APaaS Developer now handles 50 local/remote connections for testing your Web and Mobile Apps.
Creating a new App now has an “App Wizard” to provide a more streamlined experience.


Yes the Lianja cloud server is used with web and mobile.
The appliance has everything installed to save time.
Lianja Cloud Server is preinstalled as is guacamole.


if you need OData access you will need Cloud Server as SQL Server only supports ODBC Data access.


Q:
Whats the difference between “Lianja Sql Server” and “Cloud Server”?.. Cloud server contains “Lianja SQL Server”.. Does it have something to do with “Deploy”? Also.. Is there a routine in the App Builder to Import dbfs into “Lianja Sql Server”?
Is the “Cloud” located on my Server? I dont want to deploy anywhere outside my network.. I just downloaded and installed it.. I’ll play around with it..
Just deployed a database I created.. it appears to just copy the DBFs to C:\Lianja\cloudserver\tenants\public\data\rstock and not to “Lianja SQL Server..
I already wrote a routine to manually put database/tables in the SQL Server from VFP9..via ODBC driver… just thought The App Builder would do it also
A:
Lianja Cloud Server is a complete App Server which has support for serving Web and Mobile Apps into a browser. It has Lianja SQL Server embedded in it so it also provides both ODBC and OData Data access.
The “Deploy” workspace in the App Builder provides the ability to deploy databases and Web/mobile Apps into the Cloud Server. This is in the “Data” workspace.
you can import dbfs into the App Builder then deploy them to the Cloud Server. The Cloud Server runs on either windows or Linux.
Lianja SQL Server only provides ODBC Data access.


Lianja Cloud Server is the server for Cloud/Web Apps running in the Lianja Web/Mobile client, OData and WebSocket Services and Dynamic Page Services (rsp/jssp pages). Lianja SQL Server is the server for third party clients using the Lianja ODBC Driver to access Lianja data. When you purchase the Lianja Cloud Server, you also get the Lianja SQL Server too.
This article in the Wiki explains how to deploy Lianja data for Lianja SQL Server access. Additional Wiki documentation for Lianja Cloud Server and Lianja SQL Server can be found here.


Q:
I see that there are “Foxpro server pages” and also “JavaScript Server Pages” A:
The jssp JavaScript Server Pages embed the V8 JavaScript engine as used by Node.js.
javascript server pages (.jssp pages) use the same JavaScript engine as node.js (Google v8 engine). It is embedded in the cloud server (cross platform). To better handle server side page requests it uses synchronous calls not async. You can also call VFP code directly from server side JavaScript.
So if you want you can have data centric JavaScript frontend and backend.
yvonne can point you to example server side pages in both LianjaVFP and JavaScript.
Wiki Code Examples


Lianja SQL Server does not handle OData calls. These are handled by the Cloud Server.
You don’t need to use virtual tables in the Cloud Server. All the SQL is generated and executed dynamically by the OData parser engine.


1. The Lianja Cloud Server is an app server. This is detailed at:
http://www.lianja.com/resources/blog…a-cloud-server
It is a web server, database server and dynamic page server combined.
It can operate on its own without apache or IIS or (available soon as per the roadmap) it can just be used as an extension to apache (module) or IIS (ISAPI plugin). All these extensions do is let it be installed as a “handler” for certain page request extensions and OData calls. Other than that it works in the same way as how .asp .php or .py server side pages work.
The subtle differences from just handling dynamic pages is that it has embedded within it the Lianja/VFP data centric scripting language which includes Lianja/SQL (Lianja/VFP dynamic server pages), JavaScript (.jssp) Server pages, and OData API using standard URL calls. You basically have the Lianja/VFP scripting language and database engine to use to dynamically generate HTML5/JavaScript pages.

2. The Lianja Cloud Server listens on both port 80 and port 8001 (by default) after installation. This allows you to develop Web Apps as “standard Lianja Apps”, view then alongside your development view “click the Web App View icon in the page header to see how it looks in a browser”. Try running the “example_webapp” or “example_webapp2” apps in chrome on your desktop and you will see what can be achieved with NoCode. Type http://localhost/apps/example_webapp/index.html into the Chrome address bar (IE11 is supported in the next v1.0.1 build). You can run the “Lianja Server Manager” from the control panel and disable port 80, then restart the service and it will not interfere with your existing IIS port usage. You would then always postfix :8001 to the URL hostname when making requests. After we make the ISAPI plugin available for IIS then requests for .rsp pages, .jssp pages, OData requests, and Lianja Web App requests will automatically be routed to the Lianja Cloud Server.

3. Our implementation of .jssp pages (and .rsp pages for that matter) are very similar to .asp and .php pages (all the PHP _request[] array etc) is made available to the dynamic page). The V8 JavaScript engine has been integrated in with Lianja/VFP. The structure of javascript server pages (.jssp files) have the same functionality (plus more) of .asp and PHP pages. You can call VFP procedures and evaluate VFP expressions from inside the javascript code of your dynamic page or you can use plain javascript — whatever you prefer.

4. Node.js typically is not used with apache or IIS. Typically this is at a much lower level whereby you create worker threads in javascript by accepting URL requests and route then to your javascript handler code. IMO Async “everything” does not fit in well with client side database apps that make a request to a server side URL that will return some HTML/JavaScript that is then injected into a dynamic area to the web page DataView that the user is currently interacting with. A web browser dispatches async (ajax) HTTP requests that are sent to an IP, inspected and routed to the actually producer of the dynamic HTML/JavaScript code. The browser then reads the response from the remote web server. There are timeouts on ajax requests (these are browser dependent) and if the server does not respond in a certain timeframe then the request fails.
If your are comparing Lianja Cloud Server with node.js then really they are two different things altogether. If you want to write in JavaScript on the backend, they both allow that. Both use the google V8 JavaScript engine in different ways. Node.js is all async operation which as i’ve mentioned is problematic for database oriented web apps. Lianja Cloud Server runs javascript code synchronous so that it can generate dynamic HTML5/JavaScript in a meaningful order so that the browser receives it in a properly structured HTML5 document format. You can for example open a database, create a “recordset” using a Lianja SQL query and then iterate over the data generating HTML5/javascript dynamically. The “introduction to Lianja Cloud Server describes how to accomplish this”. If this is all async on the server side you get into “callback hell”. Synchronous is much simpler to code for this purpose.
Another important distinction between node.js and Lianja Cloud Server is that the Lianja Cloud Server has complete javascript dynamic page processing support built-in. This is an important distinction between the two. So, a .jssp page is structured like an .asp or .php page, which has HTML5 and dynamic code execution all handled for you using the familiar code tags (and quite a few more such as codebehind).

5. You mention that you want to process millions of records and generate huge reports from a web request. What happens to the huge report when the job completes? Is this emailed or what? Obviously you would not want to display a 10000 page report in a web browser tab. If you want to handle background work on the server then Lianja Cloud Server has support for “background services” that can be written in Lianja/VFP. If you open up the “Lianja Server Manager” from the control panel you can see how these are setup. There is an example in the distro. The way these are typically used is through a “work queue table”. So your web request page handler adds a “job” (inserts a record) to your work queue table. Your background task looks at this periodically and if there are any requests it handles them and iterates this process until all jobs have completed. Obviously your “Report job scheduler” can spawn background processes to handle individual jobs. These can then email the user or notify them in some other way when the report job has completed.
On linux you would use “cron jobs” that do the same thing as described above.

I hope that provides a better understanding of what Lianja Cloud Server is and how it is used to serve Lianja Web and Mobile Apps, dynamic HTML5 page content, and handle third party data requests using OData.