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 all starts in Infor Smart Office > Mashup Designer > Generate Package > Smart Office > Lawson Application:
That MenuItem is created with the following event handler:
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
The previous methods eventually create a .lawsonapp file which is a ZIP archive of the .mashup file and an app.config file:
The Mashup file is itself another ZIP archive of metadata files, the manifest, the XAML source code, and optional profile and resource files:
2. LifeCycle Manager > Admin Products > Upload
Then, we upload the .lawsonapp file to Infor LifeCycle Manager (LCM) > Admin > Upload Products > Upload (I switched Mashups, so the screenshots don’t match):
It creates the Mashup folder in LCM-Server\products\ with a file productinfo.xml and unzips the .lawsonapp file in the components sub-folder:
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_18.104.22.168406300711\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_22.214.171.124406300711\com\lawson\lifecycle\application\upload\
And a quick search in the LCM Client and Server logs gives us com.lawson.lifecycle.server.command.Cloud9App_UploadPackage:
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_126.96.36.199406300711.jar" -skip LCM-Server/client/plugins/com.lawson.lifecycle.application_188.8.131.52406300711.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
Then, we install the product on the desired environment (e.g. DEV, TST):
Note: Once the Mashup is installed, we can upgrade it to a new version, and repeat the steps for another 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\:
The scripts have control structures (if-then-else, for-loop) and getters to replace property values:
I think this is it, com.lawson.lifecycle.common.command.RemoteScript_Run:
6. Remote code
LCM Server will execute code from tasks.jar at D:\Infor\LifeCycle Manager\LCM-Server\products\Infor_Applications_1.0.0\tasks\ :
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 LCM Server database is an Apache Derby database that LCM uses with the Hibernate object-relational mapping framework:
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
We can see the Mashup in the product registration table:
8. Smart Office
Smart Office gets a copy of the Mashups, we can see them in the My Local Applications and Mashup File Administration tools:
It is populated by Mango.Core.Storage.FileStorageCategory.ListAllCategoryFileInfo:
That calls ListAllCategoryFileInfo in the SOAP web service /mangows/CategoryFilesManager?wsdl:
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):
You can find the JDBC connection information at Infor ION Grid Management Pages > Grid DB Broker > View application configuration:
You can also use the embedded H2 console application:
11. Local Storage
Finally, the Smart Office client that each user starts for each environment will download the Mashup blobs and save them in the 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.
- Continuous integration of Mashups #1 – HELP WANTED!!
- Continuous integration of Mashups #2 – Reverse engineering
- Continuous integration of Mashups #3 – HELP GOTTEN!!
- Continuous integration of Mashups #4 – Command line
8 thoughts on “Continuous integration of Mashups #2 – Reverse engineering”
UPDATE: Added chapter 11. Local Storage, and added number of copies to sync 2 + p + pq
UPDATE: Added chapter 12. Repository