NonDesktop apps

Building a web app with Visual FoxPro Code only.
vfpwebdemo – https://youtu.be/_FhVyBtcWjM


Q:
I would like the VFP9 app to be able to communicate with the Lianja database either remotely or on the same network, depending on the settings of the implementation. I have a few different clients that use my VFP6 app, and some may prefer to host the Lianja database on their own servers, while others may prefer to use a third party hosting service in the cloud. From Barry’s response, I gather that as long as VFP9 accesses the Lianja SQL Server via the Lianja ODBC driver, either configuration would work. Would this work using an Amazon AWS-hosted instance of Lianja Cloud Server?
A:
Yes. Lianja SQL Server is part of the Lianja Cloud Server install. When you create an AWS EC2 instance it has a FQDN which you can point to from DNS e.g. You purchase a meaningful domain name from network solutions (or other) and set it up to point at your AWS FQDN. So yes is the answer.

So you can have web apps sharing the data with Lianja SQL server and VFP accessing the data using an ODBC connection to Lianja SQL server.

Lianja ODBC driver communicates with the server using TCP/IP so it can in fact be used across the Internet.

When the cloud server us running Lianja SQL is running too.


Yes, RSP. Use the benefit of CRUD in Lianja Framework. Delegates need to be written in language:

Client side: js
Server side: VFP (PHP is on the roadmap)
Client and server sides need to be separated.

Some quotes:

Building Web / Mobile Apps requires a traditional client / server design approach.
What at we have done is provide the equivalent of the VFP base classes and many of the VFP built-in functions in the Lianja Web Framework. This allows you to create objects, call their methods and get/set their properties just as you would in VFP, albeit in javascript.
Everthing in Lianja revolves around the Lianja Object Model and ART (Actions, Rules and Transitions).
All data processing (CRUD operations) is performed on the server.
You can
use Lianja.evaluate() in javascript to call server side procedures that are all written in VFP.

You currently use javascript on the client and Lianja/VFP on the server side when you want to call server side procedures.
The equivalent of .php pages are .rsp pages or .jssp pages as documented in the Developers Guide.

.php pages generate dynamic HTML content.
.rsp pages generate dynamic HTML content but with embedded Lianja/VFP data centric scripting.
.jssp pages generate dynamic HTML content using server side javascript.
These are used
to render WebView sections in Lianja.
Most sections are automatically data bound as can be seen in the example Apps.
Server side PHP and Python scripts are on the roadmap. The others are already supported in Lianja Cloud Server.
you
test your server side Lianja/VFP procedures in desktop mode.
You
test and debug client side javascript delegates in the web app view.



 

Advertisements

NonDesktop apps

Lianja.getElementByID(“page.section”).menu is exposed on the Desktop client only (Lianja/VFP), you can’t currently modify the Section custom menu options in JavaScript code for Web Apps.


Q:
If I have an app for desktop with language VFP, and I want to create the same app for WEB, do I have to replace all the code in Java
A:
The client side code that runs in the browser needs to be written in JavaScript but you can call Lianja/VFP procedures on the server.
If you follow best practices and use standard sections whenever possible, the app will run on desktop, web and mobile.


Q:
My client-side ‘evaluateJavascript’ call is working fine back to the server file but it will be great if you could expand a little on what actually makes the server file run server-side.
My understanding: evaluateJavascript effectively does an RPC to the backend, sending the call back in a JSON string, getting the result, and sending it back in a JSON string
A:
The client-side code is in LianjaHtmlClient*.js, which is present in minified form in the distribution. There are tools on the web for formatting minified scripts if you want to look at it.
The framework is not minified unless the app is previewed in release mode. Looking at the framework will not help to prove that it’s running server-side.
Development mode and runtime views are a core requirement to understand how to build apps in Lianja.
In this case the requirement of the OP to write in JavaScript on the client and the server is fully supported but not yet properly understood.


Q:
I’m writing a little server-side function that searches a table for a given value in a given field, and returns a different given field in the same record. For instance, you could tell it to return the name of a customer with ID=5. I’ve gotten it working (muliple ways, actually) on a desktop app but can’t seem to do it on a web/mobile app. The original basic logic was building a string out of my different variables and then run Lianja.execute on that string. Lianja.execute doesn’t work on web/mobile clients so I needed another way.

I found the PREPARE/EXECUTE commands in the documentation and tried them. I couldn’t work out how it handled different types of parameters but found a way to get it to work on desktop. What I thought should work was:

Code:
local mystring = "select ? from ? where ? = ?"
local selectfield = "total"
local tablename = "expenseclaim"
local searchfield = "claimid"
local searchvalue = 5
prepare stmt from :mystring
execute stmt using :selectfield, :tablename, :searchfield, :searchvalue

This seemed to behave oddly with respect to data types. For example, it accepted expenseclaim as the name of a table, but literally output the string “total” instead of the value in the field named total.

What I got to work on a desktop app was building “mystring” by placing the variables in it directly, then calling PREPARE/EXECUTE on it. Since EXECUTE needs at least one parameter and the table name seemed to behave properly, I left that in the string as a parameter:

Code:
local selectfield = "total"
local tablename = "expenseclaim"
local searchfield = "claimid"
local searchvalue = 5
local mystring = "select " + selectfield
mystring += " from ?"
mystring += " where " + searchfield + " = " + searchvalue
PREPARE stmt from :mystring
EXECUTE stmt USING :tablename

This works perfectly fine on desktop, but on web/mobile clients it breaks on the EXECUTE line.

That might be a bug , it might not be implemented on web/mobile or I might even be making some silly mistake, but even then it feels like a rather convoluted way of going about things. Is there a way to just execute a string within a Lianja/VFP script on a server? Or to just place variables into a Lianja/VFP command?
A:
just create a statement as a string using &macro substitution or use sprintf() if you find that easier.

Commands stored in character variables can be executed dynamically

Code:
cmd = "select * from " + p_tablename + " where id=&p_id"
&cmd

You can’t use &macros in the console. Just type

ed ryan

and put your code in that file then from the console issue

do ryan

you can call your server side proc from the client using

Code:
var result = Lianja.evaluate("ryan()");

to substitute parameters you can use {…} macros on the client too.


Q:
I’m building a web/mobile app and I’ve run into a really frustrating problem. I can’t open my database from a preview in my browser, but I can from the app builder and web preview screens? i’m trying to open it on the init of my app and do some manipulation to make sure it’s set up properly before the app loads, but I can’t even get past the opening part. It works fine with Southwind so I know I’ve done something wrong in the database itself. For reference the code in my app is:

app init delegate

Code:
var initstatus = Lianja.evaluate("appinit()");
Lianja.showNotification(initstatus,true);

appinit.prg

Code:
try
    open database mydatabase
catch
    return "unable to open database"
endtry
return "success"

This shows the message “unable to open database”, but when I replace mydatabase with southwind it shows “success”. Does anyone know what I could have messed up inside my database to cause this?
Oh and yes it’s deployed. It’s sitting in lianja\cloudserver\tenants\public\data, right next to where I deployed southwind.
A:
Have a look at strerror( errno() ) which will tell you what the issue is.
Does your database have a ‘dbc_opendata’ database open event delegate (empty or containing code)?

This is not currently supported in the Lianja Web Client, so needs to be removed before deployment.


It runs on the server when the database is opened not on the client.
Q2:
Ah, yes I do have an opendata script!
I wasn’t aware it wasn’t working in the cloud server.
A2:
Please submit a ticket. It runs on the server when the database is opened not on the client.


Q:
I am seeking advice for writing apps that will be used on web & mobile – should these be written in .rsp (I know php/asp) or regular Lianja pages that are enabled for web/mobile? + benefits of one approach over the other.
A:
If you want to hand code everything and ignore the Lianja development methodology of pages, sections, UI navigation, transparent client/server interaction, automatic data binding, roles and permissions, user authentication, etc… You can write everything in .rsp and roll your own framework and methodology.

To develop web and mobile apps you should follow Lianja best practices using pages and sections. Custom HTML content should be generated dynamically on the server and bound to a Webview section.

Lianja PhoneGap apps are executables that interact with the cloud server to handle CRUD operations.

rsp pages are used by various webviewwidgets in Lianja to dynamically generate content for charts, reports, and other static display content.


Q:
I created an App using Visual Foxpro as my scripting language and now cannot generate Web, Tablet or Phone Apps from it. I now understand that I should have used Javascript as the Scripting Language when I created the original app and I have subsequently changed the Scripting Language in the Settings but to no avail.
Is there anyway to correct this or must I redo the app from scratch and select Javascript at the time of app creation?
A:
You need to replace any custom libraries and delegates with JavaScript ones.
You probably have some strange setting in the app which is preventing it being generated for the web.


You need to configure your VM with “Bridged networking” so that your mobile phone or tablet can communicate on the same IP subnet that the Cloud Server is listening on.

NATing your IP address with the host will not work. You need bridged networking.

Oh and one last thing… Remember to enable port 8001 (that the Cloud Server uses) or else turn off your firewall for testing otherwise you won’t be able to talk to the Cloud Server.


In Lianja v2.1, Lianja Mobile Apps now allow you to navigate the records in your apps using the familiar left, right, up and down “swipe” gestures.

Swipe Left navigates to the next record, Swipe Right navigates to the previous record, Swipe Up goes to the last record and Swipe Down goes to the first record.
Tap and Hold edits the record.

These gestures are only effective in Form, Canvas and Custom sections.

You can override this behavior by enabling gestures in the section attributes and write your own gesture delegate (which may me specified using the inline delegate syntax).

Note also that navigation swipe gestures are not available if you have enabled “Swipe Navigation” in the page attributes. If you have enabled “Swipe Navigation” in the page attributes, then Swipe Left and Swipe Right navigates between the next and previous pages in the App. Swipe navigation is also available in TabPanel sections.Swiping Left and Right navigates between the different Tabs.


Q:
When I try to preview in Web App View, I get the “Server connection lost” message as shown below.
The connection to local host is ok from my other system which uses it (MS Visual Web Developer).
Do I need to set a parameter somewhere for “Local Host”, or…?
A:
when i’ve had the issue, it has a) been with a lot of records using a build < 1.5 release; or b) a sign that I messed up one of the grid's (I've only seen it in a grid) column controlsources.


Q:
I’m confused about how a phone app interacts with a cloud server. How do I access data on a Lianja cloud server from a mobile app (for that matter how do I access it with a desktop app)? I know how to run a web app on a cloud server and access it via a web browser, is there a way to just run a database on the server without an app? Does the associated database get packaged with the mobile app for local access or is it supposed to access it remotely?
A:
If you build a mobile app using best practices and standard sections the data is automatically bound for you. It is a seamless SPA interacting with the database under the control of the cloud server.

If everything is data bound and validation is handled by remote procedure calls for you, and… you can dynamically create HTML5 content into webview sections in what other way are you wanting to access data on the server? You have Lianja.evaluate() and Lianja.evaluateJavaScript() as well as a lot of built-in OData functionality.

Just to clarify…

– You deploy your app and its database.
– You specify the mobile app settings in the project settings for phonegap
– You build your mobile app
– In there while testing, it will inject a reference to your local machine and access the cloud server using port 8001
After you have fully tested everything you change that URL to point at your cloud server production installation

There are example mobile apps included that you can study and install on your mobile devices.
Mobile Apps are regular client/server apps with the UI on the mobile device and the database on a remote server under the control of the cloud server.
A2:

1) User app on mobile phone opens a page. It needs data. It says to the Cloud Server (using a JSON call) “hey, I need the data from view vt_myview with parameter x set to value n.”

2) The Cloud Server says, “OK, I need to get the data from vt_myview with parameter x set to value n” — it then runs the view, just as one would run the view from the command console, connected to the backend. Now, that could be Lianja SQL Server, which could be on the same machine or could be somewhere else on the network (reachable by ODBC). Or it could be MSSQL, etc.

3) Having gotten the data back, the Cloud Server replies to the mobile app: “OK, I’ve got your data, here it comes,” and sends it back as oData (a JSON string).

4) the Mobile app then gets the oData string, decodes it into a JSON object, and the UI does its work off that object. When the mobile app makes a change to the data it sends the old and changed values back to the the Cloud server and the general cycle repeats.


Integration with AWS (Amazon) — do you know how (expletive deleted) hard it is to set up AWS right? Do you know how many resources you’ll pay for when you aren’t sharing them? Basically, it’s a 3-year learning curve to do it on your own, and even then you’ll run into challenges. There’s no mention of pricing on the roadmap, but the concept for economies through sharing instances is there, so with a “share the wealth” pricing model, what you see will almost certainly be less than you would pay if you spent that 3 years learning enough to get it almost right.


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.
A2:
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. <a href="http://nicolas.guelpa.me/blog/2015/02/21/rewrite-redirect-iis.html&quot; target="_blank" rel="nofollow"http://nicolas.guelpa.me/blog/2015/02/21/rewrite-redirect-iis.html I haven’t tried a rewrite with the LCS, so let us know if you try it.


Q:
I understand that all delegates should be written in javascript (for now) if I want an app that will be both web & desktop. But what about other code?

I mean if I write a VFP function and use it as an expression in an attribute (eg. grid ‘Filter’) it works fine in desktop but it doesn’t work in web (I have tested this).
But to write these functions in javascript doesn’t make sense either if I need to use VFP Lianja.execX() to run them anyway (as per the replies in the other post).
A:
I can only speak for myself, but anything that I am doing that is web based, I am doing in javascript sections as this will work for both desktop and web.

I have my apps seperated into client side and server side.
My client side is all javascript, the server side foxpro.

I dont think you would need to go back to the client to filter a grid unless it was very large. But that should be handled with a virtual table (Not yet ready for the web client – but coming soon – I hope

For example, when I filter my grid in a javascript section, I dont go back to the server. I am using a button (as combobox and optiongroups are not yet available for a web canvas section).
The click event of the button is in a file called lib_page1_section2.js

Here is the sample code.

Code:
function page1_section2_field7_click()
{
Lianja.get("page1.section1").filter ="machine_type='Physical'";
Lianja.get("page1.section1").refresh();
}

This code is exaclty the same as it would be in foxpro except it is case sensitive and has a semi-colon.
That said, I could have put all sorts of logic in the function written in javascript and not need anything in Foxpro.

However if there was a call that had to be done in foxpro, then I would use the LianjaExec(), but only when client side would not work.

Best practices are to use the standard sections, not the custom sections if you want to make sure your app will run everywhere.

When I create a project, I select Javascript as my language.
If I didnt, I could always set it up in the App,Page or Section setting under Custom Delegates.

The App setting is the bottom left hand side of the app builder. It’s the cogwheel that says settings.
If you click on that, the settings panel will slide in from the right.
Navigate down to custom Delegates. There you will find the Scripting language.
You will find the same thing for the page (Cogwheel at the top of the page) and for each section.

As long as these are set to javascript, the functions for all your events will be in a .JS file.

So to put javascript code behind a button, do the following.

Set my app to Javascript.
select Sections | Canvas.
Make sure the canvas section is highlighed with a blue border around it.
Select Advanced from the bottom menu.
Click on CommandButton. A button will appear on the canvas section.
Select the edge of the commandbutton.
Double click the commandbutton to bring up the field attributes.
Scroll down and click on the click event.

The file editor will appear where you can add your javascript code.
A2:
if in your delegate you call LianjaExec(“yourprgontheserver()” all the ajax stuff is done for you.
everything in an .rsp or .jsp etc. is evaluated on the server, not on the client. This works out well for me, as I can have a webview section in a mobile app that is running VFP code, on the server. Delegates on the page, of course, have to be in Javascript. But if the language at the top is set to VFP, the code sections will run on the server.


Q:
I cant use a canvas section since they may be using a different size devices, so I need something responsive.

I decided to try and do this with a custom javascript section and not an rsp page. The click functions work on the phone, but the text for the buttons are not showing up.
Are the custom javascripts sections not yet fully supported on web/mobile?
A:
Yes they are fully supported, both canvas and custom.
You may want to just use a footer menu and prefix the captions with a + e.g.

+Add,View,Delete

That will layout the buttons across any device size and you can just use the footer menu delegate to do whatever you want.



NonDesktop apps

Look at the getJSON() method for a section in the webview console.

See what it returns for a canvas section when you type in data into the fields on the canvas section.

Look at the base64_encode() function. Use it to encode the JSON string returned from getJSON() on the client.

Call a server side proc passing that base64 encoded string as a parameter to it.

In the server side procedure use base64_decode() to get the JSON string.

Now use json_decode() on that string.

Hey presto you have exchanged the data from your canvas on the client into an object on the server.

Now figure out what you want to do and then send a result back to the client. This is normally sent as a JSON string so that you can send an object back to the client rather than a single value.

Create a JavaScript object from the JSON you sent back to the client using JSON.parse( result ). You can also use JSON.stringify() to encode a JavaScript object as a string. Just google these. They are standard in all browsers.

Now you can reference the members of the JavaScript object, update your canvas section accordingly and then requery() your child section(s) by constructing a where condition that will be given as an argument to the requery() method for the target section.

Note that there currently is no setJSON() method for a section but I can see that would be useful for this scenario of handling manual querying of data. Submit an enhancement request ticket for that as it would reduce coding and be more consistent.

Also remember, Lianja.evaluate() is synchronous if no onsuccess callback is specified.


Q:
you can create an application “mobile” with DB “local” on the device?
A:
No, it is client/server just like you build Web Apps.



NonDesktop apps

Q:
My data will all be derived from .dbf files and is currently accessed from an ODBC connection.
I do not know Javascript and I do not know what is needed to convert my Lianja/VFP so that it can be dynamic HTML5/Javascript Code.

Currently all CRUD operations are primarily handled through virtual tables.
I do not understand how server side data access is not required.
1. How much of my current Lianja/VFP code can be used (there is lots of code)?
2. Can existing .prg files still be used?
3. If I create .rsp pages, how do I know what needs to be placed in it and what shouldn’t be?
4. If I don’t know JavaScript, isn’t it still required for client side programming?
5. The scripting language is set to ‘Inhert’. Does this need to be changed?
If I change the view of my app to preview in a browser, my menu items do not work (one of which shows/hides a search panel), the grid can’t display, the page doesn’t scroll and my data isn’t displayed.
How would you recommend proceeding in changing my app to be web usable as well (as best as you can without having it in front of you)?

A:
look at the web app examples. Work through them to better understand what is going on client/server.

The client web app running in the browser dispatches requests to the cloud server using an odata url. Read the doc about odata on the website.

The cloud server handles odata requests, generates the SQL for them, executes it and sends the data back in industry standard JSON.
It handles native tables and virtual tables.

In a client/server application the UI is separated from the backend business logic procedures and the database access.

So, the delegates that are related to UI events must be written in JavaScript which is the core scripting language that a web browser understands.

The Lianja object model (LOM) is available to your JavaScript code just as it is in your Lianja/VFP code in your desktop application.
This is one of the ways Lianja achieves UI device independence.

The Lianja Web Framework provides most of the Lianja system object that you are familiar with in writing desktop apps, so Lianja.evaluate() etc is available to call server side business logic written in Lianja/VFP and (in v2.0) Lianja.evaluateJavaScript() for calling server side business logic written in JavaScript.

Client/server development requires you to separate UI from the business logic. The client needs to handle client specific functionality not be designed as one large monolithic application that does everything all in one place as you would in a desktop app.

Hint: if you have a page or section that is bound to the desktop app you can omit it from your web app by using UI personalities which are enabled or disabled in the attributes.


(?A):
What I find amazing about Lianja is the myriad of ways to get things done.

For example, a beginner can use very little coding to get a fully functional web application done just by using the best practices.

He/she doesn’t need to now much about javascript, CSS, PHP (or .net), html etc.

Fully updatable data driven web applications.

Brilliant really.

But it doesn’t stop there. The more advanced users have tools build in the Lianja world to allow interaction between the Lianja objects and purely web based technologies. The showdialogs,evaluate and Odata come to mind.

But it goes further. If you are like me and like to tinker with all sorts of technologies, you can quickly appreciate the Lianja world as one that allows you to go as deep as you want into database web applications.

For example, I downloaded a Bootstrap theme that I liked, added my own rsp pages for the look and feel using Kendo UI.
I have created RSP pages that have a mix of SQL Server code and VFP code for a logic layer and return that all back the front end. All using the powerful cloud server for very quick response.

For this particular project, I am developing directly into the cloudserver apps root directory. Meaning, I am not using the Lianja IDE to create a fully Lianja supported project.
I am doing that, because in this particular project, it makes sense and being that the flexibility exists, I am happy to use it.

My point is to illustrate the incredible flexibility of the cloud server and the RSP pages.

Together, they can do anything you can think of.

Here is what my dev environment looks like.


Best practices for one App that runs on desktop and web and mobile. (As already stated in the doc link you provided).
1. Client code (delegates, custom sections, canvas section) should be JavaScript.
2. Server code can be Lianja/VFP (or JavaScript in v2.0).
3. You can call Lianja/VFP “Business procedures” that run on the server using Lianja.evaluate() (and Lianja.evaluateJavaScript() respectively in v2.0). So you can call validation, perform calculations and lookups on the server. Its seamless.
In the final release of v2.0 there is also an app.conf file which you can add to an App that “tells” the client what procedures/functions are handled by the server.
This provides transparent remote function calls that are made in the client that execute on the remote server.


ability to call server side procedures that are contained in libraries as follows.

Code:
// Client side JavaScript (notice the :: preceding myfunc()
var result = Lianja.evaluate("mylib::myfunc()");
Code:
// Server side Lianja/VFP in mylib.prg
proc myfunc()
    return "hello world"
endproc

We will be providing a way to register server side functions in the Web/mobile client so that they can be called as if they were JavaScript client side functions.

So for example you will be able to just do this in your client code.

Code:
// Client side JavaScript
var result = myfunc();

And myfunc() will be executed on the server.


Q:
I have a canvas section, with a textbox, used to set search criteria.
I have a form section bound to a virtual table. Data is loaded into a form section by requerying the section.
Next I need to populate a grid section (also bound to a virtual table) based on a value from the form section.
(Note: setting the relationship isn’t used because of multiple related fields).

This does not seem to be an issue in the desktop, although it is an issue in the web client do to asynchronous calls (which I believe is happening in this case). The form data most likely will not be loaded when the grid section is processed. I am using the value in the textbox to perform a separate query to get the value needed to populate the grid section (by requerying the secton). This is why I am attempting to figure out the best way to access the data.
How would you suggest I perform queries such as the one described with sqllookup?

A:
You cannot use sqlxxx() functions in the client.
The registration form code is all there so you can study it.
It calls business procs on the server.

You do not need to do anything at all with JSON if you build a business app using best practices.

There is no such thing as “a table is already open” in a web client/server app as this is stateless.

You can call a server side lianja/vfp procedure to perform your lookup. If you are doing that the proc is running on the server NOT the client.

Pages are made up of sections that can be related together (as you already know).

If you call the “requery” method on a section and give it a query expression then the data will be looked up on the server asynchronously.
When the call completes if data is found to match the query the section will be refreshed with the data then any child sections will be refreshed based on the data relationship between the sections.

This is no different to desktop operation.


Q:
What is a primary key in SQL
A:
A column NOT an expression

When you add a record to a child section the parent expression is used to maintain the child relationship.
An expression cannot be used to link the parent and child sections it is makes no sense.

If you want to do everything manually, fetch your data from your server side proc, populate the fields if you want to build things manually, then use requery() on the target child section to populate the child grid.

You can use the requery() method on a section to lookup records on the server and populate the section.



NonDesktop apps

Web and Mobile Apps are stateless.
What this means is that you cannot guarantee a persistent connection between the Web client and the server.

When requests are made by the browser these arrive on the server and are handled by worker processes based on their availability. Lianja uses connection pooling to optimize performance.
Not only does it use connection pooling for web requests it also uses ODBC connection pooling to handle Virtual Table access.

Therefore, executing a command only affects the server process that the command runs on. It has no effect on the client and the next Lianja.execute() may run in a completely different server context.


In Lianja v2.0 we have made it dramatically easier to share data in real time between multiple Lianja processes running in parallel.

In HTML5 Web/Mobile there is the concept of “localStorage” and “sessionStorage”.

In the Lianja v2.0 Desktop client “sessionStorage” is non persistent data that can be shared across multiple concurrent processes e.g. background processes gathering data from instruments or multiple Lianja windows on the desktop.

Access to data in sessionStorage is handled automatically for you so that concurrent reads, updates and removing of data items is atomic.

You access sessionstorage from the Lianja system object Lianja.sessionStorage.

Properties:

// The number of key/value pairs in sessionStorage
length

Methods:

Code:
// These should be quite explanatory
Lianja.sessionStorage.setItem(key, value)
value = Lianja.sessionStorage.getItem(key)
Lianja.sessionStorage.removeItem(key)
Lianja.sessionStorage.clear()

Lianja uses a shared memory segment to maintain sessionStorage.

Lianja will automatically keep the keys and their values consistent between each running process as you reference the items stored in SessionStorage. If you want to keep complex objects as the values for keys then use json_encode() and json_decode() to handle serialization and deserialization of the objects.

Code:
// in the main process App
private myobj = object("name" => "Barry", "company" => "Lianja")
Lianja.setItem("myobj", json_encode(myobj) )
Code:
// then in another process that needs to read objects from the main App window
private myobj = json_decode( Lianja.sessionStorage.getItem("myobj") )

Note that each time you call any of the methods or reference the length property the shared sessionStorage will be automatically kept current for you.


there is a “Session data changed” delegate and a “Session data changed interval” in App Settings.

Lianja will check for changes in the sessionStorage every #msecs and call the “Section data changed” if any changes in the sessionStorage have been made.
This is fast as a transaction sequence number is kept as part of the sessionStorage so no deserialization of data is required.
There is also a property called “datachanged” and “datachangedinterval” (in milliseconds) so this can be used by non GUI applications (background worker processes etc).


In Lianja v2.0 you also have several new classes that handle custom shared memory access and custom system semaphores.
New “SharedMemory” system class

Code:
m_shareddata = createObject("sharedmemory")

// attach will create the shared memory if it does not exist. Args are the "key" and the "size"
m_shareddata.attach("com.lianja.myshareddata", 64*1024)

// set key/value pairs
m_shareddata.setItem("mykey", somevalue)

// get value
m_value = m_shareddata.getItem("mykey")

New “SystemSemaphore” system class

Code:
m_sem = createObject("SystemSemaphore")

// setKey will create the SystemSemahore if it does not exist. 
m_sem.setKey("com.lianja.mysem")

// acquire exclusive access to a resource across multiple running processes
m_sem.aquire()

// do something...

// release access to the resource 
m_sem.release

Q:
Up until now, I have only created desktop apps. I am now planning on making my apps available for the web.
My current apps use VFP/Recital code.
I am also not used to programming for a client / server design.
I have read that you use javascript on the client and Lianja/VFP on the server side when you want to call server side procedures.
Here are just some of the questions I have.
1. When do you use rsp (Visual FoxPro Server) pages?
2. When do you use jssp (JavaScript Server) pages?
3. What and when is jquery, json or odata used?
4. How and why would you use each of these?

A:
Lianja is a complete Apps platform.
It is not just an IDE nor is it just a language.
You build Apps visually using “best practices“.

Apps are built out of pages and pages consist of sections etc.
You can build Web and Mobile Apps just as you can build desktop apps if you follow best practices. “Think NoCode“.
There are many pre-built sections that have a lot of built-in functionality. “Think Login page -> App Center -> Apps -> Pages -> UI Navigation“.

The Lianja HTML5/JavaScript Client for an Web/Mobile App is generated for you. It incorporates the LianjaWebFramework which manages all of the UI layout management, App and page navigation, data navigation, and all CRUD (Create Read Update Delete) operations on the sections (Forms, Grids etc) assembled into an App. You do not need to write any server side data access code. None.

The LianjaWebFramework is an HTML5/JavaScript library that takes care of the heavy lifting and handles automatic and transparent data binding between the client App running in the browser and your data which is on a remote server under the control of the Lianja Cloud Server.

The LianjaWebFramework was developed by ourselves in JavaScript and it uses jQuery, jQuery Mobile, Twitter Bootstrap and a variety of other JavaScript components some of which are commercial and some of which are open source licensed (Apache 2, BSD, LGPL).

There are occasions where you may want to build a custom UI that incorporates other UI widgets that you like.
You do this by building a WebViewWidget which is loaded into a WebView. The HTML5/JavaScript for the WebViewWidget can be dynamically generated by an .rsp page (Server side Lianja/VFP) or a .jssp page (Server side JavaScript). Both Lianja/VFP pages and JavaScript pages are part of the Lianja Cloud Server. (PHP will be included in this too very soon).

To answer your questions.
1. Do you know Lianja/VFP? Then write your dynamic HTML5/JavaScript code in that data centric language.
2. Do you know JavaScript? Then write your dynamic HTML5/JavaScript code in JavaScript.
3. You don’t need to know unless you are building custom WebViews.
4. See above.



NonDesktop apps

Q:
Hi, I am struggling a bit with the concept of which code runs where (if there is a doc which explains this please point me to it).
If I use php code (which I would assume is server-side) a message is popped up just fine in the IDE and in Desktop mode but I get nothing in web/tablet/mobile mode?

Code:
////////////////////////////////////////////////////////////////
// Event delegate for 'click' event
function Test_section1_field1_click()
{
        Lianja.ShowMessage("hello");
}

If php is indeed running server-side then surely this should never show a message at the client?
The other thing that I am not sure about is that “Lianja.ShowMessage” is not like any php code I have seen, surely this should be “$Lianja->ShowMessage”?
I get it now that delegates in JavaScript will work in web & desktop apps. It would appear then that PHP is kinda treated as a ‘client-side’ script for desktop apps?
Would the correct place to put server-side business logic then be JavaScript/Lianja Server Pages? How do you create those files? can they be debugged?
My questions are coming form the fact that I have used PHP/JavaScript extensively so am trying to relate the Lianja client/server bits to what I know.
A:
In PHP . Is used to add strings together so :: is required to be used.
Lianja/VFP, Python and JavaScript use . to reference properties and methods
whereas PHP uses ::

You currently use javascript on the client and Lianja/VFP on the server side when you want to call server side procedures.
The equivalent of .php pages are .rsp pages or .jssp pages as documented in the Developers Guide.
http://www.lianja.com/documentation/developers-guide

.php pages generate dynamic HTML content.

.rsp pages generate dynamic HTML content but with embedded Lianja/VFP data centric scripting.
.jssp pages generate dynamic HTML content using server side javascript.
These are used to render WebView sections in Lianja.

Most sections are automatically data bound as can be seen in the example Apps.
Server side PHP and Python scripts are on the roadmap. The others are already supported in Lianja Cloud Server.

you test your server side Lianja/VFP procedures in desktop mode.

You test and debug client side javascript delegates in the web app view.

if you are building desktop Apps, you can build them in Lianja/VFP, JavaScript, PHP or Python. The latter two are not yet supported in the Lianja Cloud Server but will be as detailed in the development roadmap.
Lianja is all about visually designing Apps out of pages and sections. This is all described in the developers guide and the videos. It’s not code centric, it is data centric with a high level of abstraction.



NonDesktop apps

For Web/tablet/mobile, delegates should be written in JavaScript. For desktop Apps, they can be JavaScript, Lianja/VFP, PHP or Python.


Q:
Where is the generated index.html?
A:
Web Apps are deployed to C:\Lianja\cloudserver\tenants\public\wwwroot\apps\
Desktop Apps to C:\Lianja\cloudserver\tenants\public\apps\


Assuming you’ve installed on C:, the database goes into its own folder in C:\Lianja\cloudserver\tenants\public\data,
the App goes into its own folder in C:\Lianja\cloudserver\tenants\public\wwwroot\,
Library files go into C:\Lianja\cloudserver\tenants\public\wwwroot\libra ry.
The App should include the generated index.html file.
For any prg files – you should copy the .dbo (pcompiled) version.


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.


in v1.3 any grid section filters that have {…} macros in them, these are expanded at the time of refreshing the grid.
This basically means that the filter itself is dynamically evaluated at the time the grid is refreshed. This works in all views; desktop, web and mobile.


in order to build and properly test native iOS Apps, this requires a Mac. There is no other solution as the tools required to build the native App are part of Apples Xcode toolchain and these only run on a Mac.

Native Android Apps on the other hand can be built and tested on Windows, Mac or Linux as the Android SDK runs in all of these operating systems.

Apache Cordova (latest version is 4.0) directly into the Lianja App Builder to facilitate building and testing native mobile Business Apps right inside the App Builder.


_screen is VFP desktop specific and does not exist in the web client.


Q:
As we start to look at porting our legacy APP or simply rebuilding it from scratch we will be endeavoring to use “best practices” and “No Code” where possible (albeit your Dev Team). As our development must be fast tracked we have a slight fear of creating & supporting Javascript for a Web deployment, (or creating anything meaningful in Javascript at all!).
A compiler out to pure Javascript harnessing “built-in functions in the Lianja Web Framework” as you say I think would be awesome. Writing a function in VFP and compiling out to Jscript would be a valuable tool to our Company. Lots of new guests on this forum as you are aware post about “why grids and forms” appear blank when testing under tablet or mobile.
When you said “providing the equivalent of the Lianja desktop client running native in tablets and phones” – what does this mean to the Developer?
A:
It means you will be able to write tablet and phone apps in Lianja/VFP. The database and scripting engine will be ported to android and iOS (subject to apple approval).
With all of the built-in Lianja/VFP functions (including createObject(), addObject() etc) in JavaScript the code looks very similar to what you are used to.
In Lianja/VFP
private obj
obj = createObject(“textbox”)
obj.backcolor = “pink”
obj.text = upper(“Hello world”)
In JavaScript
var obj;
obj = createObject(“textbox”);
obj.backcolor = “pink”;
obj.text = upper(“Hello world”);
And yes, by following best practices and using NoCode as much as possible it will reduce your code maintenance as the framework handles a lot of it.


Q:
With our understanding of “Lianja HTML5 Client” – Delegates:
In Web and Mobile Apps these delegates need to be written in JavaScript — the language of the browser.
http://www.lianja.com/resources/blog…tml5-client#p2
A really cool feature would be to provide a compiler from VFP code to compatible JavaScript code. Therefore a Desktop App can be used to build the Tablet or Mobile page which in turn are compiled out to pure JavaScript! A sensational feature to capture a much wider audience, assisting developers in having a better understanding of JavaScript, and encouraging the shift into Cloud Services.
A similar product claiming to be the alternative to the end of product life for VFP has included such a compiler but compiles out to its native language.
A:
Building Web / Mobile Apps requires a traditional client / server design approach.
What at we have done is provide the equivalent of the VFP base classes and many of the VFP built-in functions in the Lianja Web Framework. This allows you to create objects, call their methods and get/set their properties just as you would in VFP, albeit in javascript.
Everthing in Lianja revolves around the Lianja Object Model and ART (Actions, Rules and Transitions).
All data processing (CRUD operations) is performed on the server.
You can use Lianja.evaluate() in javascript to call server side procedures that are all written in VFP.
During the course of next year we will be providing the equivalent of the Lianja desktop client running native in tablets and phones. That is the next phase of our development.


Q:
I configured Lianja extension in IIS(7.5). I can login via a web browser using http://localhost/ortno/login.rsp where portno is 8001 but unable to login though default port 80. How can I login with htt://localhost/login.rsp ? What settings are required ?
A:
If you have correctly configured the IIS extension as per the doc wiki then you do not need to specify a port number. You also need to disable port 80 in the lianja server settings so it does not interfere with IIS. This is the default after installation.


Q:
I build a test app by following the instructions in “Getting started 1” example. The application has customers detail related to orders grid section and order_details grid section, tables from southwind database. The app is working with related data correctly in development mode but in web view related grids for orders and order_details are not shown. How can I display these related grid sections in order app modes like web / tablet view?
A:
You need to deploy your database that your web app uses.
?if you have any code in your app, it has to be written using Javascript to run in web/mobile.
This will be so until we get Native Apps (on the roadmap for next year), which VFP code will be able to be used.


Q:
1. Lianja.evaluate/execute() can be called from javascript delegates and will execute server-side VFP code only.
2. Lianja.execPHP/execJavaScript() can execute library functions in those languages, where the library has been loaded with loadLibrary().
For (2) above though, it seems that Lianja.execXX only works when called from VFP and fails in javascript/php delegates, so:
JavaScript delegate -> VFP server = OK
VFP delegate -> JavaScript server = OK
Javascript delegate-> JavaScript server = NOT OK
A:
server-side PHP and Python support is scheduled for Cloud Server 1.5.
When this is released you will have several new client-side methods available.
Lianja.evaluatePHP()
Lianja.evaluatePython()
JavaScript is already built into the Cloud Server (Google v8 engine) and can be used to generate dynamic content with .jssp pages.
i will add a new method in v1.5 to simplify calling server-side JavaScript functions.
Lianja.evaluateJavaScript()
My intention is to add some new App setting attributes “References” which is a ; separated list of custom libraries that will be loaded automatically for you when a connection is made and the App is loaded. Same will happen in a desktop App.


you can read the code for the “User Registration Form” which shows you how to handle custom client/server calls i.e.
JavaScript client –> Lianja/VFP server side procedures.
In *most* cases you do not need to build any “Custom” or “Canvas” sections.
The following standard sections are already supported in the Web Client.
– Form
– Grid
– Attachments
– WebView
– Image Strip
– TabView
– Canvas (JavaScript)
– CatalogView
– Custom (JavaScript)
– Report
– Calendar
– Charts
These sections are all data bound. There is no special code to write to display and edit your data.


Delegates can be written in any of the supported scripting languages.
“Expressions” in the attributes need to be written in the language of the database engine, just as you would in any database e.g. MSSQL, MySQL, Oracle etc. They all have their own “scripting language”.
The Lianja/VFP scripting language sits on top of all of these and provides a common language that can be used against any data source.
Steps:
1. Write a JavaScript library.
2. Load it in the load/ready delegate.
loadLibrary(“myjavascriptlibrary.js”)
3. Now you call call your functions.
result = execJavaScript(“myfunc()”)

This works the same with .php files or .py files too.
loadLibrary(“myjavascriptlibrary.php”)
result = execPHP(“myfunc()”)
loadLibrary(“myjavascriptlibrary.py”)
result = execPython(“myfunc()”)

Lianja will marshall the result of the function call between the various scripting languages.
In v1.2.4 the library filename can be prefixed with lib:/ or app:/ to load from the library directory or the app directory.
When adding Javascript libraries into a Web App you specify the script tags in the “Include in HTML HEAD” file which you can edit in the App Settings by clicking the “…”.