Product Data Synchronization Between Solr and SAP Commerce (hybris)
Requirement : The product data in SAP Commerce (Hybris) is always synchronized with the information stored in Solr.
This means that any updates or changes made to product details in Solr are automatically reflected in SAP Commerce(Hybris) Database. It works by:
- Fetching product details (like product code, stock status, EAN, and manufacturer name) from Solr.
- Checking if the product already exists in the SAP Commerce database.
- If the product exists, it updates the existing record.
- If the product does not exist, it creates a new record in the database.
This process ensures that the product information in SAP Commerce remains synchronized with the product data from Solr.
Step 1: Define the Custom Item Type SolrExtractedItemType in /samplecore/resources/samplecore-items.xmlYou need to create a custom item type that will hold the product information fetched from Solr, such as the product code, stock status, EAN, and manufacturer name
<itemtype code="SolrExtractedItemType" autocreate="true" generate="true"> <deployment table="solrextractedtypes" typecode="15800" /> <attributes> <attribute qualifier="productCode" type="java.lang.String"> <description>Product Code</description> <modifiers read="true" write="true" search="true" unique="true" /> <persistence type="property" /> </attribute> <attribute qualifier="inStockFlag" type="java.lang.Boolean"> <description>Stock Flag of the Product</description> <modifiers read="true" write="true" search="true" /> <persistence type="property" /> </attribute> <attribute qualifier="ean" type="java.lang.String"> <description>EAN of the product</description> <modifiers read="true" write="true" search="true" /> <persistence type="property" /> </attribute> <attribute qualifier="manufacturerName" type="java.lang.String"> <description>Name of manufacturer</description> <modifiers read="true" write="true" search="true" /> <persistence type="property" /> </attribute> </attributes> </itemtype>
Step 2: Do ant all command in platform
Step 3: Create a DAO for Fetching Data from Solr
In this step, we will create the SolrProductDataUpdaterDao
interface, which will define the method to fetch an existing SolrExtractedItemTypeModel
based on productCode
.
package com.hybris.sample.core.solr.product.attributes;
import de.hybris.platform.servicelayer.internal.dao.Dao;
import com.hybris.sample.core.model.SolrExtractedItemTypeModel;
public interface SolrProductDataUpdaterDao extends Dao {
SolrExtractedItemTypeModel findExistingSolrExtractedItem(String productCode);
}
DefaultSolrProductDataUpdaterDao
class, which implements the SolrProductDataUpdaterDao
interface and defines the method to fetch an existing SolrExtractedItemTypeModel
based on productCode
.
Location: /samplecore/src/com/hybris/sample/core/solr/product/attributes/DefaultSolrProductDataUpdaterDao.java
package com.hybris.sample.core.solr.product.attributes;
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
import de.hybris.platform.servicelayer.search.FlexibleSearchService;
import de.hybris.platform.servicelayer.search.SearchResult;
import javax.annotation.Resource;
public class DefaultSolrProductDataUpdaterDao implements SolrProductDataUpdaterDao {
private static final String GET_EXISTINGITEMS_BY_PRODUCTCODE =
"SELECT{" + SolrExtractedItemTypeModel.PK + "} FROM {" + SolrExtractedItemTypeModel._TYPECODE + "} WHERE {" + SolrExtractedItemTypeModel.PRODUCTCODE + "} = ?productCode";
@Resource
private FlexibleSearchService flexibleSearchService;
@Override
public SolrExtractedItemTypeModel findExistingSolrExtractedItem(
final String productCode) {
FlexibleSearchQuery query = new FlexibleSearchQuery(GET_EXISTINGITEMS_BY_PRODUCTCODE);
query.addQueryParameter("productCode", productCode);
SearchResult<SolrExtractedItemTypeModel> searchResult = flexibleSearchService.search(query);
return searchResult.getCount() > 0 ? searchResult.getResult().get(0) : null;
}
}
Step 5: Configure the
SolrProductDataUpdaterDao
in samplecore-spring.xml
Location: /samplecore/resources/samplecore-spring.xml
<alias name="defaultSolrProductDataUpdaterDao" alias="productDataUpdater" />
<bean id="defaultSolrProductDataUpdaterDao" class="com.hybris.sample.core.solr.product.attributes.impl.DefaultSolrProductDataUpdaterDao" />
Step 6: Create the Solr Data Fetching Job
Location:/samplecore/src/com/hybris/sample/core/job/SolrProductDataUpdaterJob.java
package com.hybris.sample.core.job;
import de.hybris.platform.cronjob.enums.CronJobResult;
import de.hybris.platform.cronjob.enums.CronJobStatus;
import de.hybris.platform.cronjob.model.CronJobModel;
import de.hybris.platform.servicelayer.cronjob.AbstractJobPerformable;
import de.hybris.platform.servicelayer.cronjob.PerformResult;
import de.hybris.platform.servicelayer.model.ModelService;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import javax.annotation.Resource;
import javax.net.ssl.SSLContext;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.ssl.SSLContexts;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import com.hybris.sample.core.model.SolrExtractedItemTypeModel;
import com.hybris.sample.core.solr.product.attributes.SolrProductDataUpdaterDao;
public class SolrProductDataUpdaterJob extends AbstractJobPerformable<CronJobModel>
{
// Solr query constants
private static final String SOLR_QUERY = "*:*";
private static final String SOLR_URL = "https://localhost:8983/solr/master_electronics_Product_default";
private static final String SOLR_USERNAME = "solradmin";
private static final String SOLR_PASSWORD = "admin123";
@Resource
private SolrProductDataUpdaterDao productDataUpdaterDao;
@Resource
private ModelService modelService;
private SolrClient solrClient;
@Override
public PerformResult perform(final CronJobModel job)
{
try
{
// Initialize the HttpClient for Solr connection
solrClient = new HttpSolrClient.Builder(SOLR_URL).withHttpClient(createHttpClient(SOLR_USERNAME, SOLR_PASSWORD)).build();
}
catch (final Exception e)
{
e.printStackTrace();
return new PerformResult(CronJobResult.FAILURE, CronJobStatus.FINISHED);
}
final SolrQuery solrQuery = new SolrQuery();
solrQuery.setQuery(SOLR_QUERY);
solrQuery.setFilterQueries("catalogVersion:Online");
solrQuery.addField("code_string");
solrQuery.addField("inStockFlag_boolean");
solrQuery.addField("ean_string");
solrQuery.addField("manufacturerName_text");
int start = 0;
final int pageSize = 100;
while (true)
{
solrQuery.setStart(start);
solrQuery.setRows(pageSize);
QueryResponse response = null;
try
{
response = solrClient.query(solrQuery);
}
catch (final Exception e)
{
e.printStackTrace();
return new PerformResult(CronJobResult.FAILURE, CronJobStatus.FINISHED);
}
final SolrDocumentList results = response.getResults();
if (!results.isEmpty())
{
for (final SolrDocument document : results)
{
final String productCode = document.getFieldValue("code_string").toString();
final SolrExtractedItemTypeModel existingItem = productDataUpdaterDao.findExistingSolrExtractedItem(productCode);
if (existingItem != null)
{
existingItem.setInStockFlag((Boolean) document.getFieldValue("inStockFlag_boolean"));
existingItem.setEan((String) document.getFieldValue("ean_string"));
existingItem.setManufacturerName((String) document.getFieldValue("manufacturerName_text"));
modelService.save(existingItem);
}
else
{
final SolrExtractedItemTypeModel solrExtractedItemTypeModel = modelService.create(SolrExtractedItemTypeModel.class);
solrExtractedItemTypeModel.setProductCode(productCode);
solrExtractedItemTypeModel.setInStockFlag((Boolean) document.getFieldValue("inStockFlag_boolean"));
solrExtractedItemTypeModel.setEan((String) document.getFieldValue("ean_string"));
solrExtractedItemTypeModel.setManufacturerName((String) document.getFieldValue("manufacturerName_text"));
modelService.save(solrExtractedItemTypeModel);
}
}
}
// Check if there are fewer results than page size, if so, stop
if (results.size() < pageSize)
{
break;
}
start += pageSize;
}
// Return successful job completion
return new PerformResult(CronJobResult.SUCCESS, CronJobStatus.FINISHED);
}
// Creates a HttpClient with SSL and HTTP Basic Authentication for Solr.
private HttpClient createHttpClient(final String solrUsername, final String solrPassword)
throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException
{
final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(new TrustStrategy()
{
@Override
public boolean isTrusted(final java.security.cert.X509Certificate[] chain, final String authType)
{
return true;
}
}).build();
final BasicCredentialsProvider provider = new BasicCredentialsProvider();
final UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(solrUsername, solrPassword);
provider.setCredentials(AuthScope.ANY, credentials);
return HttpClientBuilder.create().setSSLContext(sslContext).setDefaultCredentialsProvider(provider).build();
}
}
Step 7: Create Spring Bean for the Job
Location:/samplecore/resources/samplecore-spring.xml
<bean id="solrProductDataUpdaterJob"class="com.hybris.sample.core.job.SolrProductDataUpdaterJob"/>
Step 8: Do ant all command in platform,make server up after that update hac by just selecting samplecore extension (check only Update running system)
Step 9: Run ServicelayerJob and CronJob Impexes in Hac
INSERT_UPDATE ServicelayerJob ; code[unique=true] ; springId ; solrProductDataUpdaterJob ; solrProductDataUpdaterJob
INSERT_UPDATE CronJob ; code[unique=true] ; job(code) ; sessionLanguage(isocode) ; sessionCurrency(isocode) ; solrProductDataUpdaterCronJob ; solrProductDataUpdaterJob ; en ; EUR
Step 10: First let see how we are retrieving product information from solr
Open Solr Admin: Im passing catalogVersion:"Online" in FilterQuery and code_string,inStockFlag_boolean,ean_string,manufacturerName_text in FilterList ,here we can see total no of doc count is 185 Step 10: Open Backoffice and run Cronjob ,Check the type SolrExtractedItemType
Comments