Switching technology services

I have now had the help from Lansa support for a very specific problem. We have a number of solutions, some of which use the XHTML technology service, some the PPC_XHTML technology service.

None of these solutions use more than one technology service.

PPC_XHTML is no longer supported by Lansa so when we upgraded to v.14 this presented a problem. Support found a way to make it work and we continued, making only minor adjustments to the code.

Now we have been upgraded to v.14.1 and something broke in the process.

It can still be made to work but we can only have either XHTML or PPC_XHTML working at the same time. Due to a deadline we will live with that for a short time and then we will start the migration of the PPC_XHTML solutions.

The work-around is this:

Getting XHTML to work: Use Tools -> Import to import the v.14.1. weblets. Done.

Getting PPC_XHTML to work: Use Tools -> Import to import the old v.12 weblets. Check out the specific design weblets made for our solution. Check out the WAM that we need to work with. Done.

So, not bad but not optimal either. That is of course the problem using a technology that is no longer supported.

Advertisements

Using the instance list

In VLF, the standard layout consists of the menu (with applications and their sub-business objects), the filter, the instance list and the command handler. The instance list is set in the VLF designer, where the sequence and types are set.

The instance list has to visual identifiers (VisualID1 and 2) that are used as GUI keys, directed at the user, and a number of numeric and alphanumeric keys (Nkey1+ and Akey1+). Then there is option of 10 alphanumeric values (AColumn1-10), 10 numeric values (NColumn1-10) and 5 date values (DColumn1-5) – and more can be added, if you really need to. The visual GUI keys are also used in the header for the command handler.

Adding to the instance list is often done from the filter, as in

Invoke Method(#avListManager.AddtoList) Visualid1(#OPSID.AsString) Visualid2(#ITEMID) Nkey1(#LISTCOUNT) Nkey2(#OPSID) Nkey3(#COUNT1) Nkey4(#COUNT2) Akey1(#RECNAME) Akey2(#SNAME) Akey3(#ART) Acolumn1(#RECNAME) Acolumn2(#SNAME) Acolumn3(#ART) Ncolumn1(#COUNT2) Ncolumn2(#PRICE) Ncolumn3(#TOTAL)

surrounded by an appropriate use of

Invoke Method(#avListManager.BeginListUpdate)
Invoke Method(#avListManager.ClearList)
Invoke Method(#avListManager.EndListUpdate)

Updating an instance is done by

Invoke Method(#avListManager.BeginListUpdate)
Invoke Method(#avListManager.AddtoList) Visualid1(#OPSID.AsString) Visualid2(#ITEMID) Nkey1(#LISTCOUNT) Nkey2(#OPSID) Nkey3(#COUNT1) Nkey4(#COUNT2) Akey1(#RECNAME) Akey2(#SNAME) Akey3(#ART) Acolumn1(#RECNAME) Acolumn2(#SNAME) Acolumn3(#ART) Ncolumn1(#COUNT2) Ncolumn2(#PRICE) Ncolumn3(#TOTAL)
Invoke Method(#avListManager.EndListUpdate)

which will either insert a new instance or, if the keys match an existing instance, replace an instance.

Then, in the command handler the selection can be read with

Invoke Method(#avListManager.GetCurrentInstance) Visualid2(#ITEMID) Nkey1(#LISTCOUNT) Nkey2(#OPSID) Nkey3(#COUNT1) Nkey4(#COUNT2) Akey1(#RECNAME) Akey2(#SNAME) Akey3(#ART)

Thus values from the selection in the instance list can be passed to the command handler. If other values need to be passed from the filter (or other command handler) to the command handler, it can be done using the save and restore, like:

Invoke Method(#avFrameworkManager.avSaveValue) Instance(15) Withid1(CHOICE) Fromavalue(#CHOICE)
Invoke Method(#avFrameworkManager.avRestoreValue) Instance(15) Withid1(CHOICE) Toavalue(#CHOICE)

Notes in sizes:
VisualId1 and AKey1 to AKey5 are alphanumeric 32
VisualId2 is alphanumeric 50
NKey1 to NKey5 are signed 15,0
AColumn1 to AColumn10 are alphanumeric 100
NColumn1 to NColumn10 are signed 30,9
DColumn1 to DColumn5 are alphanumeric 19

WAM structure

It has been a long time now since my last post, which is mainly due to a big deadline I had to reach. Before it reached me 🙂

I had a chance to work a lot more with Lansa’s Web Application Modules (WAMs) and have made some notes in that regard:

The basic structure of the command handlers is

Begin_Com Role(*EXTENDS #PRIM_WAM) Layoutweblet('WAM_LAYOUT')
Define_Com Class(#vf_sw100) Name(#avFrameworkManager)
Define_Com Class(#vf_aw010) Name(#ThisHandler) Reference(*Dynamic)
Define_Com Class(#vf_lw002) Name(#avListManager) Reference(*Dynamic)
Define_Com Class(#fp_in001) Name(#FastPart) Reference(*Dynamic)

* VL Framework map fields. DO NOT CHANGE.
Web_Map For(*both) Fields((#VF_FRAMEI *private) (#VF_FRAMEW *private) (#VF_FRAMES *private) (#VF_ELXTOF *private) (#VF_ELXN01 *private) (#VF_ELXN02 *private) (#VF_ELXN03 *private) (#VF_ELXN04 *private) (#VF_ELXN05 *private) (#VF_ELXN06 *private) (#VF_ELXN07 *private) (#VF_ELXN08 *private) (#VF_ELXN09 *private) (#VF_ELXN10 *private) (#VF_ELXA01 *private) (#VF_ELXA02 *private) (#VF_ELXA03 *private) (#VF_ELXA04 *private) (#VF_ELXA05 *private) (#VF_ELXA06 *private) (#VF_ELXA07 *private) (#VF_ELXA08 *private) (#VF_ELXA09 *private) (#VF_ELXA10 *private) (#VF_ELMETA *private))

* Overrides and definitions go here

* Include all fields and lists that should be available in the XML in the this Web_Map
Web_Map For(*BOTH) Fields(...)

Webroutine Name(UHandleEvent)
* define the WAM events
Invoke Method(#avFrameworkManager.avRegisterEvent) Named(search) Signalaswamevent(1)
Invoke Method(#avFrameworkManager.avRegisterEvent) Named(export) Signalaswamevent(2)
* define the init event
Invoke Method(#avFrameworkManager.avInitializeWAM) Type(COMMAND) Invoker(#com_owner) Listmanager(#avListManager) Handlermanager(#ThisHandler) Fastpartmanager(#FastPart)
* call the initialize event routine
* call the WAM event routine
Invoke Method(#avFrameworkManager.avHandleWAMEvent) Anchorblock(#vf_framew) Event(#vf_event) Designmode(#vf_framed) Skin(#VF_Frames) Metatag(#vf_elmeta) Tof(#vf_elxtof) N01(#vf_elxn01) N02(#vf_elxn02) N03(#vf_elxn03) N04(#vf_elxn04) N05(#vf_elxn05) N06(#vf_elxn06) N07(#vf_elxn07) N08(#vf_elxn08) N09(#vf_elxn09) N10(#vf_elxn10) A01(#vf_elxA01) A02(#vf_elxA02) A03(#vf_elxA03) A04(#vf_elxA04) A05(#vf_elxA05) A06(#vf_elxA06) A07(#vf_elxA07) A08(#vf_elxA08) A09(#vf_elxA09) A10(#vf_elxA10) Ssiname(#VF_FRAMEI)
Endroutine

Evtroutine Handling(#avFrameworkManager.uInitialize) Options(*noclearmessages *noclearerrors)
* Restore values used in previous executions of filter
Change Field(#WAWUSR) To(#ThisHandler.avLoggedonUser)
Change Field(#BUTNR) To(#ThisHandler.avLoggedonUser)
Endroutine

Evtroutine Handling(#avFrameworkManager.uexecute) Options(*noclearmessages *noclearerrors)
Endroutine

Evtroutine Handling(#avFrameworkManager.uWAMEvent_1) Options(*NOCLEARMESSAGES *NOCLEARERRORS)
Endroutine

Evtroutine Handling(#avFrameworkManager.uWAMEvent_2) Options(*NOCLEARMESSAGES *NOCLEARERRORS)
Endroutine

End_Com

No code can go outside the routines.

The XSLT could look like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" exclude-result-prefixes="lxml wd"
 xmlns:lxml="http://www.lansa.com/2002/XML/Runtime-Data"
 xmlns:wd="http://www.lansa.com/2002/XSL/Weblet-Design"
 xmlns="http://www.w3.org/1999/xhtml"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:import href="std_keys.xsl" />
 <xsl:import href="std_variables.xsl" />
 <xsl:import href="WAM__LAYOUT.xsl" />
 <xsl:import href="std_radbuttons.xsl" />
 <xsl:import href="std_ext_radbuttons.xsl" />
 <xsl:import href="std_checkbox.xsl" />
 <xsl:import href="ub_default_button.xsl" />
 <xsl:import href="std_dropdown.xsl" />
 <xsl:import href="std_button.xsl" />
 <xsl:import href="std_select_list.xsl" />
 <xsl:import href="std_dynamic_select.xsl" />
 <xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8"
 indent="no" />
 <lxml:data />
 <xsl:template match="/">
 <xsl:call-template name="layout" />
 </xsl:template>
 <xsl:template match="/lxml:data">
  
  <xsl:call-template name="std_button">
   <xsl:with-param name="on_click_wrname" select="'UHandleEvent'" />
   <xsl:with-param name="on_click_wamname" select="'CH_LEVTOT'" />
   <xsl:with-param name="reentryvalue" select="'search'" />
   <xsl:with-param name="reentryfield" select="'VF_WAMEVENT'" />
   <xsl:with-param name="caption" select="'Search'" />
   <xsl:with-param name="name" select="'search'" />
  </xsl:call-template>
  <xsl:call-template name="std_button" />
   <xsl:with-param name="on_click_wrname" select="'UHandleEvent'" />
   <xsl:with-param name="on_click_wamname" select="'CH_LEVTOT'" />
   <xsl:with-param name="reentryvalue" select="'export'" />
   <xsl:with-param name="reentryfield" select="'VF_WAMEVENT'" />
   <xsl:with-param name="caption" select="'Export'" />
   <xsl:with-param name="name" select="'export'" />
  </xsl:call-template>
 </xsl:template>
</xsl:transform>

This would display two buttons. Clicking on the first will trigger the 1st event and the second will trigger the 2nd event, as defined in the

Invoke Method(#avFrameworkManager.avRegisterEvent) Named(search) Signalaswamevent(1)
Invoke Method(#avFrameworkManager.avRegisterEvent) Named(export) Signalaswamevent(2)

and the

<xsl:with-param name="reentryvalue" select="'search'" />
<xsl:with-param name="reentryvalue" select="'export'" />

WAMflow2

The first request to the command handler looks like protocol://server:port/path?webapp=COMMANDHANDLERNAME+webrtn=WEBROUTINENAME+partition=PARTITION+language=LANGUAGE

The interesting part is the WEBROUTINENAME which, case insensitive, determines which webroutine in the command handler will be giving control. I have mostly worked with the default UHandleEvent. The UHandleEvent webroutine is called and with the

Invoke Method(#avFrameworkManager.avHandleWAMEvent) ...

call, the

Evtroutine Handling(¤avFrameworkManager.uInitialize)

is called, followed by the

Evtroutine Handling(#avFrameworkManager.uexecute)

after which the control is returned to the webroutine.

Clicking on one of the buttons results in a request looking like protocol://server:port/path?wam=COMMANDHANDLERNAME&webrtn=WEBROUTINENAME&ml=TECHNOLOGYSERVICE&part=PARTITION&lang=LANGUAGE&_=TIMESTAMP

This calls the webroutine and then the avHandleWAMEvent calls, first

Evtroutine Handling(¤avFrameworkManager.uInitialize)

followed by the

Evtroutine Handling(#avFrameworkManager.uWAMEvent_1)

routine (where the numeric value comes from a match between the definitions of registered events and the VF_WAMEVENT parameter in the request body). After that, control is returned to the webroutine.