Sunday, September 13, 2015

Create a Cache Parameter for Custom Bussiness context in WCS

1.Create a new CallBack class for the custom business context.

public class MyCompanyCallBack {

//private static String className = com.ibm.commerce.dynacache.filter.MyCompanyCallBack.className;

private MyCompanyCallBack() { }

public static String getMyCompany(SessionAttrMap m, CacheFilterContext cfc){
CommandContext cc = cfc.getCmdctx();
 MyCompanyContext shipContext = (MyCompanyContext) cc.getContext(MyCompanyContext.CONTEXT_NAME);
return shipContext.getCountry();
}

public static void setMyCompany(SessionAttrMap m, CacheFilterContext cfc){
CommandContext cc = cfc.getCmdctx();
 MyCompanyContext shipContext = (MyCompanyContext) cc.getContext(MyCompanyContext.CONTEXT_NAME);
String country = shipContext.getShipToCountry();
cfc.getRequest().setAttribute(m.getDynacacheAttributeName(), country);
}
}

2.Add the call back entry in wc-server.xml.

<component
            compClassName="com.ibm.commerce.dynacache.filter.CacheFilterAttributeMapHelper"
            enable="true" name="DynaCacheFilterMappings">
            <property display="false" refreshInterval="300000">
                <map
                    className="com.ibm.commerce.context.base.BaseContext"
                    display="false" dynacacheAttributeName="DC_storeId"
                    methodName="getStoreId" name="getStoreId"/>
                <map
                    className="com.ibm.commerce.context.base.BaseContext"
                    display="false" dynacacheAttributeName="DC_userId"
                    methodName="getCallerId" name="getCallerId"/>
                <map
                    className="com.ibm.commerce.context.globalization.GlobalizationContext"
                    display="false" dynacacheAttributeName="DC_lang"
                    methodName="getLanguageId" name="getLanguageId"/>
                <map
                    className="com.ibm.commerce.context.globalization.GlobalizationContext"
                    display="false" dynacacheAttributeName="DC_curr"
                    methodName="getCurrency" name="getCurrency"/>
                <map
                    className="com.ibm.commerce.dynacache.filter.ParentOrganizationCallBack"
                    display="false" dynacacheAttributeName="DC_porg"
                    methodName="setParentOrg" name="setParentOrg"/>
                <map
                    className="com.ibm.commerce.dynacache.filter.ActiveOrganizationCallBack"
                    display="false" dynacacheAttributeName="DC_aorg"
                    methodName="setActiveOrg" name="setActiveOrg"/>
                <map
                    className="com.ibm.commerce.dynacache.filter.MemberGroupsCallBack"
                    display="false" dynacacheAttributeName="DC_mg"
                    methodName="setMemberGroups" name="setMemberGroups"/>
                <map
                    className="com.ibm.commerce.dynacache.filter.CatalogAndPriceCallBack"
                    display="false" dynacacheAttributeName="DC_cont"
                    methodName="setContracts" name="setContracts"/>
                <map
                    className="com.ibm.commerce.dynacache.filter.UserTypeCallBack"
                    display="false" dynacacheAttributeName="DC_userType"
                    methodName="setUserType" name="setUserType"/>
                <map
                    className="com.ibm.commerce.dynacache.filter.PortalAndWapCallBack"
                    display="false" dynacacheAttributeName="PORTAL"
                    methodName="setPortalAndWap" name="setPortalAndWap"/>
                <map
                    className="com.ibm.commerce.dynacache.filter.MyCompanyCallBack "
                    display="false" dynacacheAttributeName="DC_Company"
                    methodName="setPortalAndWap" name="setCompany"/>
            </property>
        </component>

3.Then use the parameter in the cachespec.xml as a cacheId

<cache-entry>
<class>servlet</class>
<name>/StorefrontAssetStore/Widgets/Footer/Footer.jsp</name>
<property name="do-not-consume">true</property>
<property name="save-attributes">false</property>
<property name="consume-subfragments">true</property>

<cache-id>
<component id="storeId" type="parameter">
<required>true</required>
</component>
<component id="DC_Company" type="attribute">
<required>true</required>
</component>
</cache-id>

<dependency-id>FlexFlowFeatureUpdate</dependency-id>

<dependency-id>
storeId
<component id="storeId" type="parameter">
<required>true</required>
</component>
</dependency-id>

<dependency-id>
StoreFooter:storeId
<component id="storeId" type="parameter">
<required>true</required>
</component>
</dependency-id>
</cache-entry>

Saturday, September 12, 2015

Do not cache (do-not-cache) the particular JSP in Websphere Commerce

Use the "do-not-cache" attribute as true for cache-entry of the page, which we don't want to cache. Then the particular JSP won't cache, when ever the request comes it will create a new object  instead of looking from cache object for that import JSP.


<cache-entry>
<class>servlet</class>
<name>/StorefrontAssetStore/Layouts/BrandDetails.jsp</name>
<property name="do-not-consume">true</property>
<property name="do-not-cache">true</property>
<property name="consume-subfragments">true</property>

<cache-id>
<component id="storeId" type="parameter">
<required>true</required>
</component>
<component id="catalogId" type="parameter">
<required>true</required>
</component>
<component id="DC_langId" type="parameter">
<required>true</required>
</component>
</cache-id>
</cache-entry>

Wednesday, September 9, 2015

Create a new REST Command in Websphere Commerce


1. Create a  new controller Command:
 
Package Name: com.mycompany.commerce.commands
Interface Name :com.mycompany.commerce.commands.MyCompanyControllerCmd
Class Name:com.mycompany.commerce.commands.MyCompanyControllerCmdImpl
   

       Interface and impl class

2. Then Run the RESTClassicSampleGen.bat file from "C:/IBM/WCDE_ENT70/bin/" for generate the xml mapping files and handler classes.




RESTClassicSampleGen.bat location=com.mycompany.commerce.commands.MyCompanyControllerCmd outputDir=C:\RESTconfig additionalClassPath="C:\IBM\WCDE_ENT70\workspace\WebSphereCommerceServerExtensionsLogic\bin"

3. If successfully runs, then the following  2 folder are created in "C:\RESTconfig"
  • controllerCommandSamples
  • handlerSamples



4. In the Enterprise Explorer view, go to REST > WebContent > WEB-INF > config.
  1. Create the  commandMapping-ext mapping folders.
    1. Right-click config. Click New > Folder.
    2. In the Folder name field, enter commandMapping-ext.
    3. Click Finish. The commandMapping-ext folder is created under the config directory.
  2. Copy the sample configuration to the REST configuration folder that you created
    1.  from working_dir\dataBeanSamples to the new folder: beanMapping-ext.
    2. Copy com.mycompany.commerce.commands.MyCompanyControllerCmd.xml from working_dir\controllerCommandSamples to the new folder: commandMapping-ext.
5.Go to REST > WebContent > WEB-INF > config > commandMapping-ext > .
   
Open the com.mycompany.commerce.commands.MyCompanyControllerCmd.xml file.   Change the profile name from sample to MyCommand_Summary and add the input and output parameters for the rest command.
 
 The following snippet shows the updated code:
<?xml version="1.0" encoding="UTF-8"?>
<command>
     <profiles>
          <profile name="MyCommand_Summary">
               <inputs>
                    <input inputName="field1" methodName="setField1"/>
                    <input inputName="field2" methodName="setField2"/>
               </inputs>
               <outputs>
                    <output methodName="getMyResourceId" outputName="myResourceId"/>
               </outputs>
          </profile>
     </profiles>
</command>

6.Update Handler
  1. In the Enterprise Explorer view, browse to WebSphereCommerceServerExtensionsLogic > src. Click New > Package.
  2. In the Name field, enter com.mycompany.commerce.rest.mycomponent.handler. Click Finish.
  3. Right-click the com.mycompany.commerce.rest.mycomponent.handler package. Click Import > General > File system.
  4. Click Next. Click Browse and browse to your sample code directory. For example, C:\source\workspace\WebSphereCommerceServerExtensionsLogic\src\com\mycompany\commerce\rest\mycomponent\handler. Select the Myresourcehandler.java file. Click Finish to import the file. (The class file is built automatically, so no need to copy it).
  5. Open the Myresourcehandler.java file.
    The following methods are implemented:
    findByMyResourceId
    The REST handler runs the MyResourceDataBean based on the REST input and the corresponding configuration mapping profile MyCompany_Databean_Summary. This method is used to get the resource data from MyResourceDataBean according to the myResourceId you specified. It uses findByMyResourceId as method name, storeId, myResourceId, and responseFormat as parameters, and store/{storeId}/my_resource/{myResourceId} as the path.
    findMyResourceList
    The REST handler runs the MyResourceListDataBean based on the REST input and the corresponding configuration mapping profile MyCompany_DatabeanList_Summary. This method is used to get the list of resource data, such as, 0 to more resource data from MyResourceListDataBean. It uses findMyResourceList as method name, storeId, and responseFormat as parameters, and the path that is defined for this method is store/{storeId}/my_resource/myResourceListDataBean.
    create
    The REST handler runs the MyResourceCreateCmd based on the REST input and the corresponding configuration mapping profile MyCommand_Summary. This method is used to create a new data by a command (POST). It uses create as method name, storeId, and responseFormat as parameters, and store/{storeId}/my_resource as path. It retrieves context parameters from the query and other input parameters from the request body.
    You also can use GET methods to implement queries, specifically find by primary key, find by identifier/name, and find by query. Implement queries by using find by query with internal GET methods. Avoid using GET methods with custom paths as they must be manually created, since they are not generated by the utility.
    initializeQueryRegistry
    This method initializes the new Query registry.
    FindByQuery
    This method is to implement the GET method. It uses findByQuery as method name, storeId as parameter, and store/{storeId}/resource_nameas path, such as /{storeId}/my_resource. It uses the query registry framework to map query names to internal GET methods per the REST API Discoverability.
    findSelf
    The REST handler runs the MyResourceListDataBean based on the REST input and the corresponding configuration mapping profile MyCompany_DatabeanList_Summary. This method is used to get the list of resource data created by the current user. It uses findSelf as method name, storeId as parameter, self as query name, the store/{storeId}/ my_resource?q=self as path.
    For more information about these methods, see the local Swagger UI at the following URL: http://localhost/webapp/wcs/stores/servlet/swagger/index.html.
     
     
  6. Register your new resource handler:
    1. In the Enterprise Explorer view, browse to the REST > WebContent > WEB-INF > config > resources-ext.properties file.
    2. Define the new resource handler that you created:
      # Extended Resources
      com.mycompany.commerce.rest.mycomponent.handler.MyResourceHandler
    3. Save and close the file.
    Next, verify your REST service calls in a web browser.

Friday, September 4, 2015

Get session value from CommandContext in Websphere Commerce

The below code which we can use to get the session information from CommandContext in Websphere Commerce.


HttpServletRequest request =
((com.ibm.commerce.webcontroller.HttpControllerRequestObject) this
.getCommandContext()
.getRequest())
.getHttpRequest();

Session session =request.getSession();

Check Store Flow Feature Enabled/Disabled in Controller Command.

1. The below code which is uses to check the store flow enabled

/**
 * @param storeFlowName Object.
 * @return storeFlowStatusEnabled Object.
 */
public static Boolean isStoreFlowEnabled(String storeFlowName) {
    Boolean storeFlowStatusEnabled = false;
    // Re-Leverage TagHandlerHelper (Flex-Flow Tag Cache, ETC...)
    storeFlowStatusEnabled = TagHandlerHelper.isFeatureEnabled(storeFlowName);
    return storeFlowStatusEnabled;
}

1. The below code which is uses to check the store flow disabled

/**
 * @param storeFlowName Object.
 * @return !(storeFlowStatusEnabled) Object.
 */
public static Boolean isStoreFunctionDisabled(String storeFlowName ) {
    Boolean storeFlowStatusDisabled = false;
    // Re-Leverage TagHandlerHelper (Flex-Flow Tag Cache, ETC...)
    storeFlowStatusDisabled = !(TagHandlerHelper.isFeatureEnabled(storeFlowName ));
    return storeFlowStatusDisabled;

}

ACPLOAD through Query in Websphere Commerce

If you want to run the acpload with query for my custom command. Run the following commands.

The below one is for the resourse group "AllSiteUserCmdResourceGroup".



INSERT INTO ACRESCGRY(ACRESCGRY_ID,RESCLASSNAME)
VALUES ((select coalesce(max(ACRESCGRY_ID),0)+1 from ACRESCGRY ),
'com.mycompany.commerce.context.commands.TestCmd');


INSERT INTO ACRESGPRES(ACRESGRP_ID,ACRESCGRY_ID)
VALUES ((select ACRESGRP_ID from ACRESGRP WHERE  GRPNAME = 'AllSiteUserCmdResourceGroup'),
(SELECT  ACRESCGRY_ID FROM ACRESCGRY WHERE

RESCLASSNAME = 'com.mycompany.commerce.context.commands.TestCmd'));

Saturday, August 29, 2015

Dialog Activity Issue in Websphere Commerce

If we face the Issue When we configure the following dialog activity in wcs.

Birthday Trigger

Customer Places the Order 

Order History

  1. Enable the following marketing listeners: the SensorEventListener and ExperimentEvaluationEventListener. These listeners must be enabled to support some behavioral marketing features and to gather marketing statistics for marketing experiments:
    1. Find the following string in wc-server.xml:
      compClassName="com.ibm.commerce.marketing.dialog.trigger.SensorEventListener"
    2. Below the string, ensure that the enable attribute is set to true, as shown in the following example:
      <component
          compClassName="com.ibm.commerce.marketing.dialog.trigger.SensorEventListener"
          enable="true" name="SensorEventListener">
          <property display="false">
              <start enabled="true"/>
          </property>
      </component>
    3. Find the following string in wc-server.xml:
      compClassName="com.ibm.commerce.marketingcenter.events.runtime.ExperimentEvaluationECEventListenerImpl"
    4. Below the string, ensure that the enable attribute is set to true, as shown in the following example:
      <component
          compClassName="com.ibm.commerce.marketingcenter.events.runtime.ExperimentEvaluationECEventListenerImpl"
          enable="true" name="Experiment Evaluation Event Listener">
          <property display="false">
              <start enabled="true"/>
          </property>
      </component>
  2. Restart the server
  3. Make sure the SendMarketingTriggers scheduler configured in site level.
  4. When you create a dialog activity, please make the all the component available in the activity (Target, trigger,action).

Web services error in WebSphere commerce.

Error:

ConnectionEve A   J2CA0056I: The Connection Manager received a fatal connection error from the Resource Adaptor for resource eis/JCAHTTP-WS.  The exception which was received is java.io.IOException: javax.xml.soap.SOAPException: org.xml.sax.SAXParseException: The root element is required in a well-formed document. Message being parsed:

                at com.ibm.ws.webservices.engine.SOAPPart.getEnvelope(SOAPPart.java:639)


Solution: 


This issue is because of the SOAPAction parameter got missing in the SOAPHeader,So please apply the following fix for solve the issue.


1)      Close your toolkit and stop server
2)      Follow the steps mentioned in the link - http://www-01.ibm.com/support/docview.wss?uid=swg21297330  (install attached APAR)
3)      Make sure you follow the changes step mentioned for change wc-server.xml (adding entry for SOAPAction)
4)      Restart the server and login into admin console
              5)     For the message type – com.mycompany.commerce.services, set the SOAPAction as mentioned                          in the WSDL

Can customer have multiple pending order in Websphere Commerce server

Yes, It can.

In the OrderItemAddCmd, If we are passing the orderId parameter value as "."(dot) in the request , then it will create a new order, if the customer doesn't has any pending order

Or it will add the item to existing pending order.

 And If the orderId parameter value as "**" then it will always create as a new pending order.





Websphere commerce Interview Questions

1.Contoller Command and Task Command differences

2.Organization data model

3.Calculation Framework, How to add new calusage ids

4.Payment model (tables and commands)

Exception details from the WebSphere Commerce search handlers

Problem

There is missing information in the exception details for an invalid langId parameter from the WebSphere Commerce search handlers.
For example, you might receive the following error:
{"errors":[{"errorCode":"CWXFR0230E","errorKey":"ERR_INTERNAL_SERVER_ERROR","errorLevel":"SEVERE","errorMessage":
"CWXFR0230E: Internal server error. Details will be stored within the server logs."}]}

Solution

This error message occurs for an invalid langId parameter from the WebSphere Commerce search handlers.
The error message is a known issue, where it does not indicate specific problems with the parameter, and instead returns an internal server error.
To avoid this issue, ensure that you pass a valid langId value for the WebSphere Commerce search handlers.

Pass custom parameter to OrderItemAddCmd in FEB 8

In FEB 8, They are calling all the controller command as rest. So If you want to pass any custom parameter to the OrderItemAddCmd, we don't need to customize the order facade client. In the previous version we had done that way.

Please follow the steps:

1. The Request parameter mapping for all the rest commands is in this template file "\Stores\WebContent\WEB-INF\config\com.ibm.commerce.order-fep\rest-template-config.xml"

 So please add your custom entry as "x_warrenty."
2.Pass the custom param with the request "warrenty".

3.Then extend the OrderItemAddCmd then do the bussiness logic.

Send Immediate issue for SendMsgCmd in Websphere Commerce Server.

If we are using SendMsgCmd for triggering the email, the email will take 5 minutes delay, Because In WCS has message pool concept.When the SendMsgCmd is getting call it will send the msg into pool then the scheduler command SendTransactedMsg cmd will pick all the messages from Pool then send it to the appropriate account.

For avoiding that delay, We can use sendImmediate() method, but sometime this may cause the issue for thread hung. So if that is happened then we can't move out from the page. for avoid those kind of issue use the below logic.

1. In the SendMsgCmd use sendTransacted() then after that, call the SendTransactedMsg scheduler job immediately  by using the below code.

String strPasswordNotifyName = "PasswordNotify";
            SendMsgCmd cmdSendMsg = (SendMsgCmd)CommandFactory.createCommand("com.ibm.commerce.messaging.commands.SendMsgCmd", getStoreId());
            cmdSendMsg.setMsgType("PasswordNotify");
            cmdSendMsg.setStoreID(getStoreId());
            Messaging ms = new Messaging("PasswordNotify", getStoreId());
            String strMsgSubjectKey = ms.getUserData(null, "subject_key");
            String strSubject = buildMessageSubject(strMsgSubjectKey);
            if(strSubject != null)
                cmdSendMsg.setConfigData("subject", strSubject);
            cmdSendMsg.addMember(getUsersId());
            TypedProperty hshTypedProperty = new TypedProperty();
            hshTypedProperty.put("logonId", getLogonId());
            hshTypedProperty.put("logonPassword", getPassword());
            CommandContext ccc = (CommandContext)getCommandContext().clone();
            cmdSendMsg.compose(null, ccc, hshTypedProperty);
            cmdSendMsg.sendTransacted();
            cmdSendMsg.setCommandContext(ccc);
            cmdSendMsg.setStoreID(ccc.getStoreId());
            cmdSendMsg.execute();
           
            LOGGER.logp(Level.INFO, CLASSNAME, methodName, "Message parameters set for Password Reset email - Add job command being invoked");
            AddJobCmd addJob = (AddJobCmd) CommandFactory.createCommand(AddJobCmd.NAME, getStoreId());
            addJob.setCommandContext(getCommandContext());
            addJob.setPathInfo("SendTransactedMsg");
            addJob.setName("wcsadmin");
            addJob.setStartTime(new Timestamp(System.currentTimeMillis() + 5));
            addJob.setUrl("/");
            addJob.setAccCheck(false);
            addJob.execute();
            LOGGER.logp(Level.INFO, CLASSNAME, methodName, " Add job command being execution complete");