Implementing AjaxAction based Commands


A process of communicating with Commerce commands in an Ajax fashion without refreshing the page. The response generated in the Command is converted to a JSON (JavaScript Object Notation).
However this is not done using any Ajax framework at the client end.

Commands
Create a regular command interface and implementation in Commerce.
Only difference in writing this AjaxAction based command compared to a regular command is the inclusion of the line at the end of performExecute() method
setResponseProperties(rspProp);
Here rspProp is the TypedProperty variable in the method.
All the data that is required to be sent back to the source (JSP/browser) that called this command should be placed in the TypedProperty variable.

Struts Configuration
·         Instead of setting the type of <action-mappings> as BaseAction, it is set to AjaxAction
·         There is no <global-forwards> entry required for this since only data object is got back instead of redirecting to a different page.
·         A sample struts configuration entry under action-mappings will look like below

<action path="/AjaxActionDemo" type="com.ibm.commerce.struts.AjaxAction" parameter="com.asi.commerce.commands.process.AjaxActionDemoCmd">
    <set-property property="https" value="0:0"/>
</action>

CMDREG
The CMDREG entry will be similar to that of any other command. Below is just a sample
INSERT INTO ADMINISTRATOR.CMDREG (STOREENT_ID,INTERFACENAME,DESCRIPTION,CLASSNAME,TARGET) VALUES (0,'com.asi.commerce.commands.process.AjaxActionDemoCmd','Sample command to demonstrate AjaxAction based commands','com.asi.commerce.commands.process.AjaxActionDemoCmdImpl','LOCAL');

ACPLOAD
ACPLOAD entry will be similar to that of any other command. Below is just a sample

<?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?>
<!DOCTYPE Policies SYSTEM "../dtd/accesscontrolpolicies.dtd">
<Policies>
<ResourceCategory  Name="com.asi.commerce.commands.process.AjaxActionDemoCmdResourceCategory" ResourceBeanClass="com.asi.commerce.commands.process.AjaxActionDemoCmd">
            <ResourceAction Name="ExecuteCommand"/>
                </ResourceCategory> 
                <ResourceGroup Name="AllSiteUserCmdResourceGroup" OwnerID="RootOrganization">
                                <ResourceGroupResource Name="com.asi.commerce.commands.process.AjaxActionDemoCmdResourceCategory"/>
                </ResourceGroup>
</Policies>



AjaxActionResponse.jsp & AjaxActionErrorResponse.jsp
After the command is executed, a successful and erroneous response is handled by the appropriate JSP files above for redirection.
If the command is executed successfully, the contents in the TypedProperty variable are converted to either a JSON object or JSON array depending on the data type of the Object.
If there is an exception in the command execution, the error object is built and converted to JSON format and redirected back similar to successful response.
These files should be available under WebContent folder of Stores.

Both these JSPs will attempt to call a function ‘callback()’ in the source JSP files.

Client JSP
This AjaxAction based command can be called in anyway apt depending on the requirement.
In the below case following is done.
·         An arbitrary HTML element is created using Javascript DOM capability.
·         The src attribute is set to the AjaxAction based COMMAND url. If this JSP exists inside the context of the commerce server, just the command reference would suffice. If it is being called from a third party, then the full URL is to be provided.
e.g. http://localhost/webapp/wcs/stores/servlet/AjaxActionDemo?testArg1=TEST_ARGUEMENT_1&testArg2=TEST_ARGUEMENT_2
·         Whenever the DOM element is appended to the parent container of HTML, it’s src attribute will be processed thus calling the command.
var script = document.createElement("script");
            script.setAttribute('id', "ajaxScript");
            script.setAttribute('src', wcsUrl);
      document.getElementsByTagName('head')[0].appendChild(script);
·         The Ajax response JSP files after processing the request will trigger the callback() function in the jsp with the JSON data object passed as an argument. This data can be used as per requirement.
·         Right practice would be delete the earlier created HTML element so it would not conflict when used again. This can be done in the callback() method after receiving the data.
var s = document.getElementById("ajaxScript");
      s.parentNode.removeChild(s);

Comments

Unknown said…
Good Explanation....
Anonymous said…
If we are extending a OOB interface and its class,how should we run acpload for the new command.Consider the OOB command has some rule set to run acpload.
Simon Payne said…
Thanks for this, I had a go at using the AjaxActionResponse coupled with Dojo, and the wc.service.declare/invoke pattern that IBM recommends. However I ran into problems with the JSON format: the JSON needs to be comment-filtered for this method to work. What solved it for me was to put comments around the JSON returned by AjaxActionResponse.jsp as per :

/*
<wcf:json object="${RequestProperties}"/>
*/

This was a bizarre fix that I stumbled upon, and I've many misgivings about altering an in-built IBM JSP, so am trying to extend AjaxAction instead. I wonder if you have seen this issue with comment-filtering and have any comments?
Tarunendra said…
Hi, I'm facing the same issue.. but I could see that AjaxActionResponse.jsp already have those comments. Controller Command is returning the JSON which is valid...

InputStream in = new ByteArrayInputStream(responseStr.getBytes());
rspProp.put("textDocument", in);
rspProp.put("viewTaskName", ECConstants.EC_GENERIC_DIRECTVIEW);
rspProp.put("contentType", "text/html");
setResponseProperties(rspProp);

I'd appreciate your help.
KM said…

if rspProp.put("controllerParm1", "message1");
function handleResponse(data){
//how to get value of controllerParm1 in AJAX response, if type is json.
}

And if Set databean as below then how I will get value of databean and its property into Json object in jsp page:

MyNewDataBean mndb = new MyNewDataBean();
mndb.setCallingCommandName(this.getClass().getName());
mndb.setCalledByControllerCmd(true);
rspProp.put("mndbInstance", mndb);


Popular posts from this blog

Dataload Utility In WCS

10 Steps to Configure Email – Websphere Commerce Server

Multiple Wish List