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.bndfile, and specify aLiferay-Require-SchemaVersionheader 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.1ImportantIf no
Liferay-Require-SchemaVersionheader is specified, Liferay considers theBundle-Versionheader 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.xmlfile). An example configuration for abuild.gradlefile is shown below:compile group: "com.liferay", name: "com.liferay.portal.upgrade.api", version: "2.0.3" -
Create an
UpgradeProcessclass that extends theUpgradeProcessbase class (which implements theUpgradeStepinterface):public class MyUpgradeSchemaClass extends UpgradeProcess { ... } -
Override the
UpgradeProcessclass’sdoUpgrade()method with instructions for modifying the database. Use therunSQLandrunSQLTemplate*methods (inherited from theBaseDBProcessclass) 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 theUpgradeProcessclass’srunSQLoraltermethods, along with tokens that allow porting the sentences to different databases, as shown in journal-service module’sUpgradeSchemaupgrade step class below which uses therunSQLTemplateStringmethod to execute ANSI SQL DDL from an SQL file and thealtermethod andUpgradeProcess’sUpgradeProcess.AlterColumnNameandUpgradeProcess.AlterColumnTypeinner 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.servicemodule. It uses thealtermethod 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
UpgradeStepRegistratorOSGi Component class of service typeUpgradeStepRegistrator.classthat implements theUpgradeStepRegistratorinterface: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
registermethod 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.0to2.0.0,1.0.0to1.1.0, and1.1.0to2.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.0to1.1.0) below for theUpgradeFooclass: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
@Referenceannotation to declare any classes that the registrator class depends on. For example, theWikiServiceUpgraderegistrator class below references theSettingsFactoryclass for theUpgradePortletSettingsupgrade step. ThesetSettingsFactorymethod’s@Referenceannotation declares that the registrator class depends on and must wait for theSettingsFactoryservice 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-SchemaVersionto the latest schema version for Service Builder services. For all other services, specify an@Referenceannotation 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.webmodule’sPageCommentsPortletclass upgrades to schema version2.0.0by 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
VerifyProcessare deprecated. Verifications should be tied to schema versions. Upgrade processes are associated with schema versions butVerifyProcessinstances 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_INITIALIZEDevent 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_INITIALIZEDis registered and they must be finished when thePORTLETS_INITIALIZEDevent 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;