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.
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:
-
Manually create a second database for the example module.
-
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 prefixjdbc.ext.
:jdbc.ext.driverClassName=org.postgresql.Driver jdbc.ext.url=jdbc:postgresql://localhost:5432/lportal jdbc.ext.username= jdbc.ext.password=
-
If you’ve defined the data source using portal properties, restart the Liferay Portal instance.
-
Download and unzip the
liferay-y3c4.zip
example project.curl https://resources.learn.liferay.com/examples/liferay-y3c4.zip -O
unzip liferay-y3c4.zip
-
Build and deploy the project module.
cd liferay-y3c4
./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)
NoteThis command is the same as copying the deployed jars to
/opt/liferay/osgi/modules
on the Docker container. -
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]
-
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).
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.
- Connect your Service Builder module to the data source by implementing the
DataSourceProvider
interface’sgetDataSource()
method.
public class DataSourceProviderImpl implements DataSourceProvider {
@Override
public DataSource getDataSource() {
Put the DataSourceProvider
in the *-service
module since it must be visible to the *-service
module class loader.
- 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);
}
}
-
Inside your
*-service
module, create a folder namedsrc/main/resources/META-INF/services
if it doesn’t already exist. -
Inside the
services
folder, create a file namedcom.liferay.portal.kernel.dao.jdbc.DataSourceProvider
. -
Register your data source provider as a JDK
ServiceProviderInterface
(SPI) by writing its full class name into thecom.liferay.portal.kernel.dao.jdbc.DataSourceProvider
file:
com.liferay.y3c4.internal.dao.jdbc.DataSourceProviderImpl
- 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.