WebSphere Commerce AJAX framework
The WebSphere Commerce AJAX
framework is an extension of the Dojo AJAX and events API. It provides an easy
to use framework that meets most AJAX requirements for storefront development,
and hides some of the complexity and repetitive code that a storefront
developer often encounters.
There
are four common scenarios involved with the WebSphere Commerce AJAX framework:
- An AJAX call is made to the WebSphere Commerce
server to update a business object. Sections of the page are refreshed
with new content if the update is successful. The new content is retrieved
using subsequent AJAX calls to the WebSphere Commerce server.
- An AJAX call is made to refresh a section of the
page because of certain customer interactions.
- An AJAX call is made to the WebSphere Commerce server
to update a business object. Sections of the page should refresh with new
content if the update is successful. The new content is retrieved using
subsequent AJAX calls to the WebSphere Commerce server. This is a repeat
of the first scenario, however, instead of making the code modular, a less
traffic intensive approach to the server is wanted.
In this scenario, an AJAX call is made to the WebSphere Commerce
server to update a business object. Sections of the page are refreshed with new
content if the update is successful. All the relevant information to refresh
the contents of the page are returned as a JSON object. The client then has the
contents of the JSON object and uses the DOM manipulation API to modify all the
areas of the page that should change as a result of the successful update.
- An AJAX call is made to the WebSphere Commerce
server requesting JSON data. Sections of the page are then updated using
JavaScript and the DOM manipulation API.
The
WebSphere Commerce AJAX framework is not required for the third and fourth
scenarios, as these scenarios can be performed directly using the Dojo AJAX API.
Important: Avoid making concurrent Ajax calls for commands. In particular,
avoid concurrent calls that turn a generic user into a new guest user with a
user activity token. The concurrent calls result in multiple user activity
tokens in the session, which causes undesired results.
You can make concurrent Ajax calls for
views.
Scenario 1: Updating a business object in WebSphere Commerce using
AJAX, then refreshing multiple areas using subsequent AJAX requests to get the
refresh contents
There are two parts to this scenario:
- An AJAX call is made to a WebSphere Commerce
controller command or WebSphere Commerce service to update a business
object (or multiple business objects).
- Subsequent AJAX get requests are made to WebSphere
Commerce views to retrieve the new HTML contents for each area if the
update is successful.
The following two diagrams show which interactions occur between
the client and the WebSphere Commerce server in this scenario.
Interaction
diagram when calling WebSphere Commerce controller commands:
Interaction
diagram when calling WebSphere Commerce services:
1. Making an AJAX call to a WebSphere
Commerce controller command or service
Before
the client is able to call a WebSphere Commerce controller command or service
using AJAX, the WebSphere Commerce server must define that the controller
command or service can be called using AJAX (rather than the traditional
programming model where the request is made and a new redirect is implied by
the WebSphere Commerce runtime).
To
define a controller command or service to be available for AJAX type requests,
simply define a new struts-action entry in the struts-config XML file that
identifies the controller command or service as an AJAX type of action. For
example, to create a new struts-action for the InterestItemAdd controller
command that can be called using AJAX, it must be defined it in the struts
configuration XML file:
Figure 1. Commands:
<action
parameter="com.ibm.commerce.interestitems.commands.InterestItemAddCmd"
path="/AjaxInterestItemAdd"
type="com.ibm.commerce.struts.AjaxAction">
<set-property property="authenticate" value="0:0"/>
<set-property property="https" value="0:1"/>
</action>
Figure 2. Services:
<action
parameter="order.addOrderItem"
path="/
AjaxOrderChangeServiceItemAdd" type="com.ibm.commerce.struts.AjaxComponentServiceAction">
<set-property property="authenticate" value="0:0"/>
<set-property property="https" value="0:1"/>
</action>
The characteristics of an AjaxAction type
URL is that after the execution of the command or service, the WebSphere
Commerce runtime automatically forwards the request to one of two well known
views to compose a JSON object containing all the entries in the response back
to the client. The two well known views map to these JSP files
- WC_eardir/Stores.war/AjaxActionResponse.jsp
(success case)
- WC_eardir/Stores.war/AjaxActionErrorResponse.jsp
(failure case)
- WCDE_installdir/workspace/Stores/WebContent/AjaxActionResponse.jsp
- WCDE_installdir/workspace/Stores/WebContent/AjaxActionErrorResponse.jsp
Now that AJAX struts-actions are defined, the wc.service.declare
API is used in the JavaScript code to define a service for each of the required
URLs being called in the page. The wc.service.declare API declares a JavaScript
service object that is able to call WebSphere Commerce AJAX type
struts-actions. This gives the control to the client for when to execute the
AJAX call. For example, the following JavaScript code in the client defines a
service object for calling InterestItemAdd using AJAX:
wc.service.declare({
id: "AjaxInterestItemAdd",
actionId: " AjaxInterestItemAdd",
url: " AjaxInterestItemAdd",
formId: "",
successHandler: function(serviceResponse) {
alert("success");
},
failureHandler: function(serviceResponse) {
if (serviceResponse.errorMessage) {
alert(serviceResponse.errorMessage);
}
}
});
The above definition simply defines an
object, and does not yet trigger the AJAX call to the WebSphere Commerce
server. To invoke the AJAX call, the following API is used:
wc.service.invoke("AjaxInterestItemAdd");
The successHandler function defined in the
service declaration is executed and two model changed Dojo events are published
automatically by the framework when the request completes successfully. The events
that are published are called modelChanged and modelChanged/actionId, and
Dojo automatically notifies all subscribed listeners.
2. Making AJAX calls to WebSphere Commerce
views to get refresh contents
The WebSphere Commerce AJAX framework
provides two more JavaScript objects called refresh controllers and refresh
areas. Any HTML element of a page can be designated as a refresh area. The
content within the HTML tag will be replaced by new content from the WebSphere
Commerce server whenever the refresh controller associated with the refresh
area triggers the refresh request. This sample code defines a refresh area in
the page:
<div dojoType="wc.widget.RefreshArea"
id="MiniShoppingCart"
widgetId="MiniShoppingCart"
controllerId="MiniShoppingCartController">
</div>
A refresh area always has a refresh
controller associated with it. The refresh controllers are automatically
registered to listen to modelChanged and renderContextChanged events.
Therefore, they will be notified when these events occur. They then evaluate
the model changes and/or render context changes and decide if the refresh areas
that it manages should be refreshed or not. The following sample code shows how
to define a refresh controller:
wc.render.declareRefreshController({
id: "MiniShoppingCartController",
renderContext: wc.render.getContextById("MiniShoppingCartContext"),
url: "MiniShoppingCartView",
formId: "",
modelChangedHandler: function(message, widget) {
if(message.actionId in order_updated){
widget.refresh();
}
},
renderContextChangedHandler: function(message, widget) {
},
postRefreshHandler: function(widget) {
}
});
It is important to recognize the URL that
defines the WebSphere Commerce server URL to call and get the new HTML contents
for the refresh area that the refresh controller is associated to. The
modelChangedHandler function is executed by the WebSphere Commerce AJAX
framework as soon as there is a model changed event triggered by successful
wc.service.invoke() actions. Note that the modelChangedHandler function first
checks that the model changed is for an actionId that is of interest to the
refresh area. The widget.refresh() is the code that makes an AJAX call to the
WebSphere Commerce server for the URL specified in the refresh controller. Once
the new HTML fragment returns from the server, the framework destroys anything
that exists in the current refresh area and replaces its contents with the new
HTML fragment returned by the view.
Another useful function is the
postRefreshHandler function of the refresh controller, as this is the last
function that the framework calls after a refresh area is successfully
refreshed with new contents. It can be used to unblock the user interface if it
was blocked during the AJAX calls.
Note: The refresh controllers need a render context object. In this
scenario, the render context is not used, however, a dummy render context per
page must be used to make use of refresh controllers and refresh areas.
Scenario 2: Refreshing an area of the page using an AJAX request
to get the refresh contents
Areas
of the page should refresh with new content when users interact with the user
interface. This scenario uses the render context, refresh area and refresh
controllers API from the WebSphere Commerce AJAX framework.
A
render context object keeps track of context information of the client and it
can trigger renderContextChanged events whenever updates occur to any of the
properties in the render context object. The refresh controllers are
automatically registered to listen to all the renderContextChanged events. The
refresh controller logic determines if the context change should trigger an
update of a refresh area widget. Therefore, in the refresh controller's
renderContextChangedHandler, the API is used to compare the context properties
testForChangedRC to determine if the context property has changed and then
trigger the refresh of the refresh area.
An example for declaring the refresh area
to work with shopping cart paging is as follows:
<div dojoType="wc.widget.RefreshArea" widgetId="OrderItemPagingDisplay" id="OrderItemPagingDisplay" controllerId="OrderItemPaginationDisplayController"
role="wairole:region" waistate:live="polite" waistate:atomic="false" waistate:relevant="all">
<%out.flush();%>
<c:import url="${jspStoreDir}ShoppingArea/CheckoutSection/SingleShipment/OrderItemDetailSummary.jsp">
<c:param name="catalogId" value="${WCParam.catalogId}" />
<c:param name="langId" value="${WCParam.langId}" />
<c:param name="storeId" value="${WCParam.storeId}" />
<c:param name="orderPage" value="summary" />
</c:import>
<%out.flush();%>
</div>
Scenario 3: Updating a business object in WebSphere Commerce using
AJAX and returning all relevant update information using JSON
This scenario can be achieved using the
Dojo API directly. Therefore, there is no need to use the WebSphere Commerce
AJAX framework if this scenario is of relevant interest. The dojo.xhrPost API is used in conjunction with the
traditional WebSphere Commerce runtime programming model, where a request is
made to a controller command or a service, and after execution, the WebSphere
Commerce runtime redirects the request to whatever is specified in the URL or
errorViewName parameters in the original request. For example
var parameters = {};
parameters.storeId = storeId;
parameters.langId=langId;
parameters.catalogId=catalogId;
parameters.catentryId=productId;
parameters.URL="MiniCartContentsJSON";
parameters.errorViewName="MiniCartContentsJSON";
dojo.xhrPost({
url: "OrderChangeServiceItemAdd",
handleAs: "json-comment-filtered",
content: parameters,
service: this,
load: refreshMiniCart,
error: function(errObj,ioArgs) {
alert("error");
}
});
This code snippet makes an AJAX request to
the OrderChangeServiceItemAdd service and then redirects to the
MiniCartContentsJSON view, which is mapped to a JSP file that creates a JSON
object with its content. In this scenario, the assumptions are that the same
JSP file handles the error scenario as we set the errorViewName to the same
MiniCartContentsJSON view. The client then gains control back and either the
load or error function is called depending on the respective success or
failure.
Note: The error scenario is only called when there are difficulties
communicating with the WebSphere Commerce server. Otherwise, a success or
exception from the WebSphere Commerce code executes the load function. The load
function determines from the JSON object whether the request was successful or
it failed.
The
load function uses the JSON object and DOM manipulation API to replace all the
elements in the page that should be updated with new data that resulted from
the server update. URLs do not need to be registered as AjaxAction, as this
scenario does not make use of any of the new WebSphere Commerce AJAX framework.
Scenario 4: Calling WebSphere Commerce server using AJAX to gather
new data as a JSON object and refreshing the page contents
This
scenario can be achieved using the Dojo API directly. Therefore, there is no
need to use the WebSphere Commerce AJAX framework if this scenario is of
relevant interest. The dojo.xhrPost API is used in conjunction with the
traditional WebSphere Commerce runtime programming model, where a request is
made to a view that maps to a JSP file that creates a JSON object. On the load
function of the xhrPost API, the DOM manipulation API is used to put the JSON
contents in the web page elements.