Friday, August 26, 2011

Programming a Schedule Job !!! Dynamic job

I find dynamic schedule jobs a very useful feature in Websphere commerce. It is very useful for jobs that require to be dynamically generated based on some programming logic in a command. e.g. if there are emails that need to be triggered based on a event or any admin action that requires a schedule job to run to generate reports.

AddJobCmd addJobCmd =
(AddJobCmd) CommandFactory.createCommand(
AddJobCmd.class.getName(),
commandContext.getStoreId());
addJobCmd.setQueryString();
addJobCmd.setForUserId();
addJobCmd.setStartTime();
addJobCmd.setPathInfo("");
addJobCmd.setUrl(); //Even though this is not checked in validate parameters, this is required
addJobCmd.setStoreId(new Integer(SITE_STORE));
addJobCmd.setCommandContext(commandContext);
addJobCmd.setAccCheck(false);
addJobCmd.execute();
addJobCmd.setAccCheck(true);


recurring Jobs needs these extra methods to be configured:

addJobCmd.setAttempts()
addJobCmd.setDelay()
addJobCmd.setInterval()


Thursday, August 11, 2011

Application of Activity Token | Multiple ways to getActivityToken

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.

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.

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>


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>


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.


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>