Monday, February 24, 2020

Liferay 7.2/DXP Service Builder Behavior for Upgraded Database


When we upgrade portal from older version to newer version, we can see following issues when we deploy migrated service builder bundles. Specially from Liferay 6.1/6.2 to Liferay 7.2/DXP.

Liferay 6.1/6.2 Release_ tables will not add any records for service builder services until unless if write Upgrade Step Process. Liferay 7.2/DXP will behave very different and each and every service builder service must be register in Release_ tables then only service will be available in service registry.

Release_ Table



When we upgraded the database, all tables for service builder portlets are already existed and when we try to deploy migrated bundles in Liferay 7.2 we can see following issues.

The following service(s) are missing:
 * com.liferay.portal.kernel.configuration.Configuration (&(configuration.bundle.symbolic.name=com.foo.mytest.service)(name=service)) is not found in the service registry
 * com.liferay.portal.kernel.model.Release (&(release.bundle.symbolic.name=com.foo.mytest.service)(&(release.schema.version>=1.0.0)(!(release.schema.version>=1.1.0)))(|(!(release.state=*))(release.state=0))) is not found in the service registry

g! dm na
[950] com.foo.mytest.service
 [89] com.liferay.portal.spring.extender.internal.configuration.ServiceConfigurationInitializer unregistered
    com.liferay.portal.kernel.model.Release (&(release.bundle.symbolic.name=com.foo.mytest.service)(&(release.schema.version>=1.0.0)(!(release.schema.version>=1.1.0)))(|(!(release.state=*))(release.state=0))) service required unavailable
 [90] com.liferay.portal.spring.extender.internal.context.ModuleApplicationContextRegistrator unregistered
    com.liferay.portal.kernel.model.Release (&(release.bundle.symbolic.name=com.foo.mytest.service)(&(release.schema.version>=1.0.0)(!(release.schema.version>=1.1.0)))(|(!(release.state=*))(release.state=0))) service required unavailable
    com.liferay.portal.kernel.configuration.Configuration (&(configuration.bundle.symbolic.name=com.foo.mytest.service)(name=service)) service required unavailable
g!


Caused by: org.postgresql.util.PSQLException: ERROR: relation "foo_foo" already exists
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2412)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2125)

We can use following Gogo shell commands to know more about above issues.


ds:unsatisfied
scr:info <service-if>
inspect cap service <bundle-id>

dm wtf
dm na
dependencymanager:dm


Background of Issue

Liferay 7.2 Service builder portlet will use Release_ table to manage versions and each and every service must register in the table for first deployment (Service Builder Bundles). This will help to run Upgrade Step process in future to update/add database related activities for non-developer mode environments. For migrated database, tables already existed for each and every service builder so its assumed that bundle already deployed once and looking for Release_ table version  to proceed and register service.

We can categorize these things into two types of environments

Developer Environment

Example:

Local Development environment for developers schema changes will reflect automatically through schema.module.build.auto.upgrade is true and it will be run based on build number in the service.properties file.


Developer Environment Solution

We can resolve above two issues for Developer Environment with following options.

Option: 1

For local developments is very simple, delete service builder generated tables and delete record from Release_ table (If already exist) then redeploy service bundle then problem will be resolved.

Option: 2

This option will get rid of the manual deletion. We can use Liferay provided Maven or Gradle plugin called DB Support Plugin. Follow the reference links to know more about DB Support Plugin.

For Maven

Add DB Support plugin in the pom file and run db-support:clean-service-builder maven goal so that it will clean


For Gradle


Note:

Option: 1 and Option: 2 recommended for developer environment and your data will be lost in both cases. If you wanted avoid data lost follow the Non-Developer Environment solution.

Non-Developer Environment

Example: Production or Real Lower Level Environments DEV/SIT/UAT

For non-developer mode schema.module.build.auto.upgrade should be false and we have to write Upgrade Step Process component class to update database schema changes. We can also use DBA to execute schema changes related service builder.

Non-Developer Environment Solution

Step:1

Delete bundle from portal osgi\modules directory if already deployed.

Step:2

Add release record in Release_ table with default version 1.0.0 for your service.  ServeletContextName should your service bundle symbolic name.


Step:3

Update service bundle bnd.bnd Liferay-Require-SchemaVersion to default version that we already enter in the Release_ table record.


Step:4

Write dummy upgrade step in service. Follow the reference to create upgrade step with my notes.


You can skip “Writing upgrade steps and Waiting for upgrade completion” because we are trying to use the Dummy Upgrade Step that already as part of portal class loader.
Declaring dependencies need be corrected use com.liferay.portal.upgrade.api instead of com.liferay.portal.upgrade

Gradle:

Add following in the service build.gradle file


compile group: "com.liferay", name: "com.liferay.portal.upgrade.api", version: "2.0.0"

Maven:
Add following in the service pom.xml

<dependency>
            <groupId>com.liferay</groupId>
            <artifactId>com.liferay.portal.upgrade.api</artifactId>
            <version>2.0.0</version>
</dependency>

Upgrade Step Registration

package com.liferaysavvy.student.upgrade;

import com.liferay.portal.kernel.upgrade.DummyUpgradeStep;
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( "1.0.0", "1.0.1",new DummyUpgradeStep());

    }

}


Step:5

Restart Portal

Step:6

Build and deploy your service bundle. You can manually copy service jar to your OSGI module directory or use CI/CD to build and deploy service bundle to respective environments.

Step:7

You can verify the changes using above mentioned Gogo shell commands. Service should not be in the unsatisfied list. You can also notice your upgrade step process (upgrade:check).
If still see issue you can delete osgi cache and repeat same steps one more time.


We can notice new version is updated in Release_ table for deployed service and it will be created by Dummy Upgrade Step Process.

Note:
If you plan for production portal database upgrade. Identify all modules that you are migrating as Service builder bundles, write SQL script to add records in Release_ table with default version and keep this step as part of post upgrade process.


References:


Author

Saturday, October 21, 2017

Differences between Liferay Module and Liferay Plugin

The objective of this article is providing the major differences between Liferay Module and Liferay Plugin.

Before understand difference we must have basic idea of OSGi and Liferay 7 Fundamentals.
Follow Liferay DXP/7 Tutorial to get more information.




Liferay Modules
Liferay Plugins

Introduced in Liferay 7

Introduced since Liferay Started.
From Liferay 4.x to Liferay 7/DXP


Liferay Modules are based on OSGi framework

Liferay Plugins based traditional Java web application framework. Like we use more J2EE web application Frameworks.


Liferay Module will run in OSGi Run Time Environment.


Liferay Plugins run in Traditional Application Servers such as Tomcat, JBoss , Glassfish


Liferay Module we can call it as OSGi bundles and packaged as JAR file.


Liferay Plugins are web applications and packaged as WAR files.

Liferay Module provides the dynamic component injection with help OSGi so that we can make most of the features as independent components and can easily inject into the other components when it required.


Liferay plugins are like independent web applications we cannot share anything between two web applications. It is more coupled. If we want share some classes we have to put these jar files in some global class loaders then only other web application can use that classes.


We can avoid all the problems of class loader issues.


We can see more class loader issues.

No Class Definition Found, Class Not Found Run time errors completely vanished in the runtime.


We frequently experience No Class Definition Found, Class Not Found Run time errors in the runtime.


Liferay Modules have different types like Portlet Modules, Hook Modules.
Themes and Layouts partially support modularity.


Liferay plugins have different types such as portlets, themes, ext, layout and hooks.

Liferay Modules developed based on OSGi Framework and it used the several framework to develop modules such as Declarative Services (DS), Apache Blueprint and OSGi API.


Liferay Plugins uses the J2EE web application frameworks such as Struts, Spring, Liferay MVC, JSF and other web application frameworks.


Liferay Modules followed 3-tier architecture application development such as Persistence, Service and Presentation layered architecture.


Liferay Plugins uses the same 3-tier architecture application development such as Persistence, Service and Presentation layers architecture.


Usually Liferay Module development we separated each Layer as Independent Modules
Persistence Tier Module
Service Tier Module
Web Tier Module


Liferay Plugins Development all 3 tiers packaged as single WAR file.

Liferay Modules support the dynamic deployment feature and we can stop and start module without un-deploy the module.


Liferay Plugins we must un-deploy the war file from server to remove features.


Liferay Modules uses the Apache Gogo shell Command Line Interface (CLI) to manage the Liferay Modules in the OSGi run time environment. Like stop, start, activate and deactivate.

Liferay Portal Admin screen also have to manage these Liferay modules.


Liferay plugins does not have any Command Line Interface to un-deploy the bundles and we have to removed plugin war files from servers.

Some Enterprise Application Servers have administrative feature to do these things.

Liferay Portal Admin screen also have option to manage these Liferay plugins.



Liferay modules are available in Liferay Portal Server Bundle inside OSGI directory once the module is deployed.


All Liferay Plugins are available in Liferay Portal Server webapps directory.

Liferay Module have important configuration file METAINF which is like module deployment configuration file have more information used by OSGi run time environment.


Liferay Plugins have web.xml file and used by Portlet/Servlet containers.


Liferay portlet module all xml configuration files information turn into Declarative Services (DS) Component properties. Like portlet.xml, liferay-portlet.xml and liferay-display.xml files tags and values.



Liferay Plugins used the XML configuration such as portlet.xml, liferay-portlet.xml and liferay-display.xml

If the Liferay Application have more features then we divided into multiple independent modules and these modules can communicate each other very easy in OSGi environment.


Modularity is not that easy in Liferay Plugins development so we have to keep all the files in single WAR file.

Liferay Module introduced new tool called BLADE CLI to develop Liferay Modules.


Liferay Plugins have Plugins SDK to develop Liferay Applications.


Liferay Modules have several tools such as Liferay IDE, Liferay Studio, BLADE CLI


Liferay Plugins have tools such as Liferay IDE, Liferay Studio.


Liferay Module support GRADLE and MAVEN build environment.


Liferay Plugins support ANT and MAVEN build environment.


Liferay Modules used the Liferay Workspace concept to manage the application and its configuration across the platforms.


Liferay Plugins uses the Plugins SDK to develop and manage the plugins.


Liferay Modules used the OSGi API, Declarative Services and Apache Blueprint framework. So we have limited choice to use popular we application framework like Spring. Liferay still not fully supporting Spring Modules, it means we have to use the WAR deployment.



We can use any J2EE popular web application frameworks such as Spring, Struts and JSF.

Liferay Modules provides the Micro services Architecture based applications.


To bring Micro services Architecture we have to depend on other frameworks such as Spring Micro Services.


Liferay Modules have dynamic component development feature so we can easily turn on and off the feature at any point of time with minimal effort.


Liferay Plugins not like Dynamic Component Development so bunch of feature in one plugin application. If we remove one plugin, it can turn off many features.


Liferay Modules can provide easy way deployment process and we can move easily from one environment to other with minimal effort. Liferay Workspace provided this capability.



Liferay Plugin Deployment process and moving from one environment to other tedious. We do not have any special mechanism like Liferay Workspace.

Liferay Modules uses the Bndtools to develop and build the modules. We have BLADE CLI, Liferay IDE, GRADLE and MAVEN are used the Bndtools internally.



Liferay Plugins follow the J2EE web application development so MAVEN Liferay Plugin or Liferay IDE handle the Development and Deployment.



Author

Recent Posts

Recent Posts Widget

Popular Posts