Multithreading Process
Liferay DXP 7.4 U10+ or Liferay Portal 7.4 GA14+
Your Upgrade Processes may involve making complex changes to large data sets. If performance is critical, use the processConcurrently()
method in the UpgradeProcess
class of your application. This method executes in multiple threads and can shorten your upgrade times.
Deploy Version 1.0.0
Start a new Liferay DXP instance by running
docker run -it -m 8g -p 8080:8080 liferay/dxp:2024.q2.11
Sign in to Liferay at http://localhost:8080 using the email address test@liferay.com and the password test. When prompted, change the password to learn.
Then, follow these steps:
-
Download and unzip Multithreading Process.
curl https://resources.learn.liferay.com/dxp/latest/en/building-applications/data-frameworks/upgrade-processes/liferay-j7z3.zip -O
unzip liferay-j7z3.zip
-
Move into the
1.0.0
directory, build and deploy.cd 1.0.0
../gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)
NoteThis command is the same as copying the deployed jars to /opt/liferay/osgi/modules on the Docker container.
-
Confirm the deployment in the Liferay Docker container console.
STARTED com.acme.j7z3.api_1.0.0 [1030] STARTED com.acme.j7z3.service_1.0.0 [1031]
Add Entries to the App
-
Navigate to the Script console at Control Panel → Server Administration → Script.
-
Add some entries by executing the following script.
import com.acme.j7z3.service.J7Z3EntryLocalServiceUtil; import com.liferay.portal.kernel.dao.orm.QueryUtil; entry1 = J7Z3EntryLocalServiceUtil.createJ7Z3Entry(1); entry2 = J7Z3EntryLocalServiceUtil.createJ7Z3Entry(2); entry3 = J7Z3EntryLocalServiceUtil.createJ7Z3Entry(3); entry1.setName("able"); entry2.setName("able"); entry3.setName("able"); J7Z3EntryLocalServiceUtil.addJ7Z3Entry(entry1); J7Z3EntryLocalServiceUtil.addJ7Z3Entry(entry2); J7Z3EntryLocalServiceUtil.addJ7Z3Entry(entry3);
The J7Z3_J7Z3Entry table now has three entries.
Execute the Upgrade
-
Move into the
1.0.1
directory, build and deploy.cd ../1.0.1
../gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)
-
Navigate to the Gogo shell console at Control Panel → Gogo Shell.
-
Verify that the 1.0.1 upgrade is available by entering the command
upgrade:list com.acme.j7z3.service
. The 1.0.1 version appears as a registered upgrade process in the output window. -
Execute the upgrade by entering the command
upgrade:execute com.acme.j7z3.service
. The output window shows that the upgrade was completed. -
The J7Z3_J7Z3Entry table entries have now been updated.
Implement the Multithreading Method
In the UpgradeProcess
class of your application, override the processConcurrently()
method.
@Override
protected void doUpgrade() throws Exception {
processConcurrently(
"select j7z3EntryId, name from J7Z3_J7Z3Entry",
resultSet -> new Object[] {
resultSet.getLong("j7z3EntryId"), resultSet.getString("name")
},
columns -> {
long j7z3EntryId = (Long)columns[0];
try (PreparedStatement preparedStatement =
connection.prepareStatement(
"update J7Z3_J7Z3Entry set name = ? where " +
"j7z3EntryId = ?")) {
preparedStatement.setString(1, "baker");
preparedStatement.setLong(2, j7z3EntryId);
preparedStatement.executeUpdate();
}
},
null);
}
The method has four parts:
-
SQL Query - An SQL statement to query the database data.
-
Gathering objects - Receive a result set and return an array of objects based on the result set.
-
Processing objects - Execute business logic on the array of objects.
-
Exception - Send a message if an exception occurs.
The sample project shows a simple example where the name
field is processed and modified by the processConcurrently()
method.
-
select j7z3EntryId, name from J7Z3_J7Z3Entry
- The SQL statement queries all the entries. -
resultSet -> new Object[] { resultSet.getLong("j7z3EntryId"), resultSet.getString("name")
The objects are gathered and stored in the
resultSet
array. -
columns -> { long j7z3EntryId = (Long)columns[0]; try (PreparedStatement preparedStatement = connection.prepareStatement( "update J7Z3_J7Z3Entry set name = ? where " + "j7z3EntryId = ?")) { preparedStatement.setString(1, "baker"); preparedStatement.setLong(2, j7z3EntryId); preparedStatement.executeUpdate(); } }
For every
j7z3EntryId
, thename
field is set asbaker
. -
The exception is set to
null
.
The processConcurrently()
method has two different signatures. One signature passes a SQL query as the source, as seen in this tutorial example. The other signature passes an array as the source. See the BaseDBProcess javadocs to learn more.