Tech Blog

Override LPKG

How to patch Liferay using the LPKG override

Antonio Musarra
Software Architect
4 minutes read
liferay, lpkg, and openjdk
This article is also available in Italiano 🇮🇹

A few days ago I had the happy idea of updating the version of OpenJDK from 11.0.5 to 11.0.6. It seemed that everything went in the right direction but I was struck by the famous proverb

Don't leave the old road for the new one

When starting Liferay Portal 7.2 GA2 CE here you will see the pretty hateful error indicated below (in console 1).

Caused by: org.apache.jasper.JasperException: PWC6033: Error in Javac compilation for JSP
	at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:655)
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:375)
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:473)
	at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:377)
	at org.eclipse.equinox.http.servlet.internal.servlet.RequestDispatcherAdaptor.include(RequestDispatcherAdaptor.java:48)
	at deployment.ROOT.war//com.liferay.portlet.internal.PortletRequestDispatcherImpl.dispatch(PortletRequestDispatcherImpl.java:291)
	... 165 more
Caused by: java.lang.RuntimeException: java.lang.NullPointerException: entry
Console 1 - PWC6033 error excerpt for JSP compilation

After some research I discovered that the error is due to a bug (again open) on OpenJDK 11.0.6 [JDK-8237875 (zipfs) Directory Stream entries changed behavior between JDK 11.0.5 and JDK 11.0.6](https://bugs.openjdk.java.net/browse/JDK- 8237875)

Liferay for its part has taken steps to resolve, even quickly, through LPS-107983 - OpenJDK 11.0.6 compatibility problem. This LPS is already closed and solves the problem on the 7.x and master branches.

How can we patch the LPS without waiting for the new GA to come out?

The possible solutions are:

  1. Downgrade OpenJDK to version 11.0.5;
  2. If we have the DXP we are in a position to request support directly from Liferay;
  3. If we have the CE we can apply the patch autonomously.

The first way is not always viable due to the fact that most of the Sometimes the JDK update is one of those components whose update is centralized and we have therefore little room for maneuver.

The second route is easy to follow and usually in a few days gets the Hot Fix.

In order not to miss anything, I would say to choose the third way, which is the most interesting one.

1. How to apply the patch

Let's see how it is possible and simple to apply the patch to Liferay Portal CE. The reference version is Liferay CE Portal 7.2.1 GA2.

How can we apply our Hot Fix also on the CE? The answer it's really simple: Overriding lpkg files.

The bundle we need to patch to (https://patch-diff.githubusercontent.com/raw/brianchandotcom/liferay-portal/pull/84189.patch) 84189 is Liferay Portal OSGi Web Servlet JSP Compiler (com.liferay.portal.osgi.web.servlet.jsp.compiler) which is part of the LPKG Liferay CE Static - Impl.lpkg. In this case we can then apply the Overriding lpkg files, even to the Static ones.

The procedure to follow is:

  1. Create the jar format bundle containing the patch;
  2. The bundle name must be the same as the original, minus the version information;
  3. Copy the bundle .jar file to the $LIFERAY_HOME/osgi/static folder;
  4. Remove the contents of the $LIFERAY_HOME/osgi/state directory;
  5. Launch Liferay Portal. Note that every time they add and remove .jars like this, you need to close and restart Liferay Portal for make the changes effective.

If you need to restore your customizations, delete the .jar files replacement: Liferay Portal will use the original .jar file to the next start.

It all seems very clear!

How do we create the new bundle that will contain the LPS-107983 patch? We will see this in the next chapter.

2. How to create the bundle with the patch

To create the new bundle you need the sources and to get them they exist essentially two ways which are:

  1. Clone of the sources of Liferay Portal 7.2.1 GA1 from the GitHub repository;
  2. Obtain the sources from the Maven repository com.liferay.portal.osgi.web.servlet.jsp.compiler version 4.0.14.

The choice of the first road could take a long time because of the clone of the repository which even if executed with the --depth 1 option takes some time.

Personally I chose the second path, which in a few minutes will allow us to get the bundle with the patch. To follow all the necessary steps (and not necessary no IDE). Here is the list of macro tasks:

  1. Creation of a Liferay Workspace via blade;
  2. Creating the directory structure for the portal-osgi-web-servlet-jsp-compiler module;
  3. Copy the sources from the bundle jar downloaded from the Maven repository into the module on Liferay Workspace;
  4. Download the bnd.bnd from the Liferay GitHub repository and place it on the root of the module;
  5. Download the build.gradle from Liferay's GitHub repository and place it on the module root;
  6. Modify the build.gradle to add FileUtil (com.liferay.gradle.util.FileUtil);
  7. Apply the patch 84189;
  8. Build the module;
  9. Make sure the portal is turned off;
  10. Install the module in $LIFERAY_HOME/osgi/static;
  11. Start the portal.

The set of commands shown below carry out steps 1 to 5. If you want save this time too, then you can draw directly on repository that I have prepared for you https://github.com/smclab/apply-lps-107983-openjdk-11-0-6

$ mkdir ~/apply-lps-107983-openjdk-11-0-6
$ cd ~/apply-lps-107983-openjdk-11-0-6
$ blade init -v 7.2
$ mkdir modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler
$ mkdir -p src/main/java
$ mkdir -p src/main/resources
$ cd src/main/java
$ curl https://repo1.maven.org/maven2/com/liferay/com.liferay.portal.osgi.web.servlet.jsp.compiler/4.0.14/com.liferay.portal.osgi.web.servlet.jsp.compiler-4.0.14-sources.jar | jar xv
$ rm -rf META-INF/
$ mv javax ../resources
$ curl -L -O https://github.com/liferay/liferay-portal/raw/7.2.1-ga2/modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler/bnd.bnd
$ curl -L -O build.gradle https://github.com/liferay/liferay-portal/raw/7.2.1-ga2/modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler/build.gradle
Console 2 - Steps needed to prepare the patch bundle

Step 6 requires editing the build.gradle file, this is necessary so that you do not get the error shown below.

Could not compile build file '/Users/antoniomusarra/Progetti/MyProjects/Liferay/sources/apply-lps-107983-openjdk-11-0-6/modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler/build.gradle'.
> startup failed:
  build file '/Users/antoniomusarra/Progetti/MyProjects/Liferay/sources/apply-lps-107983-openjdk-11-0-6/modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler/build.gradle': 1: unable to resolve class com.liferay.gradle.util.FileUtil
   @ line 1, column 1.
     import com.liferay.gradle.util.FileUtil
     ^
Console 3 - Compilation error before modification of build.gradle

To avoid the error, the content must be added to the build.gradle file shown below.

buildscript {
   dependencies {
      classpath group: "com.liferay", name: "com.liferay.gradle.util", version: "1.0.36"
   }

   repositories {
      maven {
         url "https://repository-cdn.liferay.com/nexus/content/groups/public"
      }
   }
}
Listing 1 - Modifying the build.gradle to add the required dependency

At this point we are in a position to apply the patch in the following way.

$ cd ~/apply-lps-107983-openjdk-11-0-6
$ curl -O https://patch-diff.githubusercontent.com/raw/brianchandotcom/liferay-portal/pull/84189.patch
$ git apply --verbose 84189.patch
Console 4 - Patching the Liferay sources of the affected bundle

If everything goes as it should, you should see an output similar to the one shown in the following figure.

Figure 1 - Patch application to the Liferay sources of the bundle affected by the bug
Figure 1 - Patch application to the Liferay sources of the bundle affected by the bug

Once applied we can proceed with the build of the bundle using the classic build command

$ ./gradlew build
Console 5 - Build of the bundle

With the portal off, we copy the new bundle (without the version) inside of the $LIFERAY_HOME/osgi/static/directory

$ cp modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler/build/libs/com.liferay.portal.osgi.web.servlet.jsp.compiler-4.0.14.jar /Users/antoniomusarra/dev/liferay/liferay-ce-portal-7.2.1-ga2-wildfly-16/osgi/static/com.liferay.portal.osgi.web.servlet.jsp.compiler.jar
Console 6 - Copy the bundle with patch in $LIFERAY_HOME/osgi/static/

At this point, after deleting the contents of the directory $LIFERAY_HOME/osgi/state/, we start the portal. Watch out for Liferay's logs why you should see the following log lines indicating the happened installation of the new bundle that overrides the existing one.

2020-03-24 22:17:48.836 INFO  [ServerService Thread Pool -- 73][ModuleFrameworkImpl:1468] Starting initial bundles
2020-03-24 22:17:49.234 INFO  [ServerService Thread Pool -- 73][ModuleFrameworkImpl:952] /Users/antoniomusarra/dev/liferay/liferay-ce-portal-7.2.1-ga2-wildfly-16/osgi/marketplace/Liferay CE Static - Impl.lpkg:com.liferay.portal.osgi.web.servlet.jsp.compiler-4.0.13.jar is overridden by /Users/antoniomusarra/dev/liferay/liferay-ce-portal-7.2.1-ga2-wildfly-16/osgi/static/com.liferay.portal.osgi.web.servlet.jsp.compiler.jar
Log 1 - Liferay start-up log with evidence of the bundle override operation

Once the portal is up and running, deploy any MVC portlet e check that you no longer get compilation errors on the JSPs. Figures a following show the home page of the Liferay portal before and after installation bundle with the patch.

Figure 2 - Portlet in error before without the patch
Figure 2 - Portlet in error before without the patch
Figure 3 - Portlet working after installing bundle with patch
Figure 3 - Portlet working after installing bundle with patch

In these cases, when we go to patch Liferay components, it is advisable to highlight it, for example with a suitable indication on the Bundle Name.

g! lb com.liferay.portal.osgi.web.servlet.jsp.compiler
START LEVEL 20
   ID|State      |Level|Name
    1|Active     |    6|Liferay Portal OSGi Web Servlet JSP Compiler (SMC - PATCHED-1) (4.0.14)|4.0.14
g!
Console 7 - Access to the Gogo Shell and verification of the new bundle installed

Very well! Now we have our Liferay 7.2 GA2 Portal that works with OpenJDK 11.0.6

3. Conclusions

In this article we have seen how simple it is to apply a patch to a core component of Liferay without the need to wait for the next release. All this is made possible for three simple reasons:

  1. Liferay is Open Source;
  2. Liferay since version 7.0 has adopted in full OSGi, ergo, the welcome to modularity;
  3. Liferay has developed sets of frameworks that facilitate its extension, including the core components of the portal.

Before you throw in the towel when you encounter a problem that may seem insurmountable, I always advise you to consult the documentation of Liferay where in most of you could find the solution to your problem.

written by
Antonio Musarra
Software Architect
In SMC he holds the role of Senior Software Architect and generally deals with specialist consultancy on projects concerning the Liferay platform, in particular taking care of the aspects of integration with other systems. He believes in sharing knowledge as a means of personal growth and for this reason, about eight years ago, he created his own blog: Antonio Musarra's Blog www.dontesta.it. With the desire to still share, he published his first eBook on Amazon in 2015, Sviluppo Liferay con Maven, arriving at his latest publication in 2018 with the eBook Liferay Portal Security Audit.

You might also like…