blog_How to Upgrade Liferay DXP Service Builder Entity

Service Builder is a model-driven code generation tool built by Liferay that allows developers to define custom object models called entities. Service Builder generates a service layer through object-relational mapping (ORM) technology that provides a clean separation between your object model and code for the underlying database. At a brief there are following key steps that we perform,

  • Create a Service builder module

  • Create a Service Builder Entity Like Employee

  • Build Service and Deploy

When we are changing the entities in service.xml and rebuild services, ServiceBuilder will update the SQL files used to create the tables, indices, etc. When you deploy the service the first time, ServiceBuilder will identify the initial deployment and will use the SQL files to create the entities and it will create the table in the database.

blog_How to Upgrade Liferay DXP Service Builder Entity

But there are some cases where we need to update existing service builder entity in service.xml, like adding a new column, changing column type, increasing column length, deleting column. In these cases, we can easily update in service.xml file and build service and deploy. But it will not update the table, for that we need to write an upgrade process for service builder.

Adding New Column

To add new column Like “Address” in existing service builder entity first update the new column name in service.xml and build the service. Create class UpgradeEmployee.java (You can give any name), extend the Liferay Upgrade Process and override doUpgrade method.


public class UpgradeEmployee extends UpgradeProcess {

    private static final Log log = LogFactoryUtil.getLog(UpgradeEmployee.class);

    private static final String EMPLOYEE_NEW_COLUMN_NAME_ADDRESS = "address";

    @Override
    protected void doUpgrade() throws Exception {
        log.info(">>>>>> UPGRADE PROCESS FOR SERVICE BUILDER : START >>>>>>>");

        /**
        * First Parameter Table Name
        * Second Parameter New Column Name
        */
        boolean isAddressColumnExist = hasColumn(EmployeeImpl.TABLE_NAME, EMPLOYEE_NEW_COLUMN_NAME_ADDRESS);
        log.info("is Address Column Exist: " + isAddressColumnExist);
        if (!isAddressColumnExist) {
            String addressColumnType = "STRING";
            alter(EmployeeImpl.class, new AlterTableAddColumn(EMPLOYEE_NEW_COLUMN_NAME_ADDRESS + StringPool.SPACE + addressColumnType));
        }

        log.info(">>>>>> UPGRADE PROCESS FOR SERVICE BUILDER : END >>>>>>>");
    }
}
    

Add below dependency in service module build.gradle file


compileOnly group: 'com.liferay', name: 'com.liferay.portal.upgrade.api'
    

Now Register the UpgradeEmployee using UpgradeStepRegistrator for that create EmployeeServiceUpgrade and implement the Liferay UpgradeStepRegistrator interface.


@Component(
    immediate = true,
    service = UpgradeStepRegistrator.class
)
public class EmployeeServiceUpgrade implements UpgradeStepRegistrator {

    private static final Log log = LogFactoryUtil.getLog(EmployeeServiceUpgrade.class);

    @Override
    public void register(Registry registry) {
        log.info(">>>>>>>>>>> Registering Employee Upgrade >>>>>>>>>>>");
        /*
        * Old Schema Version 1.0.0 which is specified in bnd.bnd
        * New Schema Version 1.0.1
        */
        registry.register("1.0.0", "1.0.1", new UpgradeEmployee());
    }
}
    

Update new Schema version in bnd.bnd file which we have specified in above class


Liferay-Require-SchemaVersion: 1.0.1
    

Now deploy the service, the new column should reflect in your database.

Dropping Existing Column

Remove Column name like “middleName” from service.xml and build the service. Add below code in doUpgrade Method


public class UpgradeEmployee extends UpgradeProcess {

    private static final Log log = LogFactoryUtil.getLog(UpgradeEmployee.class);

    private static final String EMPLOYEE_NEW_COLUMN_NAME_ADDRESS = "address";

    private static final String EMPLOYEE_COLUMN_NAME_MIDDLE_NAME = "middleName";

    @Override
    protected void doUpgrade() throws Exception {
        log.info(">>>>>> UPGRADE PROCESS FOR SERVICE BUILDER : START >>>>>>>");

        /**
        * First Parameter Table Name
        * Second Parameter New Column Name
        */
        boolean isAddressColumnExist = hasColumn(EmployeeImpl.TABLE_NAME, EMPLOYEE_NEW_COLUMN_NAME_ADDRESS);
        log.info("is Address Column Exist : " + isAddressColumnExist);
        if(!isAddressColumnExist) {
            String addressColumnType = "VARCHAR(200)";
            alter(EmployeeImpl.class, new AlterTableAddColumn(EMPLOYEE_NEW_COLUMN_NAME_ADDRESS + StringPool.SPACE + addressColumnType));
        }

        boolean isMiddleNameExist = hasColumn(EmployeeImpl.TABLE_NAME, EMPLOYEE_COLUMN_NAME_MIDDLE_NAME);
        log.info("is Middle Name Column Exist : " + isMiddleNameExist);
        if(isMiddleNameExist) {
            alter(EmployeeImpl.class, new AlterTableDropColumn(EMPLOYEE_COLUMN_NAME_MIDDLE_NAME));
        }

        log.info(">>>>>> UPGRADE PROCESS FOR SERVICE BUILDER : END >>>>>>>");
    }
}
    

Update New Schema Version in bnd.bnd and EmployeeServiceUpgrade class. Note: If you have already created EmployeeServiceUpgrade class then do not create again just update schema version


@Component(
    immediate = true,
    service = UpgradeStepRegistrator.class
)
public class EmployeeServiceUpgrade implements UpgradeStepRegistrator {
    private static final Log log = LogFactoryUtil.getLog(EmployeeServiceUpgrade.class);

    @Override
    public void register(Registry registry) {
        log.info(">>>>>>>>>>> Registering Employee Upgrade >>>>>>>>>>>");
        /*
        * Old Schema Version 1.0.1 which is specified in bnd.bnd
        * New Schema Version 1.0.2
        */
        registry.register("1.0.1", "1.0.2", new UpgradeEmployee());
    }
}
    

Update Liferay-Require-SchemaVersion in bnd.bnd


Liferay-Require-SchemaVersion: 1.0.2
    

Deploy Service Builder Module. Now deploy the service, the existing column should be dropped from your database.

Updating Column Name and Data Size

If you want to change column name “username” to “modifiedBy” with type VARCHAR(100) from VARCHAR(75).

Follow the same step as above and add below code in doUpgrade method


// Change Column Type with Column Name
boolean isUserNameColumnExist = hasColumn(EmployeeImpl.TABLE_NAME, "userName");
log.info("is UserName Column Exist : " + isUserNameColumnExist);
if(isUserNameColumnExist) {
    alter(EmployeeImpl.class, new AlterColumnName("userName","modifiedBy VARCHAR(100)"));
}
    

Similarly update schema version in bnd.bnd as well as EmployeeServiceUpgrade class. Deploy the service. Now deploy the service, the column name and data type update should reflect in your database.

Adding New Entity in Service Builder

Sometime table is not created once service is deployed for that as well, we need to write Upgrade process.

Add new Entity Like “LeaveRequest” in existing service builder. Build Service. Same as above Create class UpgradeEmployee.java extend the Liferay Upgrade Process and override doUpgrade method.


public class UpgradeEmployee extends UpgradeProcess {
    private static final Log log = LogFactoryUtil.getLog(UpgradeEmployee.class);

    @Override
    protected void doUpgrade() throws Exception {
        log.info(">>>>>> UPGRADE PROCESS FOR SERVICE BUILDER : START >>>>>>>");
        boolean isLeaveRequestTableExist = hasTable(LeaveRequestImpl.TABLE_NAME);
        log.info("is Leave Request Table Exist : " + isLeaveRequestTableExist);
        if(!isLeaveRequestTableExist) {


            runSQL(LeaveRequestImpl.TABLE_SQL_CREATE);
        }
        log.info(">>>>>> UPGRADE PROCESS FOR SERVICE BUILDER : END >>>>>>>");
    }
}
    

Now Register the UpgradeEmployee using UpgradeStepRegistrator for that create EmployeeServiceUpgrade and implement the Liferay UpgradeStepRegistrator interface.(Same as above) Note: If you have already created EmployeeServiceUpgrade class then do not create again just update schema version


@Component(
    immediate = true,
    service = UpgradeStepRegistrator.class
)
public class EmployeeServiceUpgrade implements UpgradeStepRegistrator {

    private static final Log log = LogFactoryUtil.getLog(EmployeeServiceUpgrade.class);

    @Override
    public void register(Registry registry) {
        log.info(">>>>>>>>>>> Registering Employee Upgrade >>>>>>>>>>>");
        /*
        * Old Schema Version 1.0.3 which is specified in bnd.bnd
        * New Schema Version 1.0.4
        */
        registry.register("1.0.3", "1.0.4", new UpgradeEmployee());
    }
}
    

Update new Schema version in bnd.bnd file which we have specified in above class


Liferay-Require-SchemaVersion: 1.0.4
    

Deploy the service builder module. Table will be created after deploying. Now deploy the service, the new table schema will be created in your database.