Adding a New Product Data Source for the Product Publisher Widget
This tutorial will show you how to add a new product data source by implementing the CPDataSource
interface.
Product data sources provide unique ways to search for products that are related. Liferay Commerce provides several product data sources out-of-the-box, including ones that search by product relations and by categories.
Overview
Deploy an Example
In this section, we will get an example product data source up and running on your instance of Liferay Commerce.
Start a new Liferay instance by running
docker run -it -m 8g -p 8080:8080 liferay/portal:7.4.3.120-ga120
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.
Then, follow these steps:
-
Download and unzip the Acme Commerce Product Data Source.
curl https://resources.learn.liferay.com/commerce/latest/en/developer-guide/content/liferay-m5x7.zip -O
unzip liferay-m5x7.zip
-
Build and deploy the example.
./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.acme.m5x7.impl_1.0.0
-
Verify that the example product data source was added. Open your browser to
https://localhost:8080
and navigate to a page with a Product Publisher widget. Click Configuration for the Product Publisher, then select Data Source under the Product Selection section. The new product data source (“Products Ending in the Same Word”) will be present under the Data Source dropdown below.
Congratulations, you’ve successfully built and deployed a new product data source that implements CPDataSource
.
Next, let’s dive deeper to learn more.
Walk Through the Example
In this section, we will review the example we deployed. First, we will annotate the class for OSGi registration. Second, we will review the CPDataSource
interface. And third, we will complete our implementation of CPDataSource
.
Annotate Your Class for OSGi Registration
@Component(
property = "commerce.product.data.source.name=m5x7",
service = CPDataSource.class
)
public class M5X7CPDataSource implements CPDataSource {
The product data source name must be a unique value so that Liferay Commerce can distinguish the new data from existing data sources.
Review the CPDataSource
Interface
Implement the following methods:
public String getLabel(Locale locale);
This method returns a text label that describes how product data source will search for related products. See the implementation in M5X7CPDataSource.java for a reference in retrieving the label with a language key.
public String getName();
This returns the name of the product data source.
public CPDataSourceResult getResult(
HttpServletRequest httpServletRequest, int start, int end)
throws Exception;
This will be where we add the business logic to perform the search for related products. The
HttpServletRequest
contains a reference to a particular product which the results should be related to in some way.The method will return a
CPDataSourceResult
, which contains a list of the search results; see the implementation at CPDataSourceResult.java.
Complete the Product Data Source
The product data source is comprised of logic to perform a search for related products. Do the following:
Add the Search Logic to getResult
@Override
public CPDataSourceResult getResult(
HttpServletRequest httpServletRequest, int start, int end)
throws Exception {
CPCatalogEntry cpCatalogEntry =
(CPCatalogEntry)httpServletRequest.getAttribute(
CPWebKeys.CP_CATALOG_ENTRY);
if (cpCatalogEntry == null) {
return new CPDataSourceResult(new ArrayList<>(), 0);
}
return _cpDefinitionHelper.search(
_portal.getScopeGroupId(httpServletRequest),
new SearchContext() {
{
setAttributes(
HashMapBuilder.<String, Serializable>put(
Field.STATUS, WorkflowConstants.STATUS_APPROVED
).put(
"excludedCPDefinitionId",
cpCatalogEntry.getCPDefinitionId()
).build());
setCompanyId(_portal.getCompanyId(httpServletRequest));
setKeywords(
StringPool.STAR + _getLastWordOfName(cpCatalogEntry));
}
},
new CPQuery(), start, end);
}
We use a CPDefinitionHelper to perform the search. The
CPDefinitionHelper
combines logic specific to product definitions withBaseIndexer
’s search functionality; see BaseIndexer.java for more information.Add the product definition’s ID as the value for the
"excludedCPDefinitionId"
attribute to theSearchContext
. This will omit the original product from the results. In our example, we also specify the last word of the product name to search for. For details, see the search logic implementation in the exampleM5X7CPDataSource.java
file’s_getLastWordOfName
method.
Add the Language Key to Language.properties
Add the language key and its value to a Language.properties file within our module:
products-ending-in-the-same-word=Products Ending in the Same Word
See Localizing Your Application for more information.
Conclusion
Congratulations! You now know the basics for implementing the CPDataSource
interface, and have added a new product data source to Liferay Commerce.