Activity Token is the equivalent of sessionid and thought not advised but sometimes, it is required to use activityId for some custom implementations:
1. If you are implementing a custom XSRF, even though V6 Fix Pack 10 has this feature.
2. Custom WebService across devices that can't use cookies but need to maintain commerce session.
public ActivityToken getActivityToken(HttpServletRequest request)
{
// Check, is it available as a request attribute?
ActivityToken token = null;
token = (ActivityToken) request.getAttribute(ECAttributes.ATTR_EC_ACTIVITY_TOKEN);
// that's not true, try request handle
if (token == null) {
RequestHandle handle = (RequestHandle)request.getAttribute(ECAttributes.ATTR_EC_REQUEST_HANDLE);
token = (handle != null) ? handle.getActivityToken() : null;
}
// Try command context , if above 2 returne
if (token == null) {
CommandContext commandContext = (CommandContext) request.getAttribute("CommandContext");
token = (commandContext != null) ? commandContext.getActivityToken() : null;
}
return token;
}
This is my 50th post, if you guys like reading my blogs :), please drop a comment.
Thursday, August 11, 2011
Friday, August 5, 2011
ServerJDBCHelperAccessBean, should you or should you not ?
It is highly recommended to use EJB's for any insert\updates for the overall integrity of the data in commerce but ServerJDBCHelperAccessBean is a good friend that comes handy in
several scenarios when required to insert\update tables outside of EJB's and also do selects from multiple tables. Also the flush() method is used to flush the cache in EJB container for the DB updates.
Internally uses preparedStatement but you don't have to map each param and could send an array of params to the executeQuery method in the same order as query.
It is also useful to use if you have dynamic SQLs for any kind of search.
several scenarios when required to insert\update tables outside of EJB's and also do selects from multiple tables. Also the flush() method is used to flush the cache in EJB container for the DB updates.
Internally uses preparedStatement but you don't have to map each param and could send an array of params to the executeQuery method in the same order as query.
It is also useful to use if you have dynamic SQLs for any kind of search.
code Example:
sqlQuery could be dynamic query based on logic being built or static.
databaseRows is an object of vector -> vectors.
ServerJDBCHelperAccessBean jdbcHelper = new ServerJDBCHelperAccessBean();
Vector databaseRows = new Vector();
databaseRows = jdbcHelper.executeParameterizedQuery(sqlQuery, params);
for(Object obj:databaseRows) {
Vector EachRow=(Vector)obj;
Long catentryId= (Long)EachRow.get(0);
String catGroupIdentifier =(String)EachRow.get(0);
Timestamp timePlaced = (Timestamp)EachRow.get(3);
}
Note: If you are using to update a row in DB, do make sure to update the OPTCounter.
Thursday, August 4, 2011
Dynacache - 101 !!!!
Dynacache service is an in-memory cache system that has disk offload capacity.
What is CacheSpec.xml?
The objects to be cached are specified in cachespec.xml.
Location of cachespec in toolkit\Stores\WebContent\WEB-INF On server:\Stores.war\WEB-INF\
What can be cached? Servlet\JSP's and commands that extend from CacheableCommand interface can be cached using DynaCache.
What is DynaCache Monitor? This is an application provided by IBM for dynacache statistics, it can be installed on toolkit as well as server.
Example from cachespec for JSP\Servlet caching entries:
Servlet: .e.g. storecatalogdisplay:
<cache-id>
<component id="" type="pathinfo">
<required>true</required>
<value>/StoreCatalogDisplay</value>
</component>
<component id="storeId" type="parameter">
<value>10151</value>
<required>true</required>
</component>
<component id="catalogId" type="parameter">
<required>true</required>
</component>
<component id="langId" type="parameter">
<required>false</required>
</component>
<component id="trackingEvent" type="parameter">
<required>false</required>
</component>
<priority>30</priority>
</cache-id>
Servlet: .e.g. storecatalogdisplay:
<cache-id>
<component id="" type="pathinfo">
<required>true</required>
<value>/StoreCatalogDisplay</value>
</component>
<component id="storeId" type="parameter">
<value>10151</value>
<required>true</required>
</component>
<component id="catalogId" type="parameter">
<required>true</required>
</component>
<component id="langId" type="parameter">
<required>false</required>
</component>
<component id="trackingEvent" type="parameter">
<required>false</required>
</component>
<priority>30</priority>
</cache-id>
JSP: e.g. header.jsp
<cache-entry>
<class>servlet</class>
<name>ABCStorefront/include/header.jsp</name>
<property name="do-not-consume">true</property>
<property name="save-attributes">false</property>
<property name="ignore-get-post">true</property>
<sharing-policy>not-shared</sharing-policy>
<cache-id>
<component id="storeId" type="parameter">
<required>true</required>
</component>
<component id="catalogId" type="parameter">
<required>true</required>
</component>
<component id="DC_lang" type="attribute">
<required>false</required>
</component>
<component id="userImpersonated" type="parameter">
<required>false</required>
</component>
<priority>100</priority>
</cache-id>
<!-- Dependency Ids -->
<dependency-id>TTL:STAGEPROP</dependency-id>
<dependency-id>storeId
<component id="storeId" type="parameter">
<required>true</required>
</component>
</dependency-id>
<dependency-id>catalogId
<component id="catalogId" type="parameter">
<required>true</required>
</component>
</dependency-id>
<!-- Ends Dependency Ids -->
</cache-entry>
<class>servlet</class>
<name>ABCStorefront/include/header.jsp</name>
<property name="do-not-consume">true</property>
<property name="save-attributes">false</property>
<property name="ignore-get-post">true</property>
<sharing-policy>not-shared</sharing-policy>
<cache-id>
<component id="storeId" type="parameter">
<required>true</required>
</component>
<component id="catalogId" type="parameter">
<required>true</required>
</component>
<component id="DC_lang" type="attribute">
<required>false</required>
</component>
<component id="userImpersonated" type="parameter">
<required>false</required>
</component>
<priority>100</priority>
</cache-id>
<!-- Dependency Ids -->
<dependency-id>TTL:STAGEPROP</dependency-id>
<dependency-id>storeId
<component id="storeId" type="parameter">
<required>true</required>
</component>
</dependency-id>
<dependency-id>catalogId
<component id="catalogId" type="parameter">
<required>true</required>
</component>
</dependency-id>
<!-- Ends Dependency Ids -->
</cache-entry>
Enable Servlet caching:
1. In the administrative console, click Servers > Application servers > server_name > Web container settings > Web container in the console navigation tree.
2. Select Enable servlet caching under the Configuration tab.
3. Click Apply.
4. Restart the Server.
Performance and CPU usage: performance of the overall site and CPU usage on the app server is considerably improved with Dynacache enabled. Having a good Dynacache strategy is very important for the performance of the site. Will write another blog on that topic.
1. In the administrative console, click Servers > Application servers > server_name > Web container settings > Web container in the console navigation tree.
2. Select Enable servlet caching under the Configuration tab.
3. Click Apply.
4. Restart the Server.
Performance and CPU usage: performance of the overall site and CPU usage on the app server is considerably improved with Dynacache enabled. Having a good Dynacache strategy is very important for the performance of the site. Will write another blog on that topic.
Wednesday, August 3, 2011
JSTL | Top 10 JSTL statements most often used !!!
It is highly recommended to use JSTL to build JSP Pages in WCS: ${...} --Expression Language
- Naming Convention of methods in Bean for boolean check
boolean itemsReturned=false;
public boolean isItemsReturned() {
return itemsReturned;
}
<if test="${!orderStatus. itemsReturned }">
</c:if>
- Setting Variables in a JSP:
- <c:set var="status" value="P"/>
- <c:set var="errorZipCounter" value="0" />
- <c:set var="accDisplaycount" value="${accDisplaycount + 1 }" />
- If, Else this is the equivalent of If Else as JSTL does not have the usual If Else
<c:choose><c:when test="${!empty WCParam.source}"><c:set var="source" value="${WCParam.source}" /></c:when><c:otherwise><c:set var="source" value="${source}" /></c:otherwise></c:choose>
- For statement: counter is current status variable, you could get index\first\last\current\count status.
<c:forEach items="${orderList}" var="order" varStatus="counter">If the orderList is a list of orderdatabeans or something, you could loop through them</c:forEach>
- If statment example:
<c:if test="${(!empty WCParam.orderStatus && (WCParam.orderStatus eq 'Y'))}">You can use eq,ne,lt,gt,ge,le other relational operators</c:if>
- Constructing hyperlinks: Prep-ends the name of current servlet context,URl encoding of request params and values, URl re-writing for session management.
<a href="<c:url value='/content/sitemap.jsp'/>">View sitemap</a><c:url var="productDisplayURL" value="ProductDisplay"><c:param name="catalogId" value="${WCParam.catalogId}"/><c:param name="storeId" value="${WCParam.storeId}"/><c:param name="langId" value="${WCParam.langId}"/><c:param name="productId" value="${accessoryItem.itemId}"/></c:url>
- Include content of a JSP into another JSP:
<c:import url="../../CurrentOrderSection/OrderItemDetailsDisplay.jsp"><c:param name="orderId" value="${WCParam.orderId}"/></c:import><% out.flush(); %><c:import url="${storeDir}include/footer.jsp"/><% out.flush(); %><% out.flush(); %><c:import url="{storeDir}include/header.jsp"/><% out.flush(); %>
- Removes a variable from scope:
<c:remove var="wishListURL" scope="page"/>
- Print the value: Also helpful to print values in JavaScript. The <c:out> tag evaluates an expression and outputs the result on the page
status:<c:out value="${WCParam.status}"/>firstName:<c:out value="${orderDetailsVB.orderBillingAddress.firstName}"<script language="javascript" src="<c:out value="${storeJavascriptDir}/browser_detect.js" />"></script>
- Using functions: There are several functions that are very helpful
var paramvalues = "<c:out value="${fn:substring(config.params, 1, -1)}" escapeXml="false"/>";<c:set var="dispalyPrice" value="${fn:substringAfter(orderItemTotalPrice,)}"/><c:when test="${fn:indexOf(locale, 'en') >= 0}"></c:when>
- useBean to instantiate and auto populate the bean
<wcbase:useBean id="orderDetailsVB" classname="com.abc.order.beans.OrderDetailsViewBean"><c:set target="${orderDetailsVB}" property="orderId" value="${WCParam.orderId}"/><c:set target="${orderDetailsVB}" property="orderStatus" value="${status}"/></wcbase:useBean><wcbase:useBean id="productVB" classname="com.abc.catalog.beans.ItemViewBean" scope="request" ><c:set target="${productVB}" property="itemId" value="${WCParam.catentryId}" /></wcbase:useBean>
Friday, July 29, 2011
Krypto | crazyness !!!
When ever a view or command is defined as HTTPS true in struts-config-ext.xml
commerce while redirecting converts all parameters in the URL querty string to a krypto value.
Krypto = encrypted(querystringParameters,merchantKey).
You can bypass params from this krypto by the configuration mentioned below in wc-server.xml
e.g.
storeId=10151&
catalogId=10101&
langId=-1&
orderId=55011&
myName=y
krypto:=7Agv%2BGyHJCuZcMIjIs%2Fd68CfRxuGbxeKNDAGlIEEXgm....
If there are parameters that are required to be not encrypted, commerce provides a configuration to define in wc-server.xml
<NonEncryptedParameters display="false">
<Parameter name="storeId"/>
<Parameter name="langId"/>
<Parameter name="catalogId"/>
<Parameter name="categoryId"/>
<Parameter name="productId"/>
</NonEncryptedParameters>
Problems associated with krypto:
commerce while redirecting converts all parameters in the URL querty string to a krypto value.
Krypto = encrypted(querystringParameters,merchantKey).
You can bypass params from this krypto by the configuration mentioned below in wc-server.xml
e.g.
storeId=10151&
catalogId=10101&
langId=-1&
orderId=55011&
myName=y
krypto:=7Agv%2BGyHJCuZcMIjIs%2Fd68CfRxuGbxeKNDAGlIEEXgm....
If there are parameters that are required to be not encrypted, commerce provides a configuration to define in wc-server.xml
<NonEncryptedParameters display="false">
<Parameter name="storeId"/>
<Parameter name="langId"/>
<Parameter name="catalogId"/>
<Parameter name="categoryId"/>
<Parameter name="productId"/>
</NonEncryptedParameters>
- Caching nightmare with Krypto. If the params are encrypted, it would be very difficult to define caching parameters so make sure, to add them in the above block. As a best practise all catalog related params, add them to the blocks
- krypto keeps getting longer and in the older versions of browser, it was a problem where developers had to remove the params and only keep the required one's in request\response.
Sunday, July 24, 2011
Unraveling the code patches !!
For supporting an existing commerce site, performing a code patch is an important feature for the success of an eCommerce platform.
A complete code deploy is not always an option as it could involve a longer down time and even though commerce offers the feature of deploying code on 1 node at a time through Deployment Manager (DM) without bringing down the complete site. The above step is only possible if you don't have database changes.
Also the regression testing for complete code deploy does not make it very ideal. Performing a java code patch e.g. ExtLogonControllerCmdImpl class in package com/company/user/commands
1. If there are any DB related changes. Make them first.
2.Stop 1 server at a time.
3 CD opt/IBM/WebSphere/AppServer/profiles//installedApps/WC__cell/WC_.ear/Stores.war/WEB-INF/classes/
4. Create the complete directory structure of the package and drop the class file. com/company/user/commands/ExtLogonControllerCmdImpl.class.
5. Restart the server.
If you have only JSP changes, drop the JSP in the appropriate folder and delete the JSP cache in temp folder and refresh DynaCache. Does not require a server restart.
A complete code deploy is not always an option as it could involve a longer down time and even though commerce offers the feature of deploying code on 1 node at a time through Deployment Manager (DM) without bringing down the complete site. The above step is only possible if you don't have database changes.
Also the regression testing for complete code deploy does not make it very ideal. Performing a java code patch e.g. ExtLogonControllerCmdImpl class in package com/company/user/commands
1. If there are any DB related changes. Make them first.
2.Stop 1 server at a time.
3 CD opt/IBM/WebSphere/AppServer/profiles/
4. Create the complete directory structure of the package and drop the class file. com/company/user/commands/ExtLogonControllerCmdImpl.class.
5. Restart the server.
If you have only JSP changes, drop the JSP in the appropriate folder and delete the JSP cache in temp folder and refresh DynaCache. Does not require a server restart.
Sunday, July 17, 2011
Character Verification on Registration\Forgot Password | Captcha
Recaptcha is a free solution hosted and owned by Google.
Pros: Widely used in the industry, services based solution really easy to impelemnt
Cons:The biggest minus on this is, if you have a strong firewall policy where the outgoing IP/Ports for app servers are blocked. This solution will not work as the IP addresses will change some times and hence it might not be feasible to dynamically open up the firewalls for the new addresses.

Kaptcha is a free Apache license based java solution works with JDK 1.4.2,
Pros: Really easy to implement and drop the jar files, no external webservices required. if you are using V6 and it also works with later versions of JDK hence this would work for V7. Kaptcha uses pixels and previous versions image libraries to refresh the image.
Cons: Does not support audio.
Pros: Really easy to implement and drop the jar files, no external webservices required. if you are using V6 and it also works with later versions of JDK hence this would work for V7. Kaptcha uses pixels and previous versions image libraries to refresh the image.
Cons: Does not support audio.

How to use in commerce?
1. Entry in web.xml for the servlet mapping, make this entry after dynacache and other OOB filters.
<servlet>
<servlet-name>Kaptcha</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Kaptcha</servlet-name>
<url-pattern>/kaptcha</url-pattern>
</servlet-mapping>
2. The default implementation has .jpg but if you are using edge caching such as Akamai, removed tha .jpg.
3. Add the external jar file and making a corresponding entry in META_INF (I have a blog on this for reference http://www.ibmwcs.com/2011/06/adding-external-jar-file-to-wcs.html)
4. The API returns HTML collection, you can access in your javascript as follows:
var kaptchaVariable=document.getElementsByName("kaptcha").item(1).value;
5. If you need to refresh the Kaptcha implement a javascript on click and you can do HTML write attribute.
.writeAttribute('src','/webapp/wcs/stores/kaptcha?' + Math.floor(Math.random()*100) );
6. You can also implement an on the img and use the following method
$(AnchorelementPassed).down().writeAttribute('src', '/webapp/wcs/stores/kaptch?' + Math.floor(Math.random()*100) );
7. You can implement in a ajax call or a command but you can validate in validateParameters.
HttpServletRequest request =
((com.ibm.commerce.webcontroller.HttpControllerRequestObject) this
.getCommandContext()
.getRequest())
.getHttpRequest();
String kaptchaValueExpected = (String)request.getSession().
(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
Reference: http://www.google.com/recaptcha
http://code.google.com/p/kaptcha/
1. Entry in web.xml for the servlet mapping, make this entry after dynacache and other OOB filters.
<servlet-name>Kaptcha</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Kaptcha</servlet-name>
<url-pattern>/kaptcha</url-pattern>
</servlet-mapping>
2. The default implementation has .jpg but if you are using edge caching such as Akamai, removed tha .jpg.
3. Add the external jar file and making a corresponding entry in META_INF (I have a blog on this for reference http://www.ibmwcs.com/2011/06/adding-external-jar-file-to-wcs.html)
4. The API returns HTML collection, you can access in your javascript as follows:
var kaptchaVariable=document.getElementsByName("kaptcha").item(1).value;
5. If you need to refresh the Kaptcha implement a javascript on click and you can do HTML write attribute.
.writeAttribute('src','/webapp/wcs/stores/kaptcha?' + Math.floor(Math.random()*100) );
6. You can also implement an on the img and use the following method
$(AnchorelementPassed).down().writeAttribute('src', '/webapp/wcs/stores/kaptch?' + Math.floor(Math.random()*100) );
7. You can implement in a ajax call or a command but you can validate in validateParameters.
HttpServletRequest request =
((com.ibm.commerce.webcontroller.HttpControllerRequestObject) this
.getCommandContext()
.getRequest())
.getHttpRequest();
String kaptchaValueExpected = (String)request.getSession().
(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
Reference: http://www.google.com/recaptcha
http://code.google.com/p/kaptcha/
Subscribe to:
Posts (Atom)