Using Upgrade Processes in Earlier Versions
Liferay DXP 7.4 U10/Portal 7.4 GA14 and Below
Follow these steps to create an upgrade process for your module:
-
Open your module’s
bnd.bnd
file, and specify aLiferay-Require-SchemaVersion
header with the new schema version value. Here’s an example schema version header for a module whose new schema is version1.1
:Liferay-Require-SchemaVersion: 1.1
ImportantIf no
Liferay-Require-SchemaVersion
header is specified, Liferay considers theBundle-Version
header value to be the database schema version. -
Add a dependency on the
com.liferay.portal.upgrade
, along with any other modules your upgrade process requires, in your module’s dependency management file (e.g., Maven POM, Gradle build file, or Ivyivy.xml
file). An example configuration for abuild.gradle
file is shown below:compile group: "com.liferay", name: "com.liferay.portal.upgrade.api", version: "2.0.3"
-
Create an
UpgradeProcess
class that extends theUpgradeProcess
base class (which implements theUpgradeStep
interface):public class MyUpgradeSchemaClass extends UpgradeProcess { ... }
-
Override the
UpgradeProcess
class’sdoUpgrade()
method with instructions for modifying the database. Use therunSQL
andrunSQLTemplate*
methods (inherited from theBaseDBProcess
class) to execute your SQL commands and SQL DDL, respectively. If you want to create, modify, or drop tables or indexes by executing DDL sentences from an SQL file, make sure to use ANSI SQL only. Doing this assures the commands work on different databases. If you must use non-ANSI SQL, it’s best to write it in theUpgradeProcess
class’srunSQL
oralter
methods, along with tokens that allow porting the sentences to different databases, as shown in journal-service module’sUpgradeSchema
upgrade step class below which uses therunSQLTemplateString
method to execute ANSI SQL DDL from an SQL file and thealter
method andUpgradeProcess
’sUpgradeProcess.AlterColumnName
andUpgradeProcess.AlterColumnType
inner classes as token classes to modify column names and column types:public class UpgradeSchema extends UpgradeProcess { @Override protected void doUpgrade() throws Exception { String template = StringUtil.read( UpgradeSchema.class.getResourceAsStream("dependencies/update.sql")); runSQLTemplateString(template, false, false); upgrade(UpgradeMVCCVersion.class); alter( JournalArticleTable.class, new AlterColumnName( "structureId", "DDMStructureKey VARCHAR(75) null"), new AlterColumnName( "templateId", "DDMTemplateKey VARCHAR(75) null"), new AlterColumnType("description", "TEXT null")); alter( JournalFeedTable.class, new AlterColumnName("structureId", "DDMStructureKey TEXT null"), new AlterColumnName("templateId", "DDMTemplateKey TEXT null"), new AlterColumnName( "rendererTemplateId", "DDMRendererTemplateKey TEXT null"), new AlterColumnType("targetPortletId", "VARCHAR(200) null")); } }
Here’s a simpler example upgrade step from the
com.liferay.calendar.service
module. It uses thealter
method to modify a column type in the calendar booking table:public class UpgradeCalendarBooking extends UpgradeProcess { @Override protected void doUpgrade() throws Exception { alter( CalendarBookingTable.class, new AlterColumnType("description", "TEXT null")); } }
-
If your application was modularized from a former traditional Liferay plugin application (application WAR) and it uses Service Builder, create and register a Bundle Activator to register it in Liferay’s
Release_
table. -
Create an
UpgradeStepRegistrator
OSGi Component class of service typeUpgradeStepRegistrator.class
that implements theUpgradeStepRegistrator
interface:package com.liferay.mycustommodule.upgrade; import com.liferay.portal.upgrade.registry.UpgradeStepRegistrator; import org.osgi.service.component.annotations.Component; @Component(immediate = true, service = UpgradeStepRegistrator.class) public class MyCustomModuleUpgrade implements UpgradeStepRegistrator { }
-
Override the
register
method to implement the module’s upgrade registrations—abstractions for the upgrade steps required to update the database from one schema version to the next. For example, the upgrade step registrator classMyCustomModuleUpgrade
(below) registers three upgrade steps incrementally for each schema version (past and present,0.0.0
to2.0.0
,1.0.0
to1.1.0
, and1.1.0
to2.0.0
).The first registration is applied if the module hasn’t been installed previously. It contains only one empty upgrade step: a new
DummyUpgradeStep
. This registration records the module’s latest schema version (i.e.,2.0.0
) in Liferay’sRelease_
table. Note that if the same class name is used in multiple packages, you must provide the fully qualified class name for the class, as shown in the second registration (1.0.0
to1.1.0
) below for theUpgradeFoo
class:package com.liferay.mycustommodule.upgrade; import com.liferay.portal.upgrade.registry.UpgradeStepRegistrator; import org.osgi.service.component.annotations.Component; @Component(immediate = true, service = UpgradeStepRegistrator.class) public class MyCustomModuleUpgrade implements UpgradeStepRegistrator { @Override public void register(Registry registry) { registry.register( "com.liferay.mycustommodule", "0.0.0", "2.0.0", new DummyUpgradeStep()); registry.register( "com.liferay.mycustommodule", "1.0.0", "1.1.0", new com.liferay.mycustommodule.upgrade.v1_1_0.UpgradeFoo()); registry.register( "com.liferay.mycustommodule", "1.1.0", "2.0.0", new com.liferay.mycustommodule.upgrade.v2_0_0.UpgradeFoo(), new UpgradeBar()); } }
ImportantModules that use Service Builder should not define a registration for their initial database schema version, as Service Builder already records their schema versions to Liferay’s
Release_
table. Modules that don’t use Service Builder, however, should define a registration for their initial schema. -
If your upgrade step uses an OSGi service, your upgrade must wait for that service’s availability. Use the
@Reference
annotation to declare any classes that the registrator class depends on. For example, theWikiServiceUpgrade
registrator class below references theSettingsFactory
class for theUpgradePortletSettings
upgrade step. ThesetSettingsFactory
method’s@Reference
annotation declares that the registrator class depends on and must wait for theSettingsFactory
service to be available in the run time environment:@Component(immediate = true, service = UpgradeStepRegistrator.class) public class WikiServiceUpgrade implements UpgradeStepRegistrator { @Override public void register(Registry registry) { registry.register("0.0.1", "0.0.2", new UpgradeSchema()); registry.register("0.0.2", "0.0.3", new UpgradeKernelPackage()); registry.register( "0.0.3", "1.0.0", new UpgradeCompanyId(), new UpgradeLastPublishDate(), new UpgradePortletPreferences(), new UpgradePortletSettings(_settingsFactory), new UpgradeWikiPage(), new UpgradeWikiPageResource()); registry.register("1.0.0", "1.1.0", new UpgradeWikiNode()); registry.register( "1.1.0", "1.1.1", new UpgradeDiscussionSubscriptionClassName( _subscriptionLocalService, WikiPage.class.getName(), UpgradeDiscussionSubscriptionClassName.DeletionMode.ADD_NEW)); registry.register( "1.1.1", "2.0.0", new BaseUpgradeSQLServerDatetime( new Class<?>[] {WikiNodeTable.class, WikiPageTable.class})); } @Reference private SettingsFactory _settingsFactory; @Reference private SubscriptionLocalService _subscriptionLocalService; }
-
Upgrade the database to the latest database schema version before making its services available. To do this, configure the Bnd header
Liferay-Require-SchemaVersion
to the latest schema version for Service Builder services. For all other services, specify an@Reference
annotation that targets the containing module and its latest schema version.Here are the target’s required attributes:
release.bundle.symbolic.name
: module’s bundle symbolic namerelease.schema.version
: module’s current schema version
For example, the
com.liferay.comment.page.comments.web
module’sPageCommentsPortlet
class upgrades to schema version2.0.0
by defining the reference below:@Reference( target = "(&(release.bundle.symbolic.name=com.liferay.comment.page.comments.web)(release.schema.version=2.0.0))" ) private Release _release;
Dependencies between OSGi services can reduce the number of service classes in which upgrade reference annotations are needed. For example, you need not add an upgrade reference in a dependent service, if the dependency already refers to the upgrade.
NoteData verifications using the class
VerifyProcess
are deprecated. Verifications should be tied to schema versions. Upgrade processes are associated with schema versions butVerifyProcess
instances are not.
Great! Now you know how to create data upgrades for all your modules.
Module Upgrade Life Cycle
Liferay DXP 7.4 U44+/Portal 7.4 GA44+
To ensure all upgrades run before the servers are opened to the public, there are two OSGi events:
public String PORTAL_INITIALIZED =
"(module.service.lifecycle=portal.initialized)";
public String PORTLETS_INITIALIZED =
"(module.service.lifecycle=portlets.initialized)";
-
When the
PORTAL_INITIALIZED
event is triggered, core upgrade processes should have already run and, in case you are using the upgrade on startup approach, the companies will have been initialized at that point too. -
The module upgrades start running when
PORTAL_INITIALIZED
is registered and they must be finished when thePORTLETS_INITIALIZED
event is triggered. Only after that, in case of the upgrade on startup approach, the server will be available to receive requests.
This way, Liferay ensures all upgrades run before the server is opened to the public.
When depending on these OSGi events, add the following reference to your component. This way, it won’t be available until that event is triggered:
@Reference(target = ModuleServiceLifecycle.PORTAL_INITIALIZED)
private ModuleServiceLifecycle _moduleServiceLifecycle;