Page 1 of 1

JSON external data transfer

Posted: Tue Jun 14, 2016 11:31 pm
by Jiri
We have requirements to exchange some data between LANSA web application and 3rd party. The communication can be single way:
LANSA issue request GET (...) and should receive back some data in JSON format.
JSON is nativelly used by WAMs or VL-WEB in V14, therefore it should be possible to process them directly (without need to use Integrator). What is the simplest method how to do it?
Does anybody have an example?

Re: JSON external data transfer

Posted: Wed Jun 15, 2016 1:35 am
by jyoung
Hi Jiri,

We just hooked up with a 3rd party http api posting and receiving data, not JSON though.

If you are "getting" the data from the client browser take a look at the #PRIM_WEB.HttpRequest. You can see an example of it in the xDemoWebWeatherItem in the samples.

http://docs.lansa.com/14/EN/LANSA016/PR ... EQUEST.htm

We could not use that however, because the API we were calling does not support CORS, so the request had to come from the server. Unfortunately #PRIM_WEB is not available in server modules so we ended up having to use Integrator.

Hope this helps,
Joe

Re: JSON external data transfer

Posted: Fri Jun 24, 2016 9:45 pm
by Jiri
Any other idea? JSON is format proferred by LANSA and used in WAMs, VL-WEB... why it is problem to process JSON from other source, if it will pass LANSA naming rules??

Re: JSON external data transfer

Posted: Sat Jun 25, 2016 10:27 am
by marco.kam
Hi Jiri,

The weather widget example that @jyoung mentioned is probably the best place to see some sample code.

There are a few primitives that you can use to both generate JSON (to post to a 3rd party service) as well as read and extract information from JSON into RDMLX.

From the documentation here:
http://docs.lansa.com/14/EN/LANSA016/

Please refer to the following
PRIM_WEB.HttpRequest
PRIM_WEB.HttpResponse
PRIM_WEB.Json
PRIM_WEB.JsonArray
PRIM_WEB.JsonBoolean
PRIM_WEB.JsonElement
PRIM_WEB.JsonNumber
PRIM_WEB.JsonObject
PRIM_WEB.JsonString

Here is some relavant code:

Code: Select all

* -----------------------------------------------------
* Creating JSON (can be used to post to other services)
* -----------------------------------------------------
* Create a Json object as the root element
#Json.CreateRootObject Result(#Root)
 
* Set the values for the name and title properties on the root object
#Root.InsertString Key('name') String('Marco')
#Root.InsertString Key('title') String('Principal Consultant')
 
* Create an array for the property 'skills'
#Root.InsertArray Key('skills') Result(#Skills)
 
* Insert a new skill object into the skills array
#Skills.InsertObject Result(#Skill)
* Set the values for the name and years properties on the skill object
#Skill.InsertString Key('name') String('LANSA')
#Skill.InsertNumber Key('years') Number(12)
 
* Insert a new skill object into the skills array
#Skills.InsertObject Result(#Skill)
* Set the values for the name and years properties on the skill object
#Skill.InsertString Key('name') String('javascript')
#Skill.InsertNumber Key('years') Number(5)


* -----------------------------------------------------
* Making a request and processing JSON
* -----------------------------------------------------
#Request.URL := <url to 3rd party service>

Evtroutine Handling(#Request.Completed)
If (#Request.Response *IsNot *null)
Case (#Request.Response.StatusCode)
When (= 200)
* Get the JSON from the response
       #Json := #Request.Response.Content

* Loop through the array in the response
       For Each(#Employee) In(#Json.RootItem)
              * Get the value of the id on each object in the array
#Id := #Employee<"id">.AsString
Endfor
Otherwise
* HTTP error
Endcase
EndifEndroutine
The first set of code will generate a JSON object that looks like this:
{
"name": "Marco Kam",
"title": "Principal Consultant",
"skills": [{
"name": "LANSA",
"years": 12
}, {
"name": "javascript",
"years": 5
}]
}

The second set of code will make a request to a 3rd party API, then parse the JSON that comes back. In this case it is assuming that an array of employees is coming back.

Note that #PRIM_WEB is only available in Web Page Objects. The code is generating javascript on the client side, and as a result it can only communicate with 3rd party APIs if the service supports CORS (https://developer.mozilla.org/en-US/doc ... ntrol_CORS).

There is no CORS restriction on the server, but as @jyoung mentioned, you'll have to use Integrator if you are making HTTP requests on the server side.

Re: JSON external data transfer

Posted: Thu Oct 13, 2016 7:52 pm
by MikeS
Hi Marco

I can see from your example how you reference the root elements of the JSON document, but can you clarify how I go about referencing the 'nested' array elements of the Skills array within the Employee element.

Thanks

Mike

Re: JSON external data transfer

Posted: Fri Oct 14, 2016 11:32 am
by Stewart Marshall
Hi Mike

All VL Json objects can act as a collection. This means you can try to iterate over an element whether it's an array or not. All you need is the FOR command.

In this case, you can directly access the "Skills" object created for the employee, which is the root item. Once you have a reference to the element, you can get the individual values from the elements

Code: Select all

For Each(#Skill) In(#Json.RootItem.Item<"Skills">)
    #Name := #Skill.Item<"Name">.AsString
    #Years := #Skill.Item<"Years">.AsString
...
EndFor
Here's a complete example

Code: Select all

Begin_Com Role(*EXTENDS #PRIM_WEB) Height(712) Width(1024)

Define_Com Class(#Prim_web.Json) Name(#Json)
Define_Com Class(#Prim_web.JsonObject) Name(#Root) Reference(*Dynamic)
Define_Com Class(#Prim_web.JsonArray) Name(#Skills) Reference(*Dynamic)

Define_Com Class(#PRIM_LIST) Name(#List1) DisplayPosition(1) Left(8) Parent(#COM_OWNER) TabPosition(1) Top(8) Height(394) Width(439) ColumnLines(False) RowLines(False)
Define_Com Class(#PRIM_LIST.String) Name(#ColumnLabel1) DisplayPosition(1) Parent(#List1) ColumnWidth(382) ColumnUnits(Proportion) ColumnCaption('Click here to get skills') ColumnCaptionType(Caption)

Evtroutine Handling(#COm_owner.CreateInstance)

* Create a Json object as the root element
#Root <= #Json.CreateRootObject

* Set the values for the name and title properties on the root object
#Root.InsertString( 'Name' 'Marco' )
#Root.InsertString( 'Title' 'Principal Consultant' )

* Create an array for the property 'skills'
#Skills <= #Root.InsertArray( 'Skills' )

#Com_owner.AddSkill( LANSA 12 )
#Com_owner.AddSkill( "JavaScript" 5 )
#Com_owner.AddSkill( "HTML" 10 )

Endroutine

Mthroutine Name(AddSkill)
Define_Map For(*Input) Class(#Prim_alph) Name(#Name)
Define_Map For(*Input) Class(#Prim_nmbr) Name(#Year)
Define_Map For(*Result) Class(#Prim_web.JsonObject) Name(#Skill) Pass(*By_Reference)

* Insert a new skill object into the skills array
#Skill <= #Skills.InsertObject

#Skill.InsertString( 'Name' #Name )
#Skill.InsertNumber( 'Years' #Year )

Endroutine

Evtroutine Handling(#ColumnLabel1.ColumnClick)

* Loop through the "skills" object array in the response
For Each(#Skill) In(#Json.RootItem.Item<"Skills">)

Add_Entry To_List(#List1)

#ColumnLabel1.CurrentItem.Value := #Skill.Item<"Name">.AsString + " " + #Skill.Item<"Years">.AsString

Endfor

Endroutine

End_Com

Re: JSON external data transfer

Posted: Fri Oct 14, 2016 11:53 pm
by MikeS
Hi Stewart

Thanks great. Thanks for your speedy response.

Mike

Re: JSON external data transfer

Posted: Thu Mar 02, 2017 11:53 pm
by Jiri
Hello,
Cou please give as an example of HTTP request with basic authentication? The published is only to unauthorised server.
For authorisation, it is necessary add some information to HTTP header (may vary by requirements), for exaple some user and password.

Re: JSON external data transfer

Posted: Fri Mar 03, 2017 10:19 am
by Stewart Marshall
Hi Jiri

You can access the headers of an HTTP request using the Headers property.

Code: Select all

Define_Com Class(#Prim_web.HttpRequest) Name(#Request)
#Request.Headers.Add( "Key" "Value" )
Sorry, but I don't have any specific examples.

Regards

Re: JSON external data transfer

Posted: Fri Jun 09, 2017 10:08 pm
by Jiri
Anyone have an example, how to pass basic authentication (User & Password) to LANSA HTTP request header?
On web, there is lot of examples for PHP, Nette etc. but we are not able to implement it il LANSA.
If the authorisation data (User and Password) are not passed by browser, browser will ask for it. We need to omit this step - means pass the info in HTTP header.
The mentioned method:
#Request.Headers.Add( "Key" "Value" )
works, but we did not success with passing the values.

Re: JSON external data transfer

Posted: Thu Aug 17, 2017 6:07 pm
by tsupartono
LANSA now has a server-side native RDML HTTP request and JSON data handling capabilities.
The features require EPC141050:
http://www.lansa.com/support/notes/epc/epc141050.htm

Please see the following documentation on Web Services for more details:
http://docs.lansa.com/14/en/lansa018

See also the following note on the security vulnerability associated with performing web service invocation from the client side (browser via JavaScript):
http://docs.lansa.com/14/en/lansa018/#l ... 1_0185.htm