I will try to explain what happens internally in the various Infor applications when we deploy Mashups. I need to understand this so I can streamline the deployment for my needs. Here is my artistic rendering of the current flow:
I will reverse engineer the applications by static analysis. This exposes the internals of the Infor applications, which are not supposed to be used by anyone other than Infor Product Development, and which may change with future versions of the applications. So the result is informative only. Also, I am not allowed to show any proprietary source code – I will just show snippets of decompiled code – and I will hide sensitive information such as hostnames, IP addresses, and passwords.
1. Mashup Designer > Generate > Lawson application
It then follows this stack of methods:
Mashup.Designer.MainWindow.IComponentConnector.Connect Mashup.Designer.MainWindow.OnFileDeploy Mashup.Designer.FileDeploymentWindow.OnSave Mashup.Designer.DeploymentHelper.CreateAppStream
Note: If instead we clicked the other MenuItem to generate a Mashup, it would follow this other stack of methods which doesn’t overlap with the previous:
Mashup.Designer.MainWindow.OnFileDeployMashup Mashup.Designer.DeploymentHelper.SaveMashupFile Mashup.Designer.DeploymentHelper.ValidateManifest Mango.UI.Services.Mashup.Internal.PackageHelper.CreatePackageFromManifest
2. LifeCycle Manager > Admin Products > Upload
A quick search of the upload popup with the command
findstr /c:"Select packages to upload" /s *.class in the LCM Client folder gives us the class D:\Infor\LifeCycleManagerClient\LCM-Client\plugins\com.lawson.lifecycle.application_22.214.171.124406300711\com\lawson\lifecycle\application\editors\adminview\ProductsPage.class with method
uploadPackages() which calls the interface
A quick search of the success message “Package successfully uploaded to LifeCycle Manager Server” gives us classes Cloud9UploadPackage.class which implements the interface and JavaInstallerUploadPackage.class in folder D:\Infor\LifeCycle Manager\LCM-Client\plugins\com.lawson.lifecycle.application_126.96.36.199406300711\com\lawson\lifecycle\application\upload\
Java Decompiler was not able to decompile these methods, so I used Krakatau decompiler in Python by Robert Grosse:
$ python decompile.py -path "C:/Program Files/Java/jre1.8.0_91/lib/rt.jar;LCM-Client/configuration/org.eclipse.osgi/bundles/9/1/.cp/lib/lcm-common-3.2.1.jar;LCM-Client/plugins/com.lawson.lifecycle.client_188.8.131.52406300711.jar" -skip LCM-Server/client/plugins/com.lawson.lifecycle.application_184.108.40.206406300711.jar
The method Cloud9UploadPackage.upload() gets a connection to the server, and uploads the file remotely. Then I kinda lost track of who creates the folder components folder and the file productinfo.xml. But it looks like it’s all about files and folders, nothing in a database, nothing cached in memory.
Let’s move on. This is becoming too dense.
3. LifeCycle Manager application install/upgrade and repeat per environment
4. Apache Ant tasks
The install logs show it executed three remote Apache Ant scripts:
templates/cloud9_install.vm templates/cloud9/install.vm templates/cloud9_install_relation.vm
5. Apache Velocity templates
The Ant tasks are compiled from Apache Velocity templates at D:\Infor\LifeCycle Manager\LCM-Server\products\Infor_Applications_1.0.0\templates\:
6. Remote code
Here we see the first reference to a database, the LCM Server database.
There are also these methods in D:\Infor\LifeCycle Manager\LCM-Server\products\LSO_10.2.1\tasks\tasks.jar and mangoserver_10.2.1.0.16.gar\lib\mangoserver-app-10.2.1.0.16.jar:
com.lawson.lifecycle.mango.DeployLawsonApplication.execute() com.lawson.lifecycle.mango.GridLCMTask.deployLawsonApplication() com.lawson.lso.installationpoint.InstallationPointManager.AddLawsonApp()
7. Apache Derby
The JDBC connection parameters are in the file lcm.properties at D:\Infor\LifeCycle Manager\LCM-Server\ :
hibernate.connection.driver_class=org.apache.derby.jdbc.EmbeddedDriver hibernate.connection.username=***** hibernate.connection.password=***** hibernate.connection.url=jdbc:derby:lcmdb derby.drda.portNumber=***** database.read.user=***** database.read.password=***** database.name=lcmdb
8. Smart Office
10. Grid database
MangoServer uses the Grid distributed database – an H2 database – where it duplicates the Mashups contents as blobs and sets authorization (SECURITY=1 means Access=Public, and SECURITY=0 means Access=None):
11. Local Storage
Then there is this repository in the MangoServer grid application with more metadata about the Mashups: D:\Infor\LifeCycle\host\grid\DEV\grids\DEV\applications\MangoServer\Client\Repository\LawsonApps\ :
What a rodeo.
Deploying a Mashup globally involves Smart Office client/server, Mashup Designer, metadata and lots more metadata, LiceCycle Manager client/server, remote file copy, Apache Velocity templates that compile into Apache Ant scripts that execute remote code to add records to the Apache Derby database of LifeCycle Manager, then MangoServer gets duplicates of the Mashups from the Grid H2 database via SOAP web services, and finally Smart Office client stores local copies in the user’s computer.
The number of copies that must be kept in sync is 2 + p + pq where p is the number of environments and q is the number of users (1 copy from the developer, 1 copy in the LCM files & folders, p copies in MangoServer H2 databases, and pq copies in local storage). That’s normal for software development, except I did not expect the additional copy in the MangoServer database.
Next time, I will explore the MangoServer web services to upload Mashups.
My original intention in reverse engineering the internals of Mashup deployment was to learn how to develop a command line to streamline Mashup deployment and simplify it from thousands of clickks down to a few double-clicks; see my previous post for details.
But after all this rodeo, I conclude it would be a bad idea. There are too many moving pieces, too much to learn that’s not part of my job, and Infor Product Development may change it at any time. I need to go back to the drawing board and find a new approach.
At least it was a good learning exercise.
Please leave me a comment, slap a Like, subscribe to follow my experiments, share around you, and come write the next idea with us. This is a volunteer-based blog to help each other in the M3 community. Thank you for your support.