Thursday, 29 August 2013

How to get CatalogAssetStore storeId in WCS

com.ibm.commerce.common.helpers.StoreUtil.getStorePath(storeId, com.ibm.commerce.server.ECConstants.EC_STRELTYP_CATALOG)
This method returns all the catalog related store IDs in the store path given the current store ID.

Above Util class uses RelationshipJDBCHelperAccessBean().findRelatedStores(storeId, storeRelationshipTypeName) .

This will fetch data from STOREREL database table


Friday, 6 July 2012

WCS Extended Site Model Concepts

Extended Site architecture diagram & solution outline



In WCS Extended site model Multiple stores can exist in a single Stores Web module. If so, the store assets are separated using the following methods:

Storefront Assets

Storefront assets for each store in the Stores Web module are stored in a separate store directory (storedir). For example, all storefront assets for Mystore1.com (for QC 57) are in the Mystore1 directory & all shared storefront assets are in SharedStorefrontAssetStore directory.
Storefront asset includes jsp, html, css, javascript, images & properties files.

Business logic

The store ID is used to select the command implementation for each store, as specified in the command registry.



Struts Mapping
The configurations for actions and forwards for the Extended-Sites model work the same general way as the ConsumerDirect (B2C) or AdvancedB2BDirect (B2B) models, with one important difference.
For the B2C and B2B direct models, actions and forwards will be looked up for the STORE_ID matching the parameter of the Web request. If no entry exists, it defaults to the default "STORE_ID = 0" and performs another lookup.
In the case of Extended-Sites, you also need to consider the StorePath, which is defined by the relationships between the extended site customer facing stores and the asset stores. These are defined in STOREREL. The relevant relationships for Struts are:
 NAME                                     STRELTYP_ID        
com.ibm.commerce.URL            -10         
com.ibm.commerce.view           -11        
The lookups for actions and forwards first check the Extended-site STORE_ID (as passed in from the Web request). If no entry exists it then looks up based on the related STORE_ID's from STOREREL (for example, asset stores), and then reverts to the default STORE_ID = 0, performing another lookup.
Examples of mapping: Same view name but different storeId
Struts forward mapping to display Mystore1.com specific view (e.g. storIed: 10002)
<forward className="com.ibm.commerce.struts.ECActionForward" name="MyStore1CategoryOnlyResultsDisplayView/10002" path="/Snippets/Catalog/CategoryDisplay/MyStore1CategoryOnlyResultsDisplay.jsp"/>
Struts forward mapping to display shared view ,right now it is shared between mystore1.com & mystore2.com (e.g. shared storIed: 10101, STORETYPE is BMP – Hosted B2B storefront asset store)
<forward className="com.ibm.commerce.struts.ECActionForward" name="MyStore1CategoryOnlyResultsDisplayView/10101" path="/Snippets/Catalog/CategoryDisplay/MyStore1CategoryOnlyResultsDisplay.jsp"/>
Commerce Database tables

Commerce Database tables database tables that are used to define the store path & relationship type are:

STRELTYP
The store relationship type defines all the assets that can be shared.

STOREREL
Defines a relationship between an asset store and an Extended Site store in extended site model

STORE
Stores the directory path for hosted as well as storefront asset store

Commonly used JSTL variables in Elite starter store pages

Infocenter Ref:      http://publib.boulder.ibm.com/infocenter/wchelp/v7r0m0/topic/com.ibm.commerce.elite-starterstore.doc/refs/rsmelitejstlvars.htm

Store directory variables

jspStoreDir
Web Asset directory of the shared file directory. This directory can contain common Web file formats such as JSP files, HTML, and images.
storeDir
Web Asset directory of the hosted store. This directory can contain common Web file formats such as JSP files, HTML, and images.


Utility Class

There is a simple utility class we can use to pull all the related store identifiers for a given store relationship type and store identifier, use com.ibm.commerce.common.helpers.StoreUtil.getStorePath(storeId,storePathType ). An array of store identifier values is returned. The index of the array is congruent with the sequence value from the STOREREL table. The way we use that data is up to us, either use all values to find corresponding assets by the foreign key store identifier, or use a specific index from the array based on some conditional rule.

Customized Extended site model where we don’t need separate struts view mapping for each store separated by /storied

Business Requirement:

As a developer we don’t want to create separate entry in struts-config file for each store in case we have different view implementation for different stores. We can still have the same view name & same storeId which is related store storeId(e.g. 10101 )  in the struts config file for all hosted sites in an extended site model of WCS.

Solution:

To implement this functionality we need to extend the OOB BaseAction class & override the execute() method & below is the solution outline & request processing flow of commerce:

 




(1) Extended MyBaseAction class execute() method will first call the OOB BaseAction class execute method which will do all the processing & will return a ActionForward. At this point all the processing has been done by the OOB BaseAction.

(2) Check for the LOOK_UP_AT_HOSTED_STORE property value from store specific WHRConfig.properties file inside the MyBaseAction execute() method. If it is true then execute the logic written in step # 3 otherwise ignore it & return the ActionForward from step #1 to RequestProcessor.

(3) Inside MyBaseAction execute() method we have ActionForward object from step #1 i.e. super class & from this object we will get the relative path of the resource (jsp) which will be returned to the struts RequestProcessor & in turn it will be returned to the browser for display.
In this step we will use the store path concept of the extended site model & will retrieve all the store paths i.e. related stores directory stored in the STOREREL database table.

Now we will check for requested resource in the related stores directory in the sequence maintained in the STOREREL database table in a for loop.Once it finds the requested resource in a store directory then set this path in the ActionForward object which we got from BaseAction & it break the for loop & return the updated ActionForward to the RequestProcessor & remaining things will be taken care by the OOB Request Processor & ECActionServlet classes as usual.

(4) Use this extended MyBaseAction in place of OOB BaseAction in the struts-config file action mapping section for the views shared between more than hosted sites.

In short, if we have same jsp in the store specific directory then it will be displayed to the user & if it is not there in the store specific directory then it will be displayed from the shared/related store directory.


We will get following advantage if we will go with this approach:

1. We can have views name same for all the stores so small size of struts config file, easy to maintain.
2. Since views name are same so need to create separate access control policies
3. No need to change the existing jspf paths in the already existing jsp(s) since those will work as usual unless those are not overridden in the specific store directory.
4. No changes required in the SEO URL since views name are still same.
5. In future it will help us to make changes/add new features in different sites without impacting other existing sites very easily.

Sunday, 6 November 2011

ERROR Message: CMN2007E: There is insufficient inventory to purchase 1 units of the product for catalog entry


CMN2007E
Explanation: This message is issued by the default implementations of inventory related task commands (such as CheckInventoryCmdImpl, UpdateInventoryCmdImpl, and CheckInventoryAvailabilityCmdImpl) when there is insufficient inventory for the quantity of a product required to fulfill an Order.\n\nWhen STORE.ALLOCATIONGOODFOR is zero, the CheckInventoryCmdImpl and UpdateInventoryCmdImpl default task command implementations check the INVENTORY table. Otherwise, the CheckInventoryAvailabilityCmdImpl default task command implementation checks the RECEIPT and ITEMFFMCTR tables.

Saturday, 5 November 2011

Troubleshooting: A file does not exist for a module elemhttp://www.blogger.com/post-create.g?blogID=5097596999502679730ent that has a Uniform Resource Identifier (URI)


When you start the WebSphere Commerce Test Server, you receive an error that states that a file does not exist.
Problem
When starting the WebSphere Test Server after enabling the Management Center feature, a file does not exist error is displayed in the startup logs. For example,
ApplicationMg E   WSVR0100W: An error occurred initializing, WC
org.eclipse.jst.j2ee.commonarchivecore.internal.exception.NoModuleFileException: A file does not exist for module element having uri: WebservicesRouter.war

Solution

To resolve this issue, you need to rebuild the WebServicesRouter  project and republish the test server, as follows:
  1. Open your WebSphere Commerce Developer workspace.
  2. Right-click the WebServicesRouter  project and rebuild it.
  3. Add/Remove the WC project from Test Server.
If it doesn't solve the problem then look out  for you WebServicesRouter project it might be corrupted i.e. no web.xml in WEB-INF file etc. In this case do the following :
1. Close the toolkit i.e. RAD.
2. copy the WebServicesRouter  project from C:\WCToolkit\wc.modules\workspace to C:\WCToolkit\workspace i.e. to you RAD work space.
3. Open RAD start test server and Add/Remove WC project from commerce test server.

Also check  C:\WCToolkitworkspace\WC\.settings\org.eclipse.wst.common.component file for dependent-module mapping i.e. for WebservicesRouter mapping in it.

NOTE:
It might be possible that WebservicesRouter is got corrupted in that case we right click on WebservicesRouter project in RAD and select Restore from Local History options.







Saturday, 24 September 2011

Enabling the attribute dictionary


If you are using an external catalog and loading your data into WebSphere Commerce, you can save time by using the attribute dictionary to load in attributes for your products, instead of creating new attributes for each product in the Management Center. The Catalogs tool only displays shared attributes meaning, you cannot update or add new attributes to the dictionary.

Before you beginDecide if you want to use the attribute dictionary only, or use the attribute dictionary and classic attribute functionality concurrently. Classic attribute functionality includes those attributes not in the attribute dictionary, where each product has it's own attributes.
Procedure
To enable the attribute dictionary and classic attribute functionality concurrently, switch the implementation of ResolveSkuCmd to ResolveSkuAllCmdImpl in CMDREG table:
Open a database command window.
Run the following SQL command: update cmdreg set classname='com.ibm.commerce.catalog.commands.ResolveSkuAllCmdImpl' where interfacename ='com.ibm.commerce.catalog.commands.ResolveSkuCmd';

To enable the attribute dictionary only, switch the implementation of ResolveSkuCmd to ResolveSkuNewCmdImpl in the CMDREG table:
Open a database command window.
Run the following SQL command: update cmdreg set classname='com.ibm.commerce.catalog.commands.ResolveSkuNewCmdImpl' where interfacename ='com.ibm.commerce.catalog.commands.ResolveSkuCmd';

Customize the Catalogs tool to hide the local attribute table to prevent users from using the table to create a new attribute in the legacy table.
Note: To change the ResolveSkuCmd implementation for one store, you create a new row in the CMDREG table with the STOREENT_ID set to the store ID. If you set the STOREENT_ID to "0", the command applies to all the stores. 

Ref: Infocenter : http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center.doc/tasks/tpnenattrdic.htm

Handling a limited length redirect URL

Handling a limited length redirect URL By default, all input parameters to the controller command are propagated to the redirect view command. If there is a limit on the number of characters in the redirect URL, this may cause a problem. An example of when the length may be limited is if the client is using the Internet Explorer browser. For this browser, the URL cannot exceed 2083 bytes. If the URL does exceed this limit,
the URL gets truncated. As such, you can encounter a problem if there are a large number of input parameters, or if you are using encryption, because an encrypted string is typically two to three times longer than a string that is not encrypted. There arethe URL gets truncated. As such, you can encounter a problem if there are a large number of input parameters, or if you are using encryption, because an encrypted string is typically two to three times longer than a string that is not encrypted. There are two approaches for handling a limited length redirect URL: 
1. Override the getViewInputProperties method in the controller command to return only the sets of parameters that are required to be passed to the redirect view command.
2. Use a specified special character in the URL parameters to indicate which parameters can be removed from the input parameter string.To demonstrate each of the preceding approaches, consider the following set of input parameters to the controller command: URL="MyView";
// All of the following are inputs to the original controller command. 
ip1="ipv1";
ip2="ipv2";
ip3="ipv3";
iq1="iqv1";
iq2="iqv2";
ir1="ipr1";
ir2="ipr2";
is="isv";
If you are overriding the getViewInputProperties method, the new method can be written so that only the following parameters are passed to the view command: ir2="ipr2"; is="isv"; Using the second approach, the view command can be invoked using special parameters to indicate that certain input parameters should be removed. For example, you can achieve the same result by specifying the following as the URL parameter: URL="MyView?ip*=&iq*=&ir1=" This URL parameter instructs the WebSphere Commerce run-time framework of the following: 
 The ip*= specification means that all parameters whose names start with ip should be removed.
The iq*= specification means that all parameters whose names start with iq should be removed. 
The ir1= specification means that the ir1 parameter should be removed.

Creating System Generated primary keys in WCS Entity Beans

Creating primary keys: The ejbCreate method is used to instantiate new instances of an entity bean. This method is automatically generated but the generated method only includes logic to initialize primary keys to a static value. You may need to ensure that the primary key is a new, unique value. In this case, you may have an ejbCreate method similar to the following code snippet:

public void ejbCreate(int argMyOtherValue) throws javax.ejb.CreateException {
//Initialize CMP fields MyKeyValue = com.ibm.commerce.key.ECKeyManager. singleton().getNextKey("table_name"); 
MyOtherValue = argMyOtherValue; 
}
In the preceding code snippet, the getNextKey method generates a unique integer for the primary key. The table_name input parameter for the method must be an exact match to the TABLENAME value that is defined in the KEYS table. Be certain to match the characters and case exactly.

In addition to including the preceding code in your ejbCreate method, you must also create an entry in the KEYS table. The following is an example SQL statement to make the entry in the KEYS table: insert into KEYS (TABLENAME, COUNTER, KEYS_ID) values ("table_name", 0, 1) Note that with the preceding SQL statement default values for the other columns in the KEYS table are accepted. The value for COUNTER indicates the value at which the count should start. The value for KEYS_ID should be any positive value. If your primary key is defined as a long data type (BIGINT for DB2 or NUMBER(38, 0) for Oracle), use the getNextKeyAsLong method.

How to customize java.util.logging.Logger class to write logs in separate file than System.out.log in Websphere commerce/ HCL commerce)

/** * This method updated the passed in java.util.logging.Logger object with * custom file handler to write logs data form that class ...