
Migrating WebSphere Commerce search customization assets
You can migrate WebSphere Commerce search customization assets to the REST-based search architecture. This topic provides a high-level overview of the assets you must change, and the steps required for updating several of the WebSphere Commerce search extension points.
There are key architectural differences between the search components under the WebSphere Commerce server, and under the WebSphere Commerce search server.
- Its architecture is based on the BOD programming model, using predefined nouns such as the CatalogEntry noun.
- It contains other architectures such as SOA, SOI, EJBs, EMFs, and SDOs.
- Its architecture is based on the REST programming model, using native Java objects.
- The storefront uses getData tags to call WebSphere Commerce services that return BOD-structured data. RESTful APIs are used to call the WebSphere Commerce search server services that return simpler name-value formatted data.
The migration effort and complexity varies depending on which component is customized, and the dependency levels of the customized assets on WebSphere Commerce resources.
Topic overview
This topic contains several sections of interest that are related to migrating WebSphere Commerce search customization assets.
Custom index fields and indexing scripts
Any customization made to any of the index schemas, or to the preprocessing and indexing scripts can be reapplied. The search index schema and indexing scripts are shared between the WebSphere Commerce server and the WebSphere Commerce search server, and are therefore compatible with no additional changes required.
Custom configuration files
Registering custom search profiles defined in the wc-search.xml file
Any custom search profile defined in the WebSphere Commerce server must be redefined in the WebSphere Commerce search server extension directory.
Any custom search profile which extends a default search profile in the WebSphere Commerce server must be updated, as new default search profiles are introduced in the search server that contain different names or naming conventions.
Any custom search profile that uses any of the default search query providers, processors, and search result filters must be updated, as new alternatives are introduced in the search server that contain different names or naming conventions.
- Locate the Search-Rest\WEB-INF\config\com.ibm.commerce.rest\wc-rest-resourceconfig.xml file.
- Identify which REST service the custom search profile should be listed under.
- Append your custom search profile to the end of the defined list of search profiles.
For more information about the search profiles mappings, see Mapping between WebSphere Commerce search profiles.
For more information about the search configuration properties in the wc-search.xml file, see WebSphere Commerce search configuration file (wc-search.xml) (Search EAR).
Custom configurations made in the wc-component.xml file
Most of the search-related custom properties defined in the wc-component.xml file can be reused in the search server, with the exception of the global price mode property. The price mode configuration is instead performed using the STORECONF table.
For more information about the search configuration properties in the STORECONF table, see Search configuration properties in the STORECONF table.
For more information about the search configuration properties in the wc-component.xml file, see Search properties in the component configuration file (wc-component.xml) (Search EAR).
Custom object mediators made in the wc-business-object-mediator.xml file
The search server does not support business object mediators. Therefore, any customizations performed under the wc-business-object-mediator.xml file must be moved to the wc-component.xml file. For example, mappings between a userData custom field to an internal index field or database field must instead use the correct mappings under the wc-component.xml file.
<_config:mediator-property name="CatalogEntryView/UserData[(Name='SKU')]" value="partNumber_ntk" />
valuemappingservice
defined
in the wc-component.xml file. There are different
maps for CatalogEntry UserData and CatalogGroup UserData. The corresponding
mapping in the search server wc-component.xml file
can be achieved as:
<_config:valuemapping externalName="CatalogEntryUserDataFieldNameMapping" internalName="CatalogEntryUserDataFieldNameMapping">
<_config:valuemap externalValue="SKU" internalValue="partNumber_ntk" />
</_config:valuemapping>
<_config:valuemapping externalName="CatalogGroupUserDataFieldNameMapping" internalName="CatalogGroupUserDataFieldNameMapping">
</_config:valuemapping>
<_config:postprocessor classname="com.ibm.commerce.foundation.server.services.rest.search.postprocessor.solr.SolrRESTSearchCatalogEntryViewUserDataQueryPostprocessor" />
<_config:postprocessor classname="com.ibm.commerce.foundation.server.services.rest.search.postprocessor.solr.SolrRESTSearchCatalogGroupViewUserDataQueryPostprocessor" />
Custom database query template (.tpl) files
The search server supports DSL. However, it does not support EMFs, SDOs and logical schemas. Therefore, any retrieved data from the database must be parsed by custom code and added into the main response as applicable. Any search related custom queries can be reused in the search server. For more information, see Creating a custom query postprocessor.
BEGIN_SQL_STATEMENT
name=X_GET_CUSTOM_FIELD_QUERY
base_table=tableName
sql=SELECT *
FROM tableName
WHERE CATALOG_ID=?catalogId? AND LANGUAGE_ID=?languageId? AND STOREENT_ID=?storeentId?
END_SQL_STATEMENT
BEGIN_SQL_STATEMENT
name=X_GET_CUSTOM_FIELD_QUERY_WORKSPACE
base_table=tableName
sql=SELECT *
FROM $SCHEMA$.tableName
WHERE CATALOG_ID=?catalogId? AND LANGUAGE_ID=?languageId? AND STOREENT_ID=?storeentId?
END_SQL_STATEMENT
queryParameters.put("languageId", Arrays.asList("-1"));
queryParameters.put("catalogId", Arrays.asList("10001"));
queryParameters.put("storeentId", Arrays.asList("10051"));
String readSchema = SolrSearchConfigurationRegistry.getInstance(
"com.ibm.commerce.catalog").getReadSchema();
if (readSchema != null && readSchema.length() > 0) {
queryParameters.put("$SCHEMA$",Arrays.asList(readSchema));
results = service.executeQuery("X_GET_CUSTOM_FIELD_QUERY_WORKSPACE", queryParameters);
} else {
results = service.executeQuery("X_GET_CUSTOM_FIELD_QUERY", queryParameters);
}
Custom Java classes
Custom expression providers
Most custom expression providers can be reused without any changes in the search server, as the search server supports Selection Criteria objects and control parameters.
Custom processors
All
custom search query preprocessors can be reused in the search server,
as search query preprocessors operate on the native physical SolrQuery
object
defined in the AbstractSolrSearchQueryPreprocessor
parent
class that all preprocessors extend from, which is also available
in the search server.
Search query result postprocessors might
require re-implementation. If your custom code operates on the native QueryResponse
object,
the custom code is reusable. However, if the custom postprocessor
operates on the SolrCatalogNavigationViewImpl
, it
cannot be use reused.
SearchResponse
. The following snippet
is an example on how to use the SearchResponse
:
List<Map<String, Object>> catalogEntryViews = (LinkedList<Map<String, Object>>)iSearchResponseObject.getResponse().get("external object name");
Where the object name is the external object name. Refer
to the sample custom postprocessors in the wc-search.xml file
for samples on resolving external names.Custom search query result filters
Custom result filters operate on the
logical CatalogNavigationViewType
noun. This logical
noun is not supported in the search server. All custom result filters
must be re-implemented using search query postprocessors instead.
The
main key difference in result filters is that the catalogEntryViewList
was
a list of CatalogEntryViewType
objects, but in the
search query postprocessor, it is a list of Map
.
CatalogNavigationViewType catalogNavigationView = (CatalogNavigationViewType) dataObject;
List<CatalogEntryViewType> catalogEntryViewList = catalogNavigationView
.getCatalogEntryView();
The following is an alternative code on a search query
postprocessor:
List<Map<String, Object>> catalogEntryViews = (LinkedList<Map<String, Object>>)iSearchResponseObject.getResponse().get("external object name");
Where the external object name is the external object
name of the catalogEntryView
.Business Object Mediators
Similar
to search query result filters, mediators also operate on the logical CatalogNavigationViewType
noun.
Mediators are not supported in the search server. An alternative is
search query postprocessors, as they are used instead. All custom
mediators that extend the AbstractReadBusinessObjectPartMediatorImpl
parent
class must be re-implemented using search query postprocessors instead.
Storefront services and response data format
Any custom storefront
pages that use any of the search related CatalogNavigationView
BOD
services must be updated to use the corresponding new search server
REST services.
<wcf:getData type="com.ibm.commerce.catalog.facade.datatypes.CatalogNavigationViewType" var="catalogNavigationView"
expressionBuilder="getCatalogEntryViewDetailsByID" scope="request" varShowVerb="showCatalogNavigationView"
maxItems="100" recordSetStartNumber="0" scope="request">
<c:forEach var="marketingSpotData" items="${marketingSpotDatas.baseMarketingSpotActivityData}">
<c:if test='${marketingSpotData.dataType eq "CatalogEntryId"}'>
<wcf:param name="UniqueID" value="${marketingSpotData.uniqueID}"/>
</c:if>
</c:forEach>
<wcf:contextData name="storeId" data="${storeId}" />
<wcf:contextData name="catalogId" data="${catalogId}" />
<wcf:param name="searchProfile" value="IBM_findCatalogEntryDetails_PriceMode"/>
</wcf:getData>
<c:set var="eSpotCatalogIdResults" value="${catalogNavigationView.catalogEntryView}"/>
<wcf:rest var="catalogNavigationView" url="${searchHostNamePath}${searchContextPath}/store/${WCParam.storeId}/productview/byIds" >
<c:forEach var="id" items="${catentryIdQueryList}">
<wcf:param name="id" value="${id}"/>
</c:forEach>
<wcf:param name="langId" value="${langId}" />
<wcf:param name="currency" value="${env_currencyCode}" />
<wcf:param name="responseFormat" value="json" />
<wcf:param name="catalogId" value="${WCParam.catalogId}" />
<wcf:param name="profileName" value="IBM_findProductByIds_Summary" />
</wcf:rest>
<c:set var="eSpotCatalogIdResults" value="${catalogNavigationView.catalogEntryView}"/>
The response data is being formatted in a BOD-like dot notation response to minimize the changes required in the storefront. In some cases, the response has been simplified and flattened to simpler name-value pairs, rather than using internal maps to group certain fields.
<wcf:json object="${catalogNavigationView}"/>
HTTPRequester
or an equivalent
client to validate you custom code:
http://localhost/search/resources/store/10152/productview/byId/10001?langId=-1&catalogId=10001¤cy=USD&responseFormat=json&pageSize=12&pageNumber=1
For more information about the BOD to REST services mappings, see Mapping between WebSphere Commerce search BOD services and REST services.
For more information about the WebSphere Commerce REST API for WebSphere Commerce search, see the complete list of supported query parameters for the following search services: CategoryViewHandler, ProductViewHandler, and SiteContentHandler.