Capabilities and practical application of LyciaWeb API

This is an overview of the different possibilities in setting up connection between 4GL application (as web client) and Web API (as web service).  A few distributed application examples are provided here. Lycia 4GL is used both for client and server parts in these code samples but any part can be easily replaced with any other modern programming language.

Any 4GL function can be published as web service without any coding or code reading at all. LyciaWeb will translate HTTP requests to 4GL function calls, interaction statement actions and field updates.  By default, any deployed application can be called this way. For security reasons only functions starting with the "web_" prefix can be called. The prefix pattern can be changed during runtime.

The API is accessed via /sapi and /api URLs of LyciaWeb, for stateful and stateless usages respectively. For example, in default installation the stateful Web API can be accessed from the same computer with URLs with the http://localhost:9090/LyciaWeb/sapi prefix.

 

The Lycia Web API application is a standard Java servlet and can be run on any standard Java servlet container. Session tracking is done by means of the container. So it has access to all the container options for session handling. By default, session is stored in cookies (the JSESSIONID parameter), but it can be also URL parameter or SSL session.

 

The format of URL for access to stateful API should be:

http://{host}:{port}/LyciaWeb/sapi/{guiserver_port}/{application}

or

http://{host}:{port}/LyciaWeb/sapi/{command}/{name}?{arg1}={val1} &{arg2}={val2}...

where

{host}

host name, e.g. localhost

{port}

port number, which equals 9090 by default

{guiserver_port}

port number, which equals 9090 by default

{application}

application name from folder ‘progs‘ of Application Server

{command}

command for execution by current application. E.g. set, get, setfocus, callmethod, closewindow, etc.

{name}

command parameter, like function name, field name, etc.

{arg…}

parameter name

{val…}

parameter value

 

This is the example of the link that can be used to start the application:

http://localhost:9090/LyciaWeb/sapi/cms/cms?user=username&passwor d=12345

 

Servlet container is a part of a web server that interacts with the servlets. Among its known implementations, there are:

Apache Tomcat

Oracle Weblogic

IBM WebSphere

GlassFish

Jetty

JBoss, etc.

 

The best way to write a web function is to write a new function inside which an old function is called. This will help you to avoid changing all the names in the calls to the old function inside your 4GL project. Name the function web_<someone>, it should have the same name for security reasons.

This example illustrates how to call 4GL application through another 4GL application.

Let's assume that there is some 4GL application called web_srv_func_sum.exe which we will use as a test application. This application contains additional function web_f_sum:

function web_f_sum(a, b)

  define a,b int

  return a + b;

end function

 

To invoke this function in another application, we establish the web session and call the application web_srv_func_sum.exe.

main

   define  sesweb.Session

   define  r int

   call ses.setLyciaApplication("localhost:9090/LyciaWeb/sapi",

"default-1889","web_srv_func_sum.exe")

   call ses.callMethod("web_f_sum", 5,7) returning r

   display"returns : ", r

end main

 

There is an option to include nested arrays in the code. The example below shows it can be realized within the code (Server side application web_srv_func_array2d.exe):

main

  define str string

  define ch CHAR

  define a INTEGER

 

  let a = 25

  display "web_f_sum(2,3) returns ", web_f_sum(2, 3)

 

  prompt "Input the value:" for str

 

  if str is null then

    display "string was not entered - exit"

    exit program 0

  end if

 

  display "WAIT 3 sec"

  sleep 3

end main

 

function web_f_sum(a, b)

  define a,b int

 

  return a +b;

end function

 

function web_matrix_int4x4_tranform(arr) -- the function is called from client side

define  arr, res array[4, 4] of int

define  i, j int

 

for i=1 to 4 step 1

j = 1 to 4 step 1

let  res[i, j] = arr[j, i]

end for

end for

 

return res

end function

 

The program from the client side will look as follows:

main

   define  sesweb.Session

   define  rq web.Request

   define  rs web.Response

   define  r int

 

   define  arr, res array[4, 4] of int

 

   define  i, j int

 

   call  ses.setLyciaApplication("localhost:9090/LyciaWeb/sapi","default-1889", "web_srv_func_array2d.exe")

   call ses.get() returning rs

   display "get: " , rs.getBody()

 

   call ses.get() returning rs

   display "get: ", rs.getBody()

 

   sleep 20

 

   display "call web_f_sum(102, 304)"

   call ses.callMethod("web_f_sum", 102, 304) returning r

 

   display "returns : ", r

 

   for i=1 to 4 step 1

     for j=1 to 4 step 1

       let  arr[i, j] = 4*(j-1)+i-1

     end for

   end for

 

   for i=1 to 4 step 1

     display arr[i, 1], ", ", arr[i, 2],", ", arr[i, 3],", ", arr[i, 4]

   end for

   display ""

 

   call ses.callMethod("web_matrix_int4x4_tranform", arr) returning res

   display "result: ", res

 

   for i=1 to 4 step 1

     display res[i, 1], ", ", res[i, 2], ", ", res[i, 3], ", ", res[i,4]

   end for

     

end main

 

This program illustrates interaction statements usage for server side:

main

   define nam char(20),

          age int,

          mstat char(1),

          total char(30)

 

   options input wrap

   options message line last

 

   open form f1 from "fields_fm"

   display form f1

 

   display "Press F1 to call the function" at 2, 2 ATTRIBUTES(GREEN)

   display "!" TO b_ok     

   input nam, age, mstat, total from pers_rec.*

    

     ON KEY (F1)

        message "KEY EVENT F1"    

        let total = trim(nam)||" "||  age ||" "||trim(mstat)

        display total to formonly.total  

  end input

 

end main

 

The interaction statements usage for client side:

main

   define  ses web.Session

   define  rq web.Request

   define  rs web.Request

   define  r int

 

   call  ses.setLyciaApplication("localhost:8080/LyciaWeb/sapi", "default-1889", "web_srv_form1.exe")

 

   call ses.get() returning rs

   display "get1: ", rs.getBody()

 

   call ses.set("name")

  

   call ses.key("nextfield")

   call ses.get() returning rs

   display "get2: ", rs.getBody()

  

   call ses.set("33")

  

   call ses.key("nextfield");

  

   call ses.set("M")

   call ses.get() returning rs

   display "get3: ", rs.getBody()

  

   call ses.key("F1")

   call ses.get() returning rs

   display "get4: ", rs.getBody()

  

   call ses.key("nextfield")

   call ses.get() returning rs

   display "get5: ", rs.getBody()

    

   call ses.key("accept")

end main

 

There is another lightweight mode for automatic program execution similar to Web API which does not require deployment to application server and does not involve any network interaction. It is called headless mode in this document. The application can be run simply from terminal in headless mode if QX_HEADLESS_MODE environment variable is set to 1. It will receive requests to its standard input and send responses to standard output. So some timed automatic tasks implemented in 4GL may be run via this mode using some shell script.

 

Below are some examples of interaction in the command line for the headless mode in XML.

 

The sample application in cvs: web_srv_form1.exe

 

In the given code, the symbols '<<<' and '>>>' mean server response and client response respectively. Customers can set their own in the end of the code to identify the response direction.

<?xml version="1.0" encoding="utf-8"?>

<response><openwindow>SCREEN</openwindow><displayform>f1</displayform><displayat

 row="2" col="2" attr="green">Press F1 to call the function</displayat><displayt

o field="b_ok" attr="">!</displayto><input><nam/><age>0</age><mstat/><total/></i

nput><setfocus>formonly.nam</setfocus><interact_dialog/></response>

<<<

 

<?xml version="1.0" encoding="utf-8"?>

<fglevent name="nextfield"/>

>>>

 

<?xml version="1.0" encoding="utf-8"?>

<response><setfocus>formonly.age</setfocus><interact_dialog/></response>

<<< 

 

<?xml version="1.0" encoding="utf-8"?>

<setvalue>12</setvalue>

>>>

 

<?xml version="1.0" encoding="utf-8"?>

<fglevent name="nextfield"/>

>>>

 

<?xml version="1.0" encoding="utf-8"?>

<response><setfocus>formonly.mstat</setfocus><interact_dialog/></response>

<<< 

 

<?xml version="1.0" encoding="utf-8"?>

<setvalue>S</setvalue>

>>> 

 

<?xml version="1.0" encoding="utf-8"?>

<fglevent name="f1"/>

>>> 

 

<?xml version="1.0" encoding="utf-8"?>

<response><displayto field="total" attr="">&#32;            </displayto><interact_dialog/></response>

<<< 

 

 <?xml version="1.0" encoding="utf-8"?>

<fglevent name="nextfield"/>

>>> 

<?xml version="1.0" encoding="utf-8"?>

<response><setfocus>formonly.total</setfocus><interact_dialog/></response>

<<<

 

<?xml version="1.0" encoding="utf-8"?>

<fglevent name="accept"/>

>>>

 

Contact Us

Privacy Policy

Copyright © 2024 Querix, (UK) Ltd.