Connecting Service Builder to an External Database

Service builder creates the necessary tables for the service in the lportal database with all other data used by Liferay. If you want to store the data in a separate database, you can connect service builder to it using a data source provider. This way, the database containing all data from the module can be hosted separately, have different permissions, and much more.

Warning

If your Service Builder services require nested transactions, using an external data source may not be appropriate. Transactions between separate data sources cannot be fully nested. Rollbacks may not propagate between services that use an external data source and Liferay DXP services (or another app’s services) that use a different data source.

Deploy an Example

Start a new Liferay instance by running

docker run -it -m 8g -p 8080:8080 liferay/portal:7.4.3.132-ga132

Sign in to Liferay at http://localhost:8080. Use the email address test@liferay.com and the password test. When prompted, change the password to learn.

Follow these steps to deploy the example:

  1. Manually create a second database for the example module.

  2. Define the data source using portal properties. Distinguish your data source from Liferay’s default data source by giving it a prefix other than jdbc.default.. This example configuration for PostgreSQL uses the prefix jdbc.ext.:

    jdbc.ext.driverClassName=org.postgresql.Driver
    jdbc.ext.url=jdbc:postgresql://localhost:5432/lportal
    jdbc.ext.username=
    jdbc.ext.password=
    
  3. If you’ve defined the data source using portal properties, restart the Liferay Portal instance.

  4. Download and unzip the liferay-y3c4.zip example project.

    curl https://resources.learn.liferay.com/examples/liferay-y3c4.zip -O
    
    unzip liferay-y3c4.zip
    
  5. Build and deploy the project module.

    cd liferay-y3c4
    
    ./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)
    
    Note

    This command is the same as copying the deployed jars to /opt/liferay/osgi/modules on the Docker container.

  6. Confirm the deployment in the Liferay Docker container console.

    STARTED com.liferay.y3c4.web_1.0.0 [1386]
    STARTED com.liferay.y3c4.api_1.0.0 [1384]
    STARTED com.liferay.y3c4.service_1.0.0 [1385]
    
  7. To verify the example module is working, open your database and list the tables.

Creating a Data Source Provider

The easiest way to connect to an external database is to create and register a DataSourceProvider as a JDK ServiceProviderInterface (SPI).

Note

All entities defined in a Service Builder module’s service.xml file are bound to the same data source. Binding different entities to different data sources requires defining the entities in separate Service Builder modules and configuring each of the modules to use a different data source.

  1. Connect your Service Builder module to the data source by implementing the DataSourceProvider interface’s getDataSource() method.
public class DataSourceProviderImpl implements DataSourceProvider {

	@Override
	public DataSource getDataSource() {
Tip

Put the DataSourceProvider in the *-service module since it must be visible to the *-service module class loader.

  1. Use DataSourceFactoryUtil to create a data source from portal properties that have the prefix you chose.
@Override
public DataSource getDataSource() {
	try {
		return DataSourceFactoryUtil.initDataSource(
			PropsUtil.getProperties("jdbc.ext.", true));
	}
	catch (Exception exception) {
		throw new RuntimeException(exception);
	}
}
  1. Inside your *-service module, create a folder named src/main/resources/META-INF/services if it doesn’t already exist.

  2. Inside the services folder, create a file named com.liferay.portal.kernel.dao.jdbc.DataSourceProvider.

  3. Register your data source provider as a JDK ServiceProviderInterface (SPI) by writing its full class name into the com.liferay.portal.kernel.dao.jdbc.DataSourceProvider file:

com.liferay.y3c4.internal.dao.jdbc.DataSourceProviderImpl
  1. When deploying the module, remember to define the data source as was done in step 2 of Deploy an Example.

Congratulations! Your module’s service builder services are persisting data to your external data source.