Create the JSP files, user interface provider files, and data provider files
for your Commerce Composer widget. These storefront assets define the appearance and content of your
widget.
Procedure
Part A: Move the generated source code files for the storefront assets of your widget
into a code package within the default HCL Commerce Developer workspace file
structure.
-
In the Enterprise Explorer view, create a directory to contain the code packages for custom
widgets.
Within this directory, create the code package that is to contain all of the assets for
your custom widget that are not shared among multiple widgets. If your site has multiple custom
widgets, ensure that the assets for each custom widget are in separate code packages.
The code
packages that define the default site-level widgets are in the following directory:
- workspace_dir\crs-web\WebContent\widgetdir
The JSP files and JSP fragments that are shared between multiple widgets are stored in the
Common directory within the
widgetdir
directory.
If you are creating a custom site-level widget, create the following directory, if
the directory does not exist:
- workspace_dir\crs-web\WebContent\Widgets-vendor
If you are creating a custom store-level widget, create a store-specific directory that
contains the
Widgets-vendor directory, if the directory does
not exist:
- workspace_dir\crs-web\WebContent\store\Widgets-vendor
Where
store is the name of your store directory, for example
aurora.
If your custom widget has assets that are common across multiple
widgets, but the assets are not already included in the default Widgets\Common
directory, include these assets in a Common directory in the
Widgets-vendor directory. If this
Common directory, does not exist, you must create the directory.
-
Copy the generated source code files for your widget storefront assets from the target folder
into the default HCL Commerce Developer workspace file structure.
-
Go to the project where the JET Transformation generated the source code files in the previous
task. Copy the following file structure and files that are within the target folder:
- target_folder\crs-web\WebContent\Widgets-vendor\Common
- target_folder\crs-web\WebContent\Widgets-vendor\images
- target_folder\crs-web\WebContent\Widgets-vendor\Properties
- target_folder\crs-web\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier\javascript
- target_folder\crs-web\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier\identifier.jsp
- target_folder\crs-web\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier\identifier_Data.jspf
- target_folder\crs-web\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier\identifier_UI.jspf
- target_folder\crs-web\WebContent\Widgets-vendor\Properties\MyWidgetText_en_US.properties
- target_folder\crs-web\WebContent\Widgets-vendor\Properties\MyWidgetText.properties
Where
- vendor
- The value for the
vendor
parameter within the pattern input XML file.
- identifier
- The value for the
identifier
parameter within the pattern input XML file.
- target_folder
- The folder or project that you specified as the value for the
targetFolder
parameter in the pattern input XML file. If you did not specify a value for the
targetFolder
parameter, the target_folder is the folder or
project where the pattern input XML file is located.
-
Merge the copied files and file structure into the default HCL Commerce Developer
workspace file structure. Do not overwrite any files or folders.
If you are creating a store level widget, add the Widgets-vendor
directory and the contents of the directory into your
crs-web\WebContent\store directory. Where
store is the name of your store directory.
Part B: Modify the generated source code files to complete the definition of the
storefront assets for your custom widget.
-
Complete the entry point top-level JSP file for your custom widget.
This JSP file identifies the environment setup file, the data provider, and the UI provider to
import for rendering the widget. If your widget requires multiple UI providers, the top-level JSP
file includes the code that specifies the conditions when each UI provider is used to render the
widget.
The file path to this top-level JSP file must be registered with the widget identifier in
the Commerce Composer framework. The top-level JSP file is imported into Commerce Composer layouts
when a widget is assigned to a layout. When a layout that includes the widget is assigned to a store
page, the top-level JSP file is used to call the components to provide the widget
function.
-
Go to the following merged directory:
- For site-level widgets -
crs-web\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
- For store-level widgets -
crs-web\WebContent\store\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
-
Open the identifier.jsp file for editing.
By default, the generated source code file includes the following code to help you
define the top-level JSP file for your widget:
<%-- The following code is created as an example. Modify the generated code and add any additional required code. --%>
<%-- BEGIN identifier.jsp --%>
1
<%@include file="/Widgets/Common/EnvironmentSetup.jspf"%>
2
<fmt:setBundle basename="/Widgets-vendor/Properties/mywidgettext" var="mywidgettext" />
<c:set var="widgetPreviewText" value="${mywidgettext}"/>
<c:set var="emptyWidget" value="false"/>
3
<%@include file="identifier_Data.jspf"%>
4
<c:if test="${env_inPreview && !env_storePreviewLink}">
<jsp:useBean id="previewWidgetProperties" class="java.util.LinkedHashMap" scope="page" />
<c:set target="${previewWidgetProperties}" property="name" value="${param.name}" />
<c:set target="${previewWidgetProperties}" property="name" value="${param.name}" />
</c:if>
5
<%@ include file="/Widgets/Common/StorePreviewShowInfo_Start.jspf" %>
6
<%@ include file="identifier_UI.jspf"%>
5
<%@ include file="/Widgets/Common/StorePreviewShowInfo_End.jspf" %>
<%-- END identifier.jsp --%>
- 1 The environment setup file. This configuration file is used at
run time. This file retrieves and prepares the JSP page path, file path, and resource bundle for the
widget. This file is called by many JSP files in a store and is shared by multiple widgets. By
default, the /Widgets/Common/EnvironmentSetup.jspf file is specified.
- 2 The property resource bundle for your widget. A properties file
is a resource bundle that contains the translatable text for display in the widget. By default, the
generated \Widgets-vendor\Properties\MyWidgetText.properties
file is specified.
- 3 Identifies the data provider to use for retrieving content for
use in the widget. The generated identifier_Data.jspf data
provider is set by default.
- 4 The conditional statement determine whether the widget is being
viewed in store preview. If the widget is being viewed in store preview, this code adds the logic to
ensure that the widget properties are used to render the widget during store preview. The
name field identifies the configurable property.
- 5 The StorePreviewShowInfo_Start.jspf and
StorePreviewShowInfo_End.jspf files add support for showing information about
the widget when the widget is being viewed in store preview. The include statements for these files
must enclose the include statement and logic that define the display information for the
widget.
- 6 Identifies the UI provider to use for rendering the widget on a
store page. The generated identifier_UI.jspf UI provider is
set by default.
Modify the generated top-level JSP file. Change any of the default settings or specify
more properties to meet the requirements for your custom widget.
- Optional:
If your widget requires multiple UI providers, include conditional statements to define the
conditions when each UI provider is to be used.
You can define configurable properties to allow
Management Center users to select the
rendering style. Use the values for the configurable properties as the conditions within the
conditional statements. For example, the following code sets the conditions for when each UI
provider is to be used to render the Catalog Entry Recommendation widget.
1
<c:if test="${!empty catentryIdList}">
<c:choose>
2
<c:when test="${param.widgetOrientation eq 'vertical'}">
<%@include file="CatalogEntryRecommendation_Vertical_UI.jspf"%>
</c:when>
3
<c:otherwise>
<%@include file="CatalogEntryRecommendation_Horizontal_UI.jspf"%>
</c:otherwise>
</c:choose>
</c:if>
The
CatalogEntryRecommendation.jsp top-level JSP file specifies that the catalog
entry recommendation widget can be rendered differently depending on which UI provider is used to
render the widget.
- 1 Conditional statement to check that a custom view is not set for
the widget and that there are recommendations to retrieve for display within the widget. If the
condition is met, then the top-level JSP file uses the conditional statements to check to select the
appropriate UI provider to render the widget.
- 2 Conditional statement to test whether the widget orientation
parameter is set to
'vertical'
. If the value is set to 'vertical'
,
the CatalogEntryRecommendation_Vertical_UI.jspf is used to render the widget.
Business users can set the value for the widget orientation parameter in Management Center.
- 3 If the widget orientation parameter is not set to
'vertical'
, the CatalogEntryRecommendation_Horizontal_UI.jspf
is used to render the widget.
If no list of catalog entries is specified, the retrieved recommendations are rendered with the
CatalogEntryRecommendation_Horizontal_UI.jspf UI provider. If a list of catalog
entries are specified to display in the widget, the recommendations can be rendered with the
CatalogEntryRecommendation_Vertical_UI.jspf or the
CatalogEntryRecommendation_Horizontal_UI.jspf UI provider.
- Optional:
If you define any properties for your widget, define a
previewWidgetProperties
map to display the properties in the Widget Information window for your widget
in store preview.
Use the following format to define the
previewWidgetProperties
map:
<c:if test="${env_inPreview && !env_storePreviewLink}">
<jsp:useBean id="previewWidgetProperties" class="java.util.LinkedHashMap" scope="page" />
<c:set target="${previewWidgetProperties}" property="name" value="${param.name}" />
<c:set target="${previewWidgetProperties}" property="name" value="${param.name}" />
</c:if>
Where
name
- The name of the property for your custom widget. For example,
widgetOrientation
. This property name corresponds to a key in the properties
resource bundle. If the key is not found, the provided name displays in the Widget
Information window.
value
- The value for each property can correspond to a key in the properties resource bundle with the
format
name_value
. If the key is not found in the properties resource bundle, the
provided value displays in the Widget Information window.
Ensure that you include the corresponding properties within the properties resource bundle
when you are
adding Management Center support for your
widget.
- Optional:
If your custom widget must use data that is generated by a different widget, you can use a
wcTopic event to retrieve the information for your custom widget.
- Optional:
If your custom widget must generate data for other widgets to use, you can use a wcTopic event
to publish the data.
-
Save the file.
As an example of a top-level JSP file, the following code defines the top-level JSP file,
Heading.jsp, for the Heading
widget:
<!-- BEGIN Heading.jsp -->
<%@ include file="/Widgets/Common/EnvironmentSetup.jspf" %>
<c:set var="emptyWidget" value="false"/>
<%@include file="Heading_Data.jspf"%>
<%@ include file="/Widgets/Common/StorePreviewShowInfo_Start.jspf" %>
<%@include file="Heading_UI.jspf"%>
<%@ include file="/Widgets/Common/StorePreviewShowInfo_End.jspf" %>
<wcpgl:pageLayoutWidgetCache/>
<!-- END Heading.jsp -->
Note: The
preceding top-level JSP file for the Heading widget, includes the code
<wcpgl:pageLayoutWidgetCache/>
, This tag is used for caching the widget. For
more information about widget caching, see
Commerce Composer widget caching and invalidation.
For an example of a top-level JSP file for a widget that uses marketing activities, see
the Content Recommendation widget top-level JSP file
- crs-web\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation.jsp
-
Define the data provider JSP fragment for your custom widget.
The top-level JSP file calls the data provider file to retrieve the data that is needed to
render the widget. A widget can have only one data provider, which is modeled as an independent JSP
page.
-
Go to the following merged directory:
- For site-level widget -
crs-web\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
- For store-level widgets -
crs-web\WebContent\store\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
-
Open the identifier_Data.jspf file for editing.
By default, the generated source code file is empty. Add the code to define the data that
is to be retrieved for your custom widget. If your custom widget uses the same data as an existing
widget, use the data provider file for the existing widget to help you define the file for your
custom widget.
To locate the data provider file for an existing widget go to the
crs-web\WebContent\widgetdir directory. Expand the directory
and the code package for an existing widget. Open the
identifier_Data.jspf for the existing widget.
If you are converting an existing store JSP file to be a widget, use the contents of your JSP
file to help you define the data provider information for the widget. Review your JSP and identify
the code that is related to data. Modify and include this data-related code into the data provider
file for your widget. If the JSP file that you are converting has include or import statements, move
the referenced JSP files into the
crs-web\WebContent\Widgets-vendor\Common directory. Update
the references in your data provider file to reference the new file paths.
-
Save the file.
As an example of a data provider JSP fragment, the following code defines the data provider
file,
Heading_Data.jspf, for the Heading
widget:
<%-- BEGIN Heading_Data.jsp --%>
<%-- Try to get product description --%>
<c:set var="productId" value="${param.productId}" />
<c:if test="${empty productId}">
<c:set var="productId" value="${WCParam.productId}" />
</c:if>
<c:choose>
<c:when test="${!empty productId}">
<%-- Try to get it from our internal hashMap --%>
<c:set var="key1" value="${productId}+getCatalogEntryViewAllByID"/>
<c:set var="catalogEntryDetails" value="${cachedCatalogEntryDetailsMap[key1]}"/>
<c:if test="${empty catalogEntryDetails}">
<wcf:rest var="catalogNavigationView"
url="${searchHostNamePath}${searchContextPath}/store/${WCParam.storeId}/productview/byId/${productId}" >
<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:rest>
<c:set var="catalogEntryDetails" value="${catalogNavigationView.catalogEntryView[0]}"/>
</c:if>
<c:if test="${!empty catalogEntryDetails}">
<c:set var="productName" value="${catalogEntryDetails.name}" />
<c:set var="catalogEntryID" value="${catalogEntryDetails.uniqueID}" />
</c:if>
</c:when>
<c:otherwise>
<%-- Try to get category name --%>
<c:set var="categoryId" value="${param.categoryId}" />
<c:if test="${empty categoryId}">
<c:set var="categoryId" value="${WCParam.categoryId}" />
</c:if>
<c:if test="${!empty categoryId}">
<wcf:rest var="catGroupDetailsView"
url="${searchHostNamePath}${searchContextPath}/store/${WCParam.storeId}/categoryview/byId/${categoryId}" >
<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:rest>
</c:if>
<c:if test="${!empty catGroupDetailsView}">
<c:set var="categoryName" value="${catGroupDetailsView.catalogGroupView[0].name}"/>
</c:if>
</c:otherwise>
</c:choose>
<c:if test="${empty productId && empty categoryId}">
<c:set var="emptyWidget" value="true" />
</c:if>
<c:set var="widgetSuffix" value="" />
<c:if test="${(!empty param.pgl_widgetSlotId) && (!empty param.pgl_widgetDefId) && (!empty param.pgl_widgetId)}">
<c:set var="widgetSuffix" value="_${param.pgl_widgetSlotId}_${param.pgl_widgetDefId}_${param.pgl_widgetId}" />
</c:if>
<%-- END Heading_Data.jsp --%>
For
an example of a data provider file for a widget that uses marketing activities, see the Content
Recommendation widget data provider JSP fragment:
- crs-web\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation_Data.jspf
-
Define the UI provider JSP fragment for your custom widget.
Each way that your custom widget can be rendered must be defined in a UI provider file. For
example, if your custom widget can be rendered with both a horizontal and vertical orientation, you
must define two UI provider files. Ensure that logic that defines the UI provider is included within
the top-level JSP file.
-
Go to the following merged directory:
- For site-level widgets -
crs-web\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
- For store-level widgets -
crs-web\WebContent\store\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
-
Open the identifier_UI.jspf file for editing.
By default, the generated source code file includes the following code to help you define
the UI provider file for your widget:
<%-- Add your UI code here, see example below --%>
1
<div id="widgetExample" >
<ul style="list-style: none; font-size: 24px">
<li>${param.name}</li>
</ul>
</div>
- 1 Example to demonstrate how to structure your UI provider JSP
fragment.
-
Modify the generated UI provider JSP fragment.
Identify the different divisions,
<div/>
, that must be defined to render
your widget. Add code to define how each division can be rendered. Ensure that you include the
rendering effects as JSP import parameters in your code. By including the effects as parameters,
Management Center users can specify which rendering effects are to be used to render the
widget on the storefront.
If you are converting an existing store JSP file to be a widget, use the
contents of your JSP file to define the UI provider information for the widget. Review your JSP file
and identify the code that is related to rendering the JSP file. Modify and include the code that is
related to rendering the JSP file within the UI provider file for your widget. If the JSP file that
you are converting has include statements, move the referenced JSP files into the
crs-web\WebContent\Widgets-vendor\Common directory. Update
the references in your data provider file to reference the new file paths.
-
Save the file.
As an example of a UI provider JSP fragment, the following code defines the
Heading_UI.jspf UI provider file for the Heading
widget:
<%-- BEGIN Heading_UI.jsp --%>
<div id="PageHeading<c:out value="${widgetSuffix}"/>" >
<h1>
<c:choose>
<c:when test="${!empty categoryName}">${categoryName}</c:when>
<c:when test="${!empty productName}">${productName}</c:when>
</c:choose>
</h1>
</div>
<%-- END Heading_UI.jsp --%>
For
an example of a UI provider file for a widget that uses marketing activities, see the Content
Recommendation widget UI provider JSP fragments. The Content Recommendation widget uses four UI
provider JSP fragments to define all of the ways that the widget can be rendered.
- crs-web\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation_UI.jspf
- crs-web\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation_Email_UI.jspf
- crs-web\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation_URLLink_UI.jspf
- crs-web\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation_Vertical_UI.jspf
-
Define the translatable text that is to display in the storefront for your custom widget.
-
Go to the crs-web\WebContent\Widgets-vendor\Properties
directory.
-
Open the generated MyWidgetText.properties for editing. By default, the
file includes the following property:
WidgetTypeDisplayText_identifier=displayName
-
Add the translatable text for your widget into the file.
-
Save your file.
-
Repeat the preceding steps to edit the MyWidgetText_en_US.properties file
to add translatable text for the United States English language.
- Optional:
Add the language sensitive text for your widget in the other languages that your store
supports. Create the properties files for your additional languages with the naming convention
MyWidgetText_language.properties
Include all of the assets that are not shared between multiple widgets in the code
package for your widget. This includes any JSP, JavaScript, and CSS files.
-
Create or move the CSS files for your widget.
If your widget uses an existing CSS file, ensure that the file is in the appropriate directory
for your store. For more information about the file structure of CSS files for Commerce Composer
widgets, see
Responsive Aurora starter store file structure.
If you must
create a CSS file for your widget, consider defining the CSS to follow responsive web design
practices. For more information about defining CSS to make a widget responsive, see Creating responsive widgets.
- Optional:
If an image is required by your custom widget for display in the storefront, include the image
within the crs-web\WebContent\Widgets-vendor\images
directory.
- Optional:
Create any JavaScript functions that are required for your custom widget.
For example, adding support to add products to the shopping cart. If your widget does need
JavaScript functions, you can create a new file to include all of the required JavaScript. Create
your JavaScript file within the following directory:
- For site-level widgets -
crs-web\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier\javascript
- For store-level widgets -
crs-web\WebContent\store\Widgets-vendor\om.vendor.commerce.store.widgets.identifier\javascript
If the JavaScript file is shared by multiple custom widgets, add the file into the following
directory:
- For site-level widgets -
crs-web\WebContent\Widgets-vendor\Common
- For store-level widgets -
crs-web\WebContent\store\Widgets-vendor\Common
If your widget is a site-level widget move the assets to the
Common
directory at the site-level.
To retrieve and use JavaScript for your widget, ensure that the
widget definition XML for your widget references the JavaScript file.
For an example of a
JavaScript asset for a widget, see the catalog entry recommendation widget JavaScript file.
- crs-web\WebContent\widgetdir\com.ibm.commerce.store.widgets.CatalogEntryRecommendation\javascript\CatalogEntryRecommendation.js
- Optional:
If your custom widget uses a JSP file, fragment, or other asset, move the asset into the common
directory. Ensure that your widget references the new file path.
- For site-level widgets -
crs-web\WebContent\Widgets-vendor\Common
- For store-level widgets -
crs-web\WebContent\store\Widgets-vendor\Common
If your widget is a site-level widget move the assets to the
Common
directory at the site-level.
- Optional:
If you are converting an existing store JSP file to be a widget, edit the existing store JSP to
remove the code that you converted to a widget. Update the JSP file to call the Commerce Composer
tool to provide content for the store page by including your custom widget in the page with the
following code:
<c:import url= "${path to the widget top-level JSP file}"/>