Skip to main content

Hi Unifacers,

In the current IT world driven from integrations could it be of interest to the Uniface world to have a standardized mode to develop and deploy plugins to Uniface apps? IMHO...YES!

I do not remember this specific subject being discussed, but it could be I was not part of the discussion or I have simply forgotten about it!

Pro...? Cons...? Pitfalls...? Tips...? Suggestions...?

Let's argue about it!

Gianni

Hi Unifacers,

In the current IT world driven from integrations could it be of interest to the Uniface world to have a standardized mode to develop and deploy plugins to Uniface apps? IMHO...YES!

I do not remember this specific subject being discussed, but it could be I was not part of the discussion or I have simply forgotten about it!

Pro...? Cons...? Pitfalls...? Tips...? Suggestions...?

Let's argue about it!

Gianni

Hi Gianni,

I'm not sure about what you mean, but I understand it as creating "Uniface"-plugins for Uniface-programs.
So, it should be a self contained uar that can be plugged in using the asn file. The plugin may have its own asn-file if needed.

Here an example of an operation-trigger of a service (the same can be used for forms) in the self-contained uar. The INIT-operation changes the $variation to one used by the self-contained uar to  find messages etc., the CLEANUP-trigger sets the $variation back to the $variation used by the calling program and the SENDCUSTOMER is  quit by EXIT(0) so that the CLEANUP-operation is activated:

operation INIT
  $VARTEMP$=$variation
  $variation="SC"
end; INIT

operation CLEANUP
  $variation=$VARTEMP$
end; INIT


operation SENDCUSTOMER
params
........
  numeric OUTSTATUS  : OUT
endparams

  activate "EG_WEBSERVICE".SENDCUSTOMER(.....)
  If(OUTSTATUS < -49)
  else
    if()........
  endif
  exit(0)
end; SENDCUSTOMER

There is a while since I thought about this, but I hope that I remember correctly. In the above specific example the SENDCUSTOMER calls a web-service, so the integration is done even further out from the Uniface uar.

This was my contribution to get more comments.


Regards RogerW.



Hi Gianni,

I'm not sure about what you mean, but I understand it as creating "Uniface"-plugins for Uniface-programs.
So, it should be a self contained uar that can be plugged in using the asn file. The plugin may have its own asn-file if needed.

Here an example of an operation-trigger of a service (the same can be used for forms) in the self-contained uar. The INIT-operation changes the $variation to one used by the self-contained uar to  find messages etc., the CLEANUP-trigger sets the $variation back to the $variation used by the calling program and the SENDCUSTOMER is  quit by EXIT(0) so that the CLEANUP-operation is activated:

operation INIT
  $VARTEMP$=$variation
  $variation="SC"
end; INIT

operation CLEANUP
  $variation=$VARTEMP$
end; INIT


operation SENDCUSTOMER
params
........
  numeric OUTSTATUS  : OUT
endparams

  activate "EG_WEBSERVICE".SENDCUSTOMER(.....)
  If(OUTSTATUS < -49)
  else
    if()........
  endif
  exit(0)
end; SENDCUSTOMER

There is a while since I thought about this, but I hope that I remember correctly. In the above specific example the SENDCUSTOMER calls a web-service, so the integration is done even further out from the Uniface uar.

This was my contribution to get more comments.


Regards RogerW.


Hi Roger,

Yes, Uniface plugins for Uniface applications!
A self-contained UAR is a piece of my idea too...
You configure the UAR, and probably few other lines, in your ASN file and voilà, it works...You start to use it!
On top of your description:
- same way like $variation also $language should be saved/restored
- all operations should always exit($status) as:  0 = OK, <0 = An error, >0 = A warning

Anyhow I have already other specs in mind but I would like to hear from unifacers first...
I strongly feel probably I am not the first one to think about this concept.

Thanks for your reply.

Gianni


Hi Gianni,

I'm not sure about what you mean, but I understand it as creating "Uniface"-plugins for Uniface-programs.
So, it should be a self contained uar that can be plugged in using the asn file. The plugin may have its own asn-file if needed.

Here an example of an operation-trigger of a service (the same can be used for forms) in the self-contained uar. The INIT-operation changes the $variation to one used by the self-contained uar to  find messages etc., the CLEANUP-trigger sets the $variation back to the $variation used by the calling program and the SENDCUSTOMER is  quit by EXIT(0) so that the CLEANUP-operation is activated:

operation INIT
  $VARTEMP$=$variation
  $variation="SC"
end; INIT

operation CLEANUP
  $variation=$VARTEMP$
end; INIT


operation SENDCUSTOMER
params
........
  numeric OUTSTATUS  : OUT
endparams

  activate "EG_WEBSERVICE".SENDCUSTOMER(.....)
  If(OUTSTATUS < -49)
  else
    if()........
  endif
  exit(0)
end; SENDCUSTOMER

There is a while since I thought about this, but I hope that I remember correctly. In the above specific example the SENDCUSTOMER calls a web-service, so the integration is done even further out from the Uniface uar.

This was my contribution to get more comments.


Regards RogerW.


Hi, 

You have to check that the "operation CLEANUP" is executed. there was some kind of problems there. But it's probably executed whatever you return in exit($status)....
I usually use the outstatus out-parameter, which also can be checked.
And Yes, $language could be crucial, depending on the situation.


operation SENDCUSTOMER
params
........
  numeric OUTSTATUS  : OUT
endparams

  activate "EG_WEBSERVICE".SENDCUSTOMER(.....)
  If($status < -49)
    OUTSTATUS = $status
  else
    if()........
    ;Set OUTSTATUS
  endif
  exit(0)
end; SENDCUSTOMER

Regards RogerW.


Hi Gianni,

I'm not sure about what you mean, but I understand it as creating "Uniface"-plugins for Uniface-programs.
So, it should be a self contained uar that can be plugged in using the asn file. The plugin may have its own asn-file if needed.

Here an example of an operation-trigger of a service (the same can be used for forms) in the self-contained uar. The INIT-operation changes the $variation to one used by the self-contained uar to  find messages etc., the CLEANUP-trigger sets the $variation back to the $variation used by the calling program and the SENDCUSTOMER is  quit by EXIT(0) so that the CLEANUP-operation is activated:

operation INIT
  $VARTEMP$=$variation
  $variation="SC"
end; INIT

operation CLEANUP
  $variation=$VARTEMP$
end; INIT


operation SENDCUSTOMER
params
........
  numeric OUTSTATUS  : OUT
endparams

  activate "EG_WEBSERVICE".SENDCUSTOMER(.....)
  If(OUTSTATUS < -49)
  else
    if()........
  endif
  exit(0)
end; SENDCUSTOMER

There is a while since I thought about this, but I hope that I remember correctly. In the above specific example the SENDCUSTOMER calls a web-service, so the integration is done even further out from the Uniface uar.

This was my contribution to get more comments.


Regards RogerW.


Hi Roger,

I made already few checks with a service.
As of today (9.7.05.030) cleanup() is always called also when service is exiting with $status less than zero.
Here logs of my three checks respectively with -1, 0, 1:


Starting GT0 mode...current $variation and $language:
USYS
USA
Into INIT() operation...
Into TEST() operation...Called with pStatus=1
MYVAR
MYL
Into CLEANUP() operation...

GT0: Result outside:
$status = 1
USYS
USA


Starting EQ0 mode...current $variation and $language:
USYS
USA
Into INIT() operation...
Into TEST() operation...Called with pStatus=0
MYVAR
MYL
Into CLEANUP() operation...

EQ0: Result outside:
$status = 0
USYS
USA


Starting LT0 mode...current $variation and $language:
USYS
USA
Into INIT() operation...
Into TEST() operation...Called with pStatus=-1
MYVAR
MYL
Into CLEANUP() operation...
LT0: Result outside:
$status = -1
USYS
USA


Regards,
Gianni


Hi Unifacers,

In the current IT world driven from integrations could it be of interest to the Uniface world to have a standardized mode to develop and deploy plugins to Uniface apps? IMHO...YES!

I do not remember this specific subject being discussed, but it could be I was not part of the discussion or I have simply forgotten about it!

Pro...? Cons...? Pitfalls...? Tips...? Suggestions...?

Let's argue about it!

Gianni

Hi Gianni

We don't have plugins as you mention them.
But I try to get our application modular

So all operation should have the same number of parameters.

params  string v_VAL_IN   :IN      ;UIL: input data
  string v_VAL_OUT :OUT ;UIL: output data
  string v_PARA :INOUT ;UIL: control data
  string $GDA$ :INOUT ;UIL: global data area
endparams


UIL = UnifAceItemList
The $GDA$ parameter is not yet used in our application, it's for the purpose of transfering environment information through the instances if there are (official) no global objects availble like in services. All operations are recursiv called with this $GDA$ without modifing (directly) the content of $GDA$

Example: "Create a person" (without any error handling&co)

v_VAL_IN = ""
putitem/id v_VAL_IN,"PER_NAM1","Meier"
putitem/id v_VAL_IN,"PER_NAM2","Peter"
v_PARA = ""
putitem/id v_PARA,"COMMIT",1 ; The instance should do a commit on it's own
activate v_inst."PER_CRT"(v_VAL_IN,v_VAL_OUT,v_PARA,$GDA$)
v_PER_NR= $item("PER_NR",v_VAL_OUT)


There a few predefined operation (via include)
One of them is "GENERAL" to do some background things in an instance.
e.g. get the list of avaible*) operations  in a component like a reflection interface
*) Only those wich are defined by default ot declared in a defines trigger

And there is always a component local variable (beside $GDA$) called $INSTANCEPROERTIES$
This holds properties of an instance wich could used at runtime.
A few of this properties are generated a compile tim (like the list of operations), some could be set and read at runtime via special globale procedures. To do this "remote" from another instance, there are two simple operations "SET_INSTANCEPROPERTIES" and "GET_INSTANCEPROPERIES"


This are some operation we will define by default 🙂


CB ; CallBack-Interface
EDIT ; Default interactive EDIT
GDA_GET ; Get and SET $GDA$ from outside
GDA_SET ;-"-
GENERAL ; Some general things, addressed by a parameter TOPIC
INSTANCEPROPERTIES_GET ; GET and SET $INSTANCEPROPERIES$
INSTANCEPROPERTIES_SET ; -"-
OP_CPT_INFO ; Get Information about the instance
OP_GET_CLL_HANDLE ; Get the collection handle of a entity
OP_GET_OCC_HANDLE ; Get a occournce handle of a entity
...
xxx


BTW: About INIT and CLEANUP
Our framework contains an "instance and transaction monitor"
So (I hope) all newinstance and deleteinstance are running over this "monitor".
Every time a instance is about to kill, GENERAL will called with the topic "CLEANUP_AHEAD".
So a instance have the opportunity to save all values in database an do other cleanup things.
To do is in this way is important as UnifAce sometimes kills dependig instances at the" wrong" moment. With "CLEANUP_AHEAD" all instance are still alive and can be called.
Think about protocol instance. Maybe UnifAce will destroy the protocol (instance) before doing the last chance write and then ...?  🙂


There are much more things behind the curtain.

Hope I could gave you a hint what one can do to make a component plugable 🙂


Ingo


Hi Gianni

We don't have plugins as you mention them.
But I try to get our application modular

So all operation should have the same number of parameters.

params  string v_VAL_IN   :IN      ;UIL: input data
  string v_VAL_OUT :OUT ;UIL: output data
  string v_PARA :INOUT ;UIL: control data
  string $GDA$ :INOUT ;UIL: global data area
endparams


UIL = UnifAceItemList
The $GDA$ parameter is not yet used in our application, it's for the purpose of transfering environment information through the instances if there are (official) no global objects availble like in services. All operations are recursiv called with this $GDA$ without modifing (directly) the content of $GDA$

Example: "Create a person" (without any error handling&co)

v_VAL_IN = ""
putitem/id v_VAL_IN,"PER_NAM1","Meier"
putitem/id v_VAL_IN,"PER_NAM2","Peter"
v_PARA = ""
putitem/id v_PARA,"COMMIT",1 ; The instance should do a commit on it's own
activate v_inst."PER_CRT"(v_VAL_IN,v_VAL_OUT,v_PARA,$GDA$)
v_PER_NR= $item("PER_NR",v_VAL_OUT)


There a few predefined operation (via include)
One of them is "GENERAL" to do some background things in an instance.
e.g. get the list of avaible*) operations  in a component like a reflection interface
*) Only those wich are defined by default ot declared in a defines trigger

And there is always a component local variable (beside $GDA$) called $INSTANCEPROERTIES$
This holds properties of an instance wich could used at runtime.
A few of this properties are generated a compile tim (like the list of operations), some could be set and read at runtime via special globale procedures. To do this "remote" from another instance, there are two simple operations "SET_INSTANCEPROPERTIES" and "GET_INSTANCEPROPERIES"


This are some operation we will define by default 🙂


CB ; CallBack-Interface
EDIT ; Default interactive EDIT
GDA_GET ; Get and SET $GDA$ from outside
GDA_SET ;-"-
GENERAL ; Some general things, addressed by a parameter TOPIC
INSTANCEPROPERTIES_GET ; GET and SET $INSTANCEPROPERIES$
INSTANCEPROPERTIES_SET ; -"-
OP_CPT_INFO ; Get Information about the instance
OP_GET_CLL_HANDLE ; Get the collection handle of a entity
OP_GET_OCC_HANDLE ; Get a occournce handle of a entity
...
xxx


BTW: About INIT and CLEANUP
Our framework contains an "instance and transaction monitor"
So (I hope) all newinstance and deleteinstance are running over this "monitor".
Every time a instance is about to kill, GENERAL will called with the topic "CLEANUP_AHEAD".
So a instance have the opportunity to save all values in database an do other cleanup things.
To do is in this way is important as UnifAce sometimes kills dependig instances at the" wrong" moment. With "CLEANUP_AHEAD" all instance are still alive and can be called.
Think about protocol instance. Maybe UnifAce will destroy the protocol (instance) before doing the last chance write and then ...?  🙂


There are much more things behind the curtain.

Hope I could gave you a hint what one can do to make a component plugable 🙂


Ingo

Hi Ingo,

thanks for your detailed description of the kind of modularization you are working with daily.

Your modularization is for your application...my post is about something much more basic level!

Let's think about:
- any integration with a piece of software owned/driven from an external company (Like Google Universe: Mail, Map, Calendar, Translator, ...): for each of them you need to have first a basic module, then you build your needs on top of it.
- any addendum to Uniface to manage external devices: for each of them you need to have first a basic module, then you build your needs on top of it.
- any addendum to Uniface Proc Script language like new function(s), new instruction(s) could be other basic modules to build application needs on top of them.

An example: I remember another post about interfacing German Tax services; I imagine it was first built a module to interface basic tech stuffs then application needs on top of it.

All these modules could be PLUGINS!

In other development environment they are often called "libraries".

I will add a comment to my initial post sharing an example.

Gianni


Hi Unifacers,

In the current IT world driven from integrations could it be of interest to the Uniface world to have a standardized mode to develop and deploy plugins to Uniface apps? IMHO...YES!

I do not remember this specific subject being discussed, but it could be I was not part of the discussion or I have simply forgotten about it!

Pro...? Cons...? Pitfalls...? Tips...? Suggestions...?

Let's argue about it!

Gianni

UNIFACE plugins

Definition: a uniface plugin could be a full application (launcher, monitor, configurator, ...) or a part of an application (module, library, ...) that can be used together or integrated within a Uniface application. Each plugin is dedicated to a single business or technical object. Base for each plugin should be a microservice architecture, extended with a re-susable presentation layer.  The word "plugin" is used to identify a software that can easily be re-used in any Uniface installation and configuration.

Perimeter (DRAFT) for a "whatever" plugin:
- SelfContainedUARname: UP_XXXX_whatever_VVV where:
    - XXXX is a unique identifier of plugin provider
    - whatever is the concept implemented in the plugin
    - VVV is the plugin version
    each plugin provider is responsible to maintain plugin info updated
- Mission: [short description (max 250 char) defining the plugin interface perimeter]
- PluginVersion: x.y[.z]
- UnifaceVersionsSupported: Ux.Uy[, Ux1.Uy1][, Ux2.Uy2]
- ComponentsNames: XXXX_*
- GlobalObjects: Each plugin component is connected to its library named XXXX_*
   Objects being part of SYSTEM_LIBRARY should have their names starting with XXXX_*
   $variation and $language MUST be saved and restored from ALL plugin interactions
   Objects being part of USYS variation should have their names starting with XXXX_*
- Security: None | ???TBD???
- DBMS: None | XXXX_APPMODEL
- UserInterface: None | Char | C/S | Web
- LanguagesSupported: "USA" MUST be supported! Further list of international codes from ISO-639-3
- ServicesPerimeter: None | Uniface | LAN | Internet
- PrintingPerimeter: None | Uniface | OtherToBeSpecified
- DataExchangePerimeter: InLine | LocalFolder | MailBox | OtherToBeSpecified
- OperationsList: simpleListOfOperationsAvailableWithoutParams but a short description
- PresentationComponents: simpleListOfPresentationComponents with attribute: Contained | Indipendent and a short description
- OtherPluginPreRequisites: None | ListOfOtherPlugin(s)ThatMUSTbeAvailable
- PluginOptionals: None | ListOfOtherOptionalPlugins
- OtherTechPreRequisites: None | ListOfOtherTechPreRequisites
- DeliveryMode: OpenSources | UARonly | withSourcesIfRequested
- TechDocumentation: None | Samples | Included
- Contact: eMailAddress

Let's try with an example 
(thanks to Theo Neskeens providing initial GoogleMap Integration sample):
- SelfContainedUARname: UP_GSAN_GMAP_100
- Mission: Interface to Google Map, Services and Presentations
- Version: 1.0.0
- UnifaceVersion: 9.7
- ComponentsNames: GSAN_*
- GlobalObjects: None
- Security: None
- DBMS: None
- UserInterface: C/S
- LanguagesSupported: ITA
- ServicesPerimeter: Internet
- PrintingPerimeter: Uniface, GSAN_UPDF plugin
- DataExchangePerimeter: InLine
- OperationsList:
GSAN_GMAP_SVC.getDistance() get distance in km between two GeoPoints|Addresses|POIs in an UIL
GSAN_GMAP_SVC.getPathFromTo() get traveling steps between two GeoPoints|Addresses|POIs in an UIL
GSAN_GMAP_SVC.getStaticMap() get static map related to a GeoPoint|Address|POI in an UIL
- PresentationComponents:
GSAN_GMAP_MAP Contained form showing either static or dynamic maps
- OtherPluginPreRequisites: None
- PluginOptionals: GSAN_UPDF: to interactively print map to PDF
- OtherTechPreRequisites: Google Developer Account must be setup
- DeliveryMode: UARonly
- TechDocumentation: Samples
- Contact: name.surname@domain.ext

Simpler HowTo:
- Add reference to UP_GSAN_GMAP_100 UAR file to the [RESOURCES] section of your ASN file
- Use in your application activate "GSAN_GMAP_SVC".getDistance() with documented parameters to get distance between two addresses.

Open questions:
- For the "Security" item, suggestions are still welcome... 🙂
- Should a list of Uniface plugins available be maintained on uniface.info? If yes, how?


Hi Unifacers,

In the current IT world driven from integrations could it be of interest to the Uniface world to have a standardized mode to develop and deploy plugins to Uniface apps? IMHO...YES!

I do not remember this specific subject being discussed, but it could be I was not part of the discussion or I have simply forgotten about it!

Pro...? Cons...? Pitfalls...? Tips...? Suggestions...?

Let's argue about it!

Gianni

Hi Gianni

About the UAR-Name:

I would suggest the follwing format

UP_<ProviderId>_<PackageId>{_<VersionId>}

So the only things to manage ist the provider id.

e.g a plugin from UnifAce will be:
UP_UNIFACE_GRAPHICS.uar
or
UP_UNIFACE_GRAPHICS_V201911.uar
if this is a newer version.

Your plugins will then be
UP_GIANNI_SUPERTOOL1.uar
UP_GIANNI_SUPERTOOL2.uar

...

Ingo


Hi Gianni

About the UAR-Name:

I would suggest the follwing format

UP_<ProviderId>_<PackageId>{_<VersionId>}

So the only things to manage ist the provider id.

e.g a plugin from UnifAce will be:
UP_UNIFACE_GRAPHICS.uar
or
UP_UNIFACE_GRAPHICS_V201911.uar
if this is a newer version.

Your plugins will then be
UP_GIANNI_SUPERTOOL1.uar
UP_GIANNI_SUPERTOOL2.uar

...

Ingo

Hi Ingo,

good point!

I agree about UAR name, it could be helpful to have them like you proposed.
Anyhow: the XXXX code is used into naming convention for various objects...is it still working and fully applicable in all cases?

Question: in your opinion, what about simple user defined functions like:

FirstCap(string)
it gives back the string passed as parameter with first letter of each word forced uppercase.

Should they be usable directly into code like:
   myVar = FirstCap(anotherVar)
or only through an activate operation of a component like:
   activate "UP_GIANNI_UTILITIES".FirstCap(anotherVar : IN, myVar : OUT)

The first solution is simpler but it is more difficult to define a naming convention to avoid ANY overlapping. The second solution is less readable but respect the naming convention already defined.

Gianni


Hi Gianni

About the UAR-Name:

I would suggest the follwing format

UP_<ProviderId>_<PackageId>{_<VersionId>}

So the only things to manage ist the provider id.

e.g a plugin from UnifAce will be:
UP_UNIFACE_GRAPHICS.uar
or
UP_UNIFACE_GRAPHICS_V201911.uar
if this is a newer version.

Your plugins will then be
UP_GIANNI_SUPERTOOL1.uar
UP_GIANNI_SUPERTOOL2.uar

...

Ingo

Hi Gianni

Naming convention, the mother of all trouble 🙂
If the name is to short, you will run into duplicate names. If it is to long, it's unreadable.
Library/projects names could be a first aid.
But:
In 9.7 you can't call a function with a "namespace" at the beginning  of  the name
$1 =GIANNI::FirstCap("hello")
wouldn't work 
Didn't check this in UF 10, but should also not working grumble 
Same for other global objects like menus&co

The other idea is to use the name mangeling mechanism *)
$1 = GIANNI@FirstCap@S@S("hello")
Where the first  @ spearate the "namespace" from the function name
The second @ spearate the types of the paramters
And the third @ spearate the types of the return value

It's "readable" like C++ (mangeled) function names.
And one have to keep the names short.

*) not exactly C++ mangeling, but useable to make up such names by hand


BTW:
your funtion FirstCap should have a second parameter "para"
Just in case one would refine the function call.
All my function in our application does have this extra parameter.
e.g.
GF_GET_PARA_STR(<val_lst>,<key_lst>,<def_val>,<nf_val>,<para>) ; returns string
This function gets a string out of a UIL(UnifaceItemList) by one of the keys in <key_lst>.
If in the UIL only the ID but no value found, <def_val> will be used.
If none of the keys found, <nf_val> will returned.
If in para is the id UPC then the uppercase will be returned.

With extra this "para" it's very easy to enhance the function without doing a refactoring of the whole code 🙂

Ingo



Hi Gianni

About the UAR-Name:

I would suggest the follwing format

UP_<ProviderId>_<PackageId>{_<VersionId>}

So the only things to manage ist the provider id.

e.g a plugin from UnifAce will be:
UP_UNIFACE_GRAPHICS.uar
or
UP_UNIFACE_GRAPHICS_V201911.uar
if this is a newer version.

Your plugins will then be
UP_GIANNI_SUPERTOOL1.uar
UP_GIANNI_SUPERTOOL2.uar

...

Ingo

Hi Ingo,

Your proposal to have a further parameter "para" is already in my habits; I call it "mode" but I use it only when I feel it is somehow needed, when the interface to the concept supported it is not fully clear. This is a good example of "defensive programming".

I feel your suggestions are getting plugin definition simpler and more consistent and I am going to update plugin definition I have published at the beginning of this thread.

I hope other Unifacers will give more suggestions based on their experience or will decide to agree on this Uniface plugins concept.

Thanks for your answers.

Gianni