Continuous integration of Mashups #2 – Reverse engineering

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:

Reverse engineering

That MenuItem is created with the following event handler:

It then follows this stack of methods:


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:


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:


\_rels\ .rels:


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):

The result is:

It creates the Mashup folder in LCM-Server\products\ with a file productinfo.xml and unzips the .lawsonapp file in the components sub-folder:

Reverse engineering

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_3.2.1.201406300711\com\lawson\lifecycle\application\editors\adminview\ProductsPage.class with method uploadPackages() which calls the interface com.lawson.lifecycle.application.upload.UploadPackage.upload(monitor):

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_3.2.1.201406300711\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 -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_3.2.1.201406300711.jar" -skip LCM-Server/client/plugins/com.lawson.lifecycle.application_3.2.1.201406300711.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:



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:

And com.lawson.lifecycle.server.command.RemoteAntScript_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.\lib\mangoserver-app-

31 32

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 at D:\Infor\LifeCycle Manager\LCM-Server\ :


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:

9. MangoServer

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:

12. Repository

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\ :
36 37


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.

Future work

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.

That’s it!

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.

Related posts

Continuous integration of Mashups – HELP WANTED!!

I need help deploying many Smart Office Mashups, on multiple environments, fast, several times a day. Think continuous integration. Currently, it takes cubic time. Ideally, there would be a solution in linear time.


Here is a typical scenario: a user reports an error with a Mashup, I fix the error in the XAML file, and I propagate the fix to the server. For that, I generate the Lawson package in Mashup Designer in Smart Office (ISO), I upload the package in LifeCycle Manager (LCM), and I upgrade the Mashup on each environment.

Here are some screenshots:

My best case scenario is one Mashup and two environments once a day. My average scenario is three Mashups and three environments three times a day. My worst case scenario is 13 Mashups and five environments seven times a day.

(Note: normally we should develop in the DEV environment and push to the TST environment for users to test, but we are in a transition period between on-premise and Infor Cloud, and somehow we have five environments to maintain. Also, we could tell users to install Mashups locally or we could share Mashups with a role, but users got confused with versions and roles, so we have to do global deployments only.)

Clickk counter

I count mouse clicks, mouse moves, and keystrokes as clickks. To optimize as much as possible, I suppose that ISO, Mashup Designer, LCM Client, the Manage Products page, and the Applications tab are all launched and ready to use, and that I don’t close them during the day. The clickk counter is approximately the following:

7 clickks to generate the Lawson package in Mashup Designer
20 clickks to upload the package in LCM
11 clickks to upgrade the Mashup in the environment


x: number of Mashups
y: number of environments
z: number of times per day

The formula is:

(7x + 20x + 11xy)z


  • 49 clickks (7*1+20*1+11*1*2)*1 for my best case scenario
  • 540 clickks (7*3+20*3+11*3*3)*3 for my average scenario
  • 7462 clickks (7*13+20*13+11*13*5)*7 for my worst case scenario

The exact numbers are not important. What matters is that the result has order of n3 time complexity, i.e. it takes cubic time to deploy many Mashups on multiple environments, several times a day !!! In reality the number of environments is pretty constant, so the result will tend to order n2, but that’s still quadratic, not linear. Also, the number of Mashups and the number of times per day will eventually reach a limit, and the result will be constant, but still insanely high (in the range of 7462 clickks in my case).

$ command line ?

The goal is to reduce the number of clickks to a matter of a few double-clicks, ideally via the command line. How? The step in Smart Office can easily be done with a command line, it’s a simple archive of an archive (we can use ZIP tools, command line, .NET System.IO.Packaging.Package, or the Pack.exe tool in the Smart Office SDK). But the steps in LCM do not have a command line. They are Apache Velocity scripts, compiled into Apache Ant tasks, that execute Java code, remotely, to upload files to the server and add records to the Apache Derby database (lcmdb), and also the Mashups contents are saved as blobs in the MangoServer Grid database (GDBC) which is a distributed H2 database (h2db). I think. There is probably a distributed in-memory Grid cache as well. I could not find documentation nor a quick hack for all this.

Ideally there would be a command line like this fake screenshot:

Do you have any suggestions? Please let me know in the comments below.

Thank you.

Related posts