Speeding-Up Re-Deployment of WAR Artifacts in Liferay 7.x

Thin WAR Artifacts

Sometimes WAR artifacts are quite thin, meaning they are less than 1MB in size and most of their dependencies are deployed as OSGi modules. In other words, these types of WAR artifacts have portlet-specific code in WEB-INF/classes but few (if any) embedded jars in WEB-INF/lib.

Deployment of thin WARs can be quite fast -- typically only couple of seconds more than an OSGi JAR artifact. (The reason why WAR artifacts are generally slower to deploy than OSGI JAR artifacts is because they must first be transformed into an OSGi Web Application Bundle (WAB) by Liferay's WAB Generator.)

Thick WAR Artifacts


But sometimes WAR artifacts can be quite thick, meaning they are tens (or sometimes 100+ MB) because they include many dependencies as embedded jars in WEB-INF/lib. I first experienced this when building-out support for Oracle ADF portlets in Liferay. A typical ADF Faces portlet starts out at 35MB and embeds about 15 ADF-specific dependency JARs in WEB-INF/lib. But in order to support ADF Task Flows, there are an additional 60+ dependencies and the size of the WAR artifact will increase to 107MB.

Slow Re-Deployment


I found that subsequent re-deploys of an ADF Task Flows portlet tended to get longer and longer. For example:

First Deployment: 18.5 sec
Subsequent re-deploys: 15.1 sec, 16.7 sec, 21.3 sec, 21.2 sec, 31.0 sec, 26.1 sec, 30.7 sec, 38.7 sec

Actually, the system became unresponsive after eight or nine attempts!



The solution to this problem was to override the default value of the module.framework.web.servlet.annotation.scanning.blacklist property in the $LIFERAY_HOME/ file. This property is used to improve the performance of the WAB Generator by restricting the scanning of classes using a package name blacklist. For portlets with embedded dependencies, it's typically possible to blacklist most (if not all) of the packages found inside of the embedded JAR dependencies in WEB-INF/lib.

Specifically, I developed and executed the following Bash script which listed all of the package names found in the embedded JAR dependencies in WEB-INF/lib:

FILES=`find target/ -name \*\.jar -print`
rm -f find-packages.txt
touch find-packages.txt
for file in $FILES; do
        jar tvf $file | awk '{print $8}' |  sed s:/[^/]*$:: >> find-packages.txt
cat find-packages.txt | sort -u | grep "\/" | sed -e 's/$/\/,\\/g'
rm find-packages.txt

I then appended the output of this script to the default value of the module.framework.web.servlet.annotation.scanning.blacklist property in the $LIFERAY_HOME/ file.

After restarting the portal, my first deployment took about the same amount of time, but the subsequent redeploys were faster and became much more consistent. In addition, the system stayed responsive (it did not become unresponsive):

First Deployment: 18.2 sec
Subsequent re-deploys: 13.4 sec, 13.6 sec, 13.5 sec, 13.0 sec, 13.9 sec, 13.7 sec, 13.0 sec, 13.0 sec, 13.1 sec, 13.4 sec


The aforementioned blacklist property was introduced as part of LPS-86820 and according to the JIRA ticket, it is available in 7.0 DXP, 7.1 DXP, 7.2.1 CE GA2, and 7.2 DXP.

There is also a whitelist property that was introduces as part of LPS-98771 and according to the JIRA ticket, it is available in 7.1 DXP,  7.2.1 CE GA2, and 7.2 DXP.


Sometimes developers are unable to avoid embedding dependencies in WEB-INF/lib for WAR artifacts. In order to improve the performance of the WAB Generator during re-deploys, you can override the default value of the module.framework.web.servlet.annotation.scanning.blacklist property.  I would recommend doing this even if you have very few dependencies in WEB-INF/lib, since you should always experience some performance benefit, even if it is small.




Neil, in the title you state "Liferay 7.x" but the property "module.framework.web.servlet.annotation.scanning.blacklist" doesn't seem to exist for versions before 7.2.


I had a small glimmer of hope we could improve re-deployment times in our current 7.0 installations, too.

Alexander, thanks for pointing that out. I just updated the blog post with an "Availability" section and it is available in 7.0 DXP via fix pack. Are you a 7.0 DXP customer or are you using 7.0 CE?