Abstract :
Setting up Liferay development environment by installing Liferay binaries and running them on the local laptop with a custom MySQL database involves installing the database, establishing connectivity and ensuring that the desktop setup has all environment settings configured to run continuously during development. A more easier approach is the serverless one, where we spin up docker containers and can be up and running quickly.
A similar approach applies for Liferay commerce too where one can spin up a Liferay commerce server using a docker image and build an ecommerce site using the minimum accelerator within no time.
Objective:
Our objective is to see how to:
- Setup Liferay 7.3.5 connected to MySQL 5.7 in a docker container
- Setup Liferay commerce 2.0.5 to a docker container and spin up our own ecommerce site
- Write a Jython portlet and run it in Liferay
Setup Liferay 7.3.5 connected to MySQL 5.7 in a docker container

- Clone the code available in the GitHub repo : https://github.com/ragnaray/liferay-mysql-custom/tree/master/liferay-portal
- download liferay-ce-portal-tomcat-7.3.5-ga6-20200930172312275.tar and copy to liferay-portal\configs\common
- Open in Intellij editor
- Install the Liferay Intellij Plugin from marketplace
- Create a Liferay workspace in Intellij File → New → Project
- Select the Liferay option on the left menu bar and choose Liferay Maven workspace and click Next

- Select the name of your project (for eg. liferay-portal)

- Choose the folder in which you will create your workspace and click Finish.
- Run the following commands to build the custom MySQL DB docker image and push it to your own docker repo (lets call it https://hub.docker.com/repository/docker/goldvault)
- docker build -t mysql_liferay:latest .
- docker tag mysql_liferay:latest goldvault/mysql_liferay:latest
- docker push goldvault/mysql_liferay:latest
10. Run the following commands to build the liferay portal docker image and push it to your own docker repo
- docker build -t liferay:latest .
- docker tag liferay:latest goldvault/liferay:latest
- docker push goldvault/liferay:latest
11. Create a new docker-compose.yml with the following instructions
version: '3.4'
services:
liferay:
image: "goldvault/liferay:latest"
depends_on:
- mysql_liferay
volumes:
- "./configs/docker/osgi/modules:/opt/liferay/deploy"
- "./configs/dev/portal-ext.properties:/opt/liferay/portal-ext.properties"
ports:
- "8080:8080"
- "9000:9000"
- "8000:8000"
- "11311:11311"
environment:
- "LIFERAY_HOME=/opt/liferay"
- "CATALINA_HOME=/opt/tomcat"
- "JAVA_OPTS=-Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n"
networks:
- lfrnet
mysql_liferay:
container_name: "mysql_dev"
image: "goldvault/mysql_liferay:latest"
ports:
- "3306:3306"
environment:
- "MYSQL_ROOT_PASSWORD=root"
networks:
- lfrnet
networks:
lfrnet:
12.run the command
docker-compose up
from the folder containing this docker-compose.yml file
13.You will get some errors initially, then run docker-compose stop
14.Next run docker-compose start
15.Navigate to localhost:8080 and enter your email , accept terms and conditions.
You are now all set to start your portlet development
Setup Liferay commerce 2.0.5 to a docker container and spin up our own ecommerce site
- Run
docker pull liferay/commerce:2.0.5
docker run -it -p 8080:8080 liferay/commerce:2.0.5

2. Open a new browser and navigate to : https://localhost:8080
3. Click the Sign In link and enter the default liferay credentials test@liferay.com/test
4. Next open the Product Menu and navigate to the Account Menu -> My Account -> Account Settings. In the information tab add a new user information for admin user admin@liferay.com and password <mysecretgoldvault#007>
5. Sign-out of your account.
6. Next we shall be using the Liferay out-of-box Minimum accelerator to build our quick ecommerce site. Navigate to Control Panel → Sites → Sites, Click the Add (+) button to add a new site, Choose an Accelerator (Minimum).
7. Enter a name: minime.iot.store, Click Save, In the Site Menu click Go to Site.
8. Here we shall be using all the default pages and widgets provided by Minimum. Customization of the pages is out of scope of this blog. (The store is currently facing problems hiring developers due to their very high expected salary)
9. Presented below are all the out-of-box pages that will be customized as part of our project Vulcan when Dr Evil is able to hire Austin the developer, Vanessa the Business Analyst and Frau the Project Manager from the market.





Write a Jython portlet and run it in Liferay
While we all agree that java is de-facto language for developing portlets. Jython has several advantages:
- Python syntax (used by Jython) is considerably more concise and quicker to develop for many programmers.
- Use can use the several data analytics libraries readily available in python and enjoy the benefits of both the UI based portlet world and the processing power of python.
So lets get going
- Install Jython on ubuntu using the command apt install Jython
- jip is a package manager similar to pip which we shall be using to install java libraries in python. Navigate to : https://pypi.org/project/jip/#files and download jip-0.9.15.tar.gz (22.6 kB)
- untar the file and navigate to the folder containing setup.py. run
jython setup.py install
4. You can now go ahead and install all required java libraries using the command
jip install <groupId>:<artifactId>:<version>
eg.
jip install javax.portlet:portlet-api:3.0.0
jip install org.apache.portals.bridges:portals-bridges-script-dependencies-jython:2.0
jip list
jip remove xerces:xercesImpl:2.9.1
5. Create a HelloJython.py file to host our portlet code
from jip.embed import require
require('javax.portlet:portlet-api:3.0.0')
from javax.portlet import GenericPortlet
#require('xerces:xerces:2.4.0')
#from org.apache.xerces.parsers import SAXParser
#
# HelloJython.py
#
class HelloJython(GenericPortlet):
def doView(self, request, response):
greeting = "<H1>Hello, Jython!</H1>"
response.writer.println(greeting)
# Return portlet instance as a last evaluated object
# because ScriptPortlet expects the evaluated result object
# as a portlet class or non-initialized portlet instance.
value = HelloJython()
6. Create a portlet.xml file similar to the one below
<?xml version="1.0" encoding="UTF-8"?>
<portlet-app id="velocitysimplest" version="1.0">
<portlet>
<portlet-name>HelloJython</portlet-name>
<display-name>Hello Jython</display-name>
<portlet-class>org.apache.portals.bridges.script.ScriptPortlet</portlet-class>
<!-- Optional init parameter for script engine
If this init parameter is not set, the ScriptPortlet will look up a script engine automatically
by the mimeType or the extension of the script source file. -->
<init-param>
<name>engine</name>
<!--
Note: You can set other script engine which support JSR-223 ScriptEngine
such as 'groovy', 'jruby', 'jython'.
-->
<value>jython</value>
</init-param>
<!-- Optional init parameter for the key for portlet/preferencesValidator class or
portlet/preferencesValidator instance which is evaluated and returned by the script.
By default, when this init parameter is not set, ScriptPortlet retrieves
the last evaluated object from the script.
If you set this to 'value', then ScriptPortlet retrieves an object named 'value'
from the bindings of the script engine.
Depending on script engines, this init parameter should be properly configured
because some script engines do not return the last evaluated object. -->
<init-param>
<name>eval-key</name>
<value>value</value>
</init-param>
<!-- Required init parameter for script source path -->
<init-param>
<name>source</name>
<!--
Note: You can set script source in three ways.
The first is to use context relative path,
the second is to use file: url,
and the third is to classpath: uri.
Here are the examples for each way.
-->
<!--
<value>/WEB-INF/groovy/HelloGroovy.groovy</value>
<value>file:/C:/Program Files/Tomcat/webapps/demo/WEB-INF/groovy/HelloGroovy.groovy</value>
<value>classpath:org/apache/portals/bridges/script/HelloGroovy.groovy</value>
-->
<value>classpath:org/apache/portals/bridges/script/HelloJython.py</value>
</init-param>
<!-- Optional init parameter for script file content encoding. The default value is 'UTF-8'. -->
<init-param>
<name>encoding</name>
<value>UTF-8</value>
</init-param>
<!-- Optional init parameter for auto-refresh option.
If auto-refresh is true, then a modification of script source can be refreshed automatically.
By default, this option is set to false. -->
<init-param>
<name>auto-refresh</name>
<value>true</value>
</init-param>
<!-- Optional init parameter for refresh-delay option.
When auto-refresh is true, this init parameter sets the milliseconds of automatic refreshing interval.
By default, this option is set to 60000 milliseconds (a minute). -->
<init-param>
<name>refresh-delay</name>
<value>60000</value>
</init-param>
<!-- Optional init parameter for script preferences validator path -->
<init-param>
<name>validator</name>
<!--
Note: You can set script preferences validator source in three ways.
The first is to use context relative path,
the second is to use file: url,
and the third is to classpath: uri.
Here are the examples for each way.
-->
<!--
<value>/WEB-INF/groovy/HelloGroovyPrefsValidator.groovy</value>
<value>file:/C:/Program Files/Tomcat/webapps/demo/WEB-INF/groovy/HelloGroovyPrefsValidator.groovy</value>
<value>classpath:org/apache/portals/bridges/script/HelloGroovyPrefsValidator.groovy</value>
-->
<value>classpath:org/apache/portals/bridges/script/HelloJythonPrefsValidator.py</value>
</init-param>
<!-- The followings are not special for ScriptPortlet, but normal configurations for a portlet. -->
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
<portlet-mode>EDIT</portlet-mode>
<portlet-mode>HELP</portlet-mode>
</supports>
<supported-locale>en</supported-locale>
<portlet-info>
<title>Hello Jython</title>
<short-title>Hello Jython</short-title>
<keywords>demo,jython</keywords>
</portlet-info>
<portlet-preferences>
<preference>
<name>message</name>
<value>Hello, Jython!</value>
</preference>
<preferences-validator>org.apache.portals.bridges.script.ScriptPortletPreferencesValidator</preferences-validator>
</portlet-preferences>
</portlet>
</portlet-app>
7. Package and deploy the war file to tomcat.
Still checking if this Jython portlet thing works in 2021. So this section can be considered dicey for now. But the first 2 sections are good to go.
References:Reference:
- https://github.com/ragnaray/liferay-mysql-custom/tree/master/liferay-portal
- https://hub.docker.com/repository/docker/20112945/liferay
- https://hub.docker.com/repository/docker/20112945/mysql_liferay
- https://serafeimkourlos.medium.com/liferay-portal-with-mysql-in-docker-compose-file-ce866906456d
- https://learn.liferay.com/commerce/latest/en/installation-and-upgrades/installing-commerce-2.1-and-below/using-the-liferay-commerce-docker-image.html
- https://learn.liferay.com/commerce/latest/en/starting-a-store/accelerators.html
- https://portals.apache.org/bridges/bridges-script/index.html
Good Bye ! Stay Safe ! and Stay Hands On!