Getting new webroutines deployed

In recent versions of Lansa – I think from v.14SP2 and later – if you want to deploy a patch package new webroutine in an existing WAM, you need to check the “Install Imports” setting.

The relevant documentation has this to say:

“If the Install Imports option is selected, standard imports and repository definitions are included in the patch:

Standard importsIncludes Web Resources, Web Utilities, Standard Weblets, Messages, System Variables and Technology Services. These imports may change in a new LANSA release (GA, SP or EPC).Standard imports ensure changes in the associated import files are applied. For large applications, this may be a time-consuming task.
Repository definitionsUpdates to Repository Definitions may be needed for Repository Help and Repository Security. When installing WAM, Weblet or External Resource file changes do not require an import because the associated files are published directly. Only changes to External Resource definitions require an import. These changes include file path changes, mime type changes and file encoding changes. LANSA will not inform you of this. You will need to determine this yourself.

I didn’t understand it that way but now I know: I need to check the “Install Imports” setting.

That also means I can’t make the patch uninstallable.

And I might add, I need to use patches rather than versions, as a new version will remove my Lansa Web Administrator settings, along with removing my IIS settings.

Substitution variables in deployment packages

It is no secret that the Lansa documentation is not written with me in mind and this blog is partly a way to compensate for that. For instance the page “Valid Substitution Variables for Command Parameters” lists a number of variables that can be used for commands to be executed prior and after an installation. But what does that actually mean?

Well, I needed to find the folder where the X_Dbmenv.dat file is located so I thought %DIRL% might be the right one. It was, but I checked first by making a test install and can give these examples for Windows 32 bit installations:

%DIRL% (current LANSA root directory) is ROOTFOLDER\X_Win95\X_LANSA\
%DIRP% (current partition directory) is ROOTFOLDER\X_Win95\X_LANSA\x_PARTITION\
%TEMP% (current temporary directory) is the current Windows tempory folder
%PKGD% (current package directory) is ROOTFOLDER\X_Win95\X_LANSA\x_apps\

Debugging package build; missing characters in dpcreate.log

There’s a fun error in the data in dpcreate.log, which is created during package build in Lansa v.15. The error happens when a line is too long for single record in the log so it is split over multiple lines.

Each log record can be 276 characters long with a code character, a space, 253 characters of data, a tab and then the date and time.

Except, when the 253 characters are insufficient the line is split and the next record starts with the code character appended with an ‘X’. Probably a mnemonic for “extended”. This, unfortunately, has the knock-on effect of erasing the first character in the data for that record.

For example:

C "C:\Program Files (x86)\WiX Toolset v3.10\Bin\Candle.exe" -nologo -sw1055 -sw1076 -dPlatform=x86 -fips -arch x86 -I"e:\lansa\X_Win95\X_Lansa\X_Apps\X_Wix\Source" -out Obj\Release\ -ext "C:\Program Files (x86)\WiX Toolset v3.10\Bin\WixUtilExtension.dll" 2021/11/25 09:07:18
CX -ext "C:\Program Files (x86)\WiX Toolset v3.10\Bin\WixUIExtension.dll" "e:\lansa\X_Win95\X_Lansa\X_Apps\X_Wix\Source\MsiUi.wxs" "e:\lansa\X_Win95\X_Lansa\X_Apps\X_Wix\Source\AppDlg.wxs" "e:\lansa\X_Win95\X_Lansa\X_Apps\X_Wix\Source\OdbcDlg.wxs" "e:\lans 2021/11/25 09:07:18
CX \X_Win95\X_Lansa\X_Apps\X_Wix\Source\MaintenanceTypeDlg.wxs" "e:\lansa\X_Win95\X_Lansa\X_Apps\X_Wix\Source\MaintenanceWelcomeDlg.wxs" "e:\lansa\X_Win95\X_Lansa\X_Apps\X_Wix\Source\ServerDlg1.wxs" "e:\lansa\X_Win95\X_Lansa\X_Apps\X_Wix\Source\ServerDlg2. 2021/11/25 09:07:18
CX xs" "e:\lansa\X_Win95\X_Lansa\X_Apps\X_Wix\Source\VerifyReadyDlg.wxs" "e:\lansa\X_Win95\X_Lansa\X_Apps\X_Wix\Source\CommPortsDlg.wxs" "e:\lansa\X_Win95\X_Lansa\X_Apps\X_Wix\Source\UserIdDlg.wxs" "e:\lansa\X_Win95\X_Lansa\X_Apps\X_Wix\Source\WebSitePlugi 2021/11/25 09:07:18
CX Dlg.wxs" "e:\lansa\X_Win95\X_Lansa\X_Apps\X_Wix\Source\WebSiteVirtualDirDlg.wxs" Src\Release\E2960.wxs 2021/11/25 09:07:18

In this case the data is easily reconstructed once you are aware of the error.

Windows installer parameters

We are still working on getting v. 15 running and one of the issues that I’ve been working on is the command line parameters for Windows installers (MSI packages) of deployment packages.

Again, I run afoul with the Lansa documentation which is structured in a way that runs counter to my thinking.

The first thing I needed was to set the default folder and that appears to be a standard msiexec parameter, APPA. But I needed to set the listener port to something other than 4545 and that was less obvious. If you look at the setting when making the deployment package, all the settings with a parentheses afterwards, you can use the string in the parentheses as a parameter. So, “Database Name (DBAS)” means that I can use the DBAS as a parameter for msiexec.

But you need to dive into a lot of different pages, under “Version Installation Dialogs” in the documentation to find the rest of the parameters. I’ve tried to collect them here:

APPL                    Installation folder
DBUT                    DBMS Type
PART                    Partition
LANG                    Language
FORM                    Startup Form
PROC                    Startup Process
FUNC                    Startup Function
INIT                    Initial Function
DPAP                    Remove Previous Application
DBII                    Data Source Name
DBSV                    Database Server Name
DBAS                    Database Name
DBUS                    Database User
PSWD                    Database Password
SUDB                    Setup Database (Y/N)
UPDB                    Upgrade V12 Database
CREATENEWUSERFORSERVICE Create new user for service (default to use existing)
USERIDFORSERVICE        User Id for service
PASSWORDFORSERVICE      Password
VIRTUALWEBSITE          Website name
HTTPPORTNUMBER          Website port
VIRTUALDIRECTORYALIAS   Virtual directory
HOSTROUTEPORTNUMBER     Listener port (this was the one I was looking for)
JSMPORTNUMBER           JSM Server port
JSMADMINPORTNUMBER      JSM Administrator port
USER                    LANSA User Name
DBID                    SuperServer Server Type
PSUS                    SuperServer Primary Server User Name
PSPW                    SuperServer Primary Server Password
PSLU                    SuperServer LU Partner Name
PSEA                    SuperServer Server Exceptional Arguments
PSTY                    SuperServer Server Type
PSCC                    SuperServer Commitment Control
PSDB                    SuperServer DBCS Capable
PSDL                    SuperServer Divert Locks
PSWM                    SuperServer Show Wait Message
PSEP                    SuperServer Server Execution Priority
PSCT                    SuperServer Client to Server Table
PSST                    SuperServer Server to Client Table
PSTC                    SuperServer Server Trusted Connection
UPGD                    JIT Upgrade Option
ASLU                    JIT Application Server Name
ASUS                    JIT Application Server User
ASPW                    JIT Application Server Password
ASCT                    JIT Client to Server Table
ASST                    JIT Server to Client Table
UPCF                    JIT Connection Failure Action
UPDF                    JIT Download Failure Action
ASTS                    JIT Application Server Trusted Connection
DBTC                    Use Trusted Connection (Y/N)

A command-line installation could therefore be

msiexec /i V15_A_v1.0.0_en-us.msi APPA=X:\LANSA8954 HOSTROUTEPORTNUMBER=8954

The fix for legacy WAM and Lansa v.14.2+

I didn’t post my solution to my problem in Lansa v.15 related to the style attribute in WAMs. I’ll correct that now:

Due to CSP any “style” attribute in the WAM source is moved to a “data-style” attribute, and then one of the new standard scripts move it back, client-side. Unfortunately, if you have a legacy solution you probably can’t use the new standard scripts.

The solution is to just add this simple javascript to your pages, preferably in a script file that is loaded on all pages:

document.querySelectorAll('[data-style]').forEach((elem) => {
  elem.style.cssText = (elem.style.cssText? (elem.style.cssText.match(/;\s*$/)? elem.style.cssText + elem.dataset.style : elem.style.cssText + "; " + elem.dataset.style) : elem.dataset.style);
  elem.removeAttribute('data-style');
});

It finds all DOM elements with a “data-style” attribute, adds the value from that to the “style” attribute of the element, and removes the “data-style” attribute. The reason why I don’t just set the cssText property to the value but potentially add the value, is that any javascript that might have run before might have set some style attributes already.

This will need to be adapted if you overwrite some styles with your current javascript.

v.15 modifies WAM output

Finally working with v.15 and while it is generally a good experience, I have so far one technical issue: The output from Web Application Modules (WAMs) is modified, transformed, in an extra step after the XLS transformation.

Case in point: XSL using the XHTML technology service

<?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="std_hidden.xsl" />
   <xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8"
               indent="no" />

   <xsl:template match="/">
      <html>
         <body style="background-color: grey;">
         Hello World.
         </body>
      </html>
   </xsl:template>

</xsl:transform>

which is possibly the most basic template you can write – I’ve even removed the weblet layout – is transformed to


<html xmlns="http://www.w3.org/1999/xhtml"><body data-style="background-color: grey;">
   Hello World.
</body></html>

See the differences? There’s an added namespace, (xmlns="http://www.w3.org/1999/xhtml"), and the style attribute has been transformed to a data-style attribute.

This former happens to the first tag present on the page. The latter is then fixed in the standard std_script_v2.min.js script, provided this runs – which it doesn’t in the example above, as I’ve removed the default layout.

It is not a problem in most scenarios. I expect most will continue to use WAMs to output web pages to supported browsers, and that’s fine.

The behaviour bothers me on principle. I wrote the transform, but it was transformed by another process that I cannot control. It limits me to generate output that adheres to what Lansa thinks I should be doing.

It also bothers me specifically, as I have for a short while longer, some legacy browsers I’d like to support and the new std_script_v2.min.js cannot run in those. I’ll probably work a bit on getting std_script_v2.min.js to run.

EDIT: I think I’ve found the transform that is doing this: \x_lansa\web\tsp\tsp_global_publisher.xsl:

	<!-- Change style attribute into data-style for CSP support -->
	<xsl:template match="@style">
		<xsl:attribute name="data-style"><xsl:value-of select="wd:translate(., false())"/></xsl:attribute>
	</xsl:template>

Obviously it will cause me – and especially the rest of my team – untold pain in the future if I change this but at least it gives us a hint of why it is done. Could it be Content Security Policy? Yes, it appears so. In that case, I’ll accept that it is an elegant solution to a problem that would probably have stumped me, for a while.

I still think I should have the option of using it or not and unlike Web Pages, there are no settings for WAMs so I can’t adjust it.

Response(*JSON) and invalid values

We still haven’t upgraded but at least we have it on our schedule. So this is at least in v.12 but I suspect it also applies in later versions.

I have a lot of webroutines that returns JSON but often I have had to generate the JSON by hand, which obviously is less than optimal. So when I get the chance I use Response(*JSON), like:

Webroutine Name(status) Response(*JSON) Desc('lagerstatus') Onentry(SESSIONSTATUS_NONE)

While this returns rather convoluted JSON it generally works. Except, when it doesn’t:

{"value":.00}

This is not a valid JSON, it should have been

{"value":0.00}

Unfortunately no edit code makes this possible so I have to skip Response(*JSON) and instead build the JSON myself.

I am looking forward to upgrading

We are still at v.14.1 and v.12 but will soon be upgrading to v.14.2 and v.15, respectively. That’s good.

Unfortunately, I doubt upgrading from v.14.1 to v.14.2 will solve the basic XSLT editing problems in the Lansa editor. Currently, I had a WAM fail when I had saved this XSLT/XML

<tr><input id="{$WSSHPLNR/@id}" type="hidden" name="{$WSSHPLNR/@id}" value="{$WSSHPLNR}" /><td ...

and when I, the next day, loaded the WAM, or whenever I switch between the “XSL” and “Web Page” tabs in the design tab, it gets changed to

<tr /><input id="{$WSSHPLNR/@id}" type="hidden" name="{$WSSHPLNR/@id}" value="{$WSSHPLNR}" /><td ...

Solution? Move the <input> tag to before the <tr> tag. Yes, I know, I should have done that anyway, but the editor shouldn’t make my content illegal when I switch tabs.

Server modules live separate lives

As much of the other posts I write here, this relates to something that surprised me.

Currently I write a lot of server modules as APIs, and this time I needed to submit a job for some processing. But for some reason this failed and I couldn’t find a reason.

That wasn’t really a problem, because I could just save the data I needed to process in a saved list and have a batch job read the list and do the processing.

Except, that didn’t work either.

Maybe that’s what Lansa means by

SAVE_LIST and RESTORE_SAVED_LIST should be used in the same context. That is, you should not use SAVE_LIST from within a function run on the WEB and later restore the saved list from within a function run as a Visual LANSA function.

Because even though the saved list was stored in DC@F80, the F80P#I field was not set to the partition I was using. It was set to “SYS”. So, in the batch job I couldn’t read the saved list, because the batch job was a regular function.