Friday, 1 October 2021

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 in separate file.

*  1. New log file name patter is NewLogFile_%g.log where %g is sequential number starting with 0

*  2. New Log file size max limit is 25MB after that system will rotate log in new file where %g is replaced by next sequence

*  3. From log request/response message all new line, space  and tabs characters are removed

*  4. To enable/disable logging we still use OOB WAS admin console Logs & Trace configuration

*  5. To enable logging for a class in separate file add log level as "com.xyz.XYZClassName=fine"

*     in WAS admin console Logs & Trace configuration

*  6. To disable logging remove above log level from logs configuration in WAS admin console

*  7. Max number of new log files count is 20 as passed in new FileHandler argument

*  8. String.format("[%1$tF %1$tT %1$tZ] ",new Date(record.getMillis())) will format date as [2021-10-01 15:24:26 BST]

*  

* @param logger java.util.logging.Logger lass object obtained like Logger.getLogger(CLASSNAME)

* @param newLogFile: newLogFile = System.getenv("USER_INSTALL_ROOT")+"\\logs\\server1\\NewLogFile_%g.log"

*/

public static void updateLoggerWithCustomHandler(Logger logger,String newLogFile) {


try {

Handler fileHandler = new FileHandler(newLogFile, 25000000, 20,true);

fileHandler.setFormatter(new SimpleFormatter() {

      

      @Override

      public String format(LogRecord record) {

          StringBuilder sb = new StringBuilder();

          sb.append(String.format("[%1$tF %1$tT %1$tZ] ",new Date(record.getMillis())));

          sb.append(String.format("%1$08x",record.getThreadID())).append(" ");

          sb.append(record.getSourceClassName()).append(" ");

          sb.append(record.getSourceMethodName()).append(" ");

          sb.append(record.getMessage().replaceAll("[\\n\\t\\s]", ""));

          sb.append(System.getProperty("line.separator"));

          if (null != record.getThrown()) {

              sb.append("Throwable occurred: ");

              Throwable thrown = record.getThrown();

              PrintWriter printWriter = null;

              try {

                  StringWriter stringWriter = new StringWriter();

                  printWriter = new PrintWriter(stringWriter);

                  thrown.printStackTrace(printWriter);

                  sb.append(stringWriter.toString());

              } finally {

                  if (printWriter != null) {

                      try {

                      printWriter.close();

                      } catch (Exception e) {

                          // ignore

                      }

                  }

              }

          }

          return sb.toString();

      }

      

    });

 

logger.setUseParentHandlers(false);

logger.addHandler(fileHandler);


} catch (IOException e) {

//Error while creating separate log file for OS api logging

}

  }


NOTE: call above defined static method updateLoggerWithCustomHandler  static block on class which requires logger update and logger  object should be fetched as public static class level instance variable like Logger LOGGER = Logger.getLogger(CLASSNAME);

Sunday, 19 September 2021

Docker file syntax

 File name must be " Dockerfile"  without any extension

Dockerfile Content example:


    FROM <Docker_registry>/commerce/ts-web:<source_image_tag>

    RUN  command some command

    RUN command some other

   COPY     /opt/source-code /var/container/folder/source-code

   ENTRYPOINT  {"command","param"]

=== example seep for 10 sec on container start up ==
ENTRYPOINT  ["sleep"]
CMD ["10"]

Docker commands cheat sheet

Docker commands list that can be executed on docker host


1. docker login 

  provide username and password when prompted

2. docker pull dockerImageName   ( here default library or registry name is "library" otherwise use syntax "username/dockerImageName", it pulls image but not run)

3. docker run -it -p 80:3000 -p 8080:3000 -v /opt/my-host-folder: /var/inside/docker/container/folder-name username/dockerImageName

 here  -i attach host input to docker container

          -t attach host terminal to docker container to see output

  -p port mapping host-port:container internal port

  -v volume mapping host-volume-path: container internal volume path

4. docker run -d username/dockerImageName ( run docker in background in detached mode)   

5. docker run -attach username/dockerImageName ( run docker in foreground in attached mode)

6. docker ps -a ( list all container processes running)

7. docker images ( list all docker images on docker host)

8. docker stop  dockercontinerName  ( stop docker container)

9. docker rm dockercontinerName ( delete docker container dockercontinerName or dockerId can be used)

10. docker rmi username/dockerImageName ( delete docker image, make sure first stop any running container of this image)

11. docker inspect dockercontinerName   ( view details of docker container config like ip address port running etc.)

12. docker build Dockerfile -t username/dockerImageName ( build docker with tag as username/dockerImageName)

13. docker push username/dockerImageName ( push docker to public docker hub registry under your user, make sure you are logged in first using docker login command)

14. docker pull username/dockerImageName:source_image_tag

15. docker run --entrypoint command-name username/dockerImageName ( overwrite docker container entry point command at rum time when docker container started)

16.  docker run -e ENV-VAR-NAME=VALUE username/dockerImageName ( export or set environment variable to be passed to docker container at start up)

Note: username above could be docker registry name 

Friday, 12 July 2019

WCS Webactivity not working properly for Customer segments

This problem is related to personalizationID. If
personalizationID is not updated, the activity will treat it as
same user and will be applied. So changing to a new
personalizationID is the solution. A new configuration is
introduced in instance xml. If configured, the new
personalizationID will be created in WC_PERSISTENT cookie when
the user logs off. By default, it is not configured and the
personalizationID will still be the same as original one.

To enable it, need to add "logoffRefresh="true"" element in
instance xml. See the following:
 <PersonalizationId display="false" enable="true"
logoffRefresh="true"/>

Friday, 6 April 2018

Add WCS v8 Search Rest Resource Customization in Search-Rest project


Add custom search profile in wc-rest-resourceconfig.xml for a rest resource

1. Create folder com.ibm.commerce.rest-ext in /Search-Rest/WebContent/WEB-INF/config/
2. Create wc-rest-resourceconfig.xml file in folder com.ibm.commerce.rest-ext
3. Add Resource as below
<ResourceConfig>
    <Resource name="sitecontent">
        <GetUri uri="store/{storeId}/sitecontent/keywordSuggestionsByTerm/{term}"
                description="Get keyword suggestions."
                defaultSearchProfile="true" searchProfile="X_IBM_findNavigationSuggestion_Keywords"/>                       
    </Resource>
</ResourceConfig>

4. Make sure that defaultSearchProfile attribute is set as true if you want to make X_IBM_findNavigationSuggestion_Keywords as default searchProfile for this rest resource
5. If you don't add defaultSearchProfile as true then WCS search will use searchProfile for original rest resource defined in wc-rest-resourceconfig.xml under com.ibm.commerce.rest folder

Tuesday, 10 January 2017

Apache HTTP Server Rewrite Rules Basics

Apache Rewrite Rules Basics:

Note : Please note rewrite rules are evaluated first and then conditions staring from first condition. 

Syntax Example (301 Redirect of a a request to old host to new host):

RewriteCond %{REQUEST_URI} ^/hello1/hello2/*
RewriteCond %{HTTP_HOST} ^([a-z]{2})\.([a-z]+)\.xyz\.com
RewriteRule ^/(hello1)/(hello2)/* http://www.%2.xyz.com/$1/$2 [R=301,L]

# Note: 1 %n (where n could be any numeric from 1 to 9) is backreference notation which contains matched group value in the right hand side of the last RewriteCond part,in above example %2 is value of host which matches regex condition ([a-z]+)
#Note2 : $n (where n could be any numeric from 1 to 9) is backreference notation which contains matched group value in the left hand side of the RewriteRule part,in above example $1 is hello1 and $2 is hello2

List of Specific Characters Set in RewriteCond or RewriteRule :

RewriteCond %{REQUEST_URI} ^/(en|ca|it|fr)\-(us|ca|it|fr)/*
RewriteRule ^/(en|ca|it|fr)\-(us|ca|it|fr)/* http://www.xyz.$2 [R=301,L]

#Note: en-it or en-ca or any combination of above characters list will match the regex condition in RewriteCond and RewriteRule

White List of to allow a specific site access and block remaining:

RewriteCond %{HTTP_HOST} ^www\.xyz\.com
RewriteCond %{REMOTE_ADDR} !^aa.bb.cc.dd$
RewriteCond %{REMOTE_ADDR} !^aa1.bb1.cc1.dd1$
RewriteRule ^/* http://www.abc.com [R=301,L]

#Note: In above rewrite rule any request coming to host www.xyz.com will be redirected to host  http://www.abc.com unless requst is coming from above list public ip addresses aa.bb.cc.dd or aa1.bb1.cc1.dd1

URL Masking or Reverse Proxy:
Accessing a site xyz.com but internally it is serving content from internal site abc.com or in other way redirected to site abc.com however browser host url in will not be changed to abc.com. Example

RewriteCond %{HTTP_HOST} !^www\.xyz\.com
RewriteCond %{REQUEST_URI} ^/proxy$
RewriteRule ^(.*) http://www.abc.com$1 [P,L]

#Note: In above request url www.xyz.com/proxy will be internally redirected to site http://www.abc.com/proxy but in browser address bar we still see url www.xyz.com/proxy. Here config flag [P] is important as this flag is meant for proxy.

Friday, 27 May 2016

Format currency in WCS backend business logic instead of using JSTL tag in jSP



NumberFormat formatter = null;
formatter= NumberFormat.getCurrencyInstance(getCommandContext().getLocale());
               
DecimalFormat df = (DecimalFormat)formatter;
DecimalFormatSymbols dfs = df.getDecimalFormatSymbols();

dfs.setCurrencySymbol(getCurrencySymbol());
df.setDecimalFormatSymbols(dfs);
               
String formattedAmoun= df.format(amount);

Tuesday, 12 April 2016

WCS Web Activity Caching Issue

 If you have whole page cache setup for CategoryDisplay pages or any other pages and one of the eSpots on these pages used for creating web activities and this web activity for content recommendation does work when  you visit the page first time and once it is cached next hit to this page does not display the correct content as per web activity evaluation logic then possible cause could be your cachespec.xml config issue. Make sure that cache-entry for CategoryDisplay cache-id or any other cache-id setup for whole page cache (i.e. consume-subfragments is set to true) below  attributes highlighted in RED colour are excluded from save-attributes= false property list.

<cache-entry>
<class>servlet</class>
<name>com.ibm.commerce.struts.ECActionServlet.class</name>
<property name="consume-subfragments">true</property>
<property name="save-attributes">false
<exclude>jspStoreDir</exclude>
<exclude>javax.servlet.forward.path_info</exclude>
<exclude>requestURIPath</exclude>
<exclude>requestServletPath</exclude>
</property>
              <cache-id>
<component id="" type="pathinfo">
<value>/CategoryDisplay</value>
<required>true</required>
</component>
<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>true</required>
</component>
<component id="categoryId" type="parameter">
<required>true</required>
</component>
<component id="top_category" type="parameter">
<required>false</required>
</component>
<component id="parent_category_rn" type="parameter">
<required>false</required>
</component>
</cache-id>
<cache-entry>


Issue is that if whole page is cached then request to that page will be served directly from dynacache sever and backend controller command will not be executed. In this case WCS marketing engine uses command URL (e.g. CategoryDisplay) to execute the web activity target condition and for this to be executed correctly cached page must persist above mentioned request attributes for each category. This is specially applicable for web activities where target conditions are like customer views a specific category for example brake pads then recommend some content for eSpot.

Monday, 14 March 2016

How to run a .sql file from java process specially if data is huge in the database and jdbc connections time out due to long running query




private  void extractDataInCsv() {

    try {
   
   
    File file = new File(this.getClass().getResource("/com/ibm/commerce/data/OrdersDataExtract.sql").toURI());

       
        Runtime rt = Runtime.getRuntime();
        String  executeSqlCommand= null;
       
        if(getRequestProperties().getBoolean("localDev",false)){
        executeSqlCommand = "db2cmd /c /i /w && db2 -tvf "+file.getAbsolutePath(); // local dev  windows
        }else{
        executeSqlCommand = "db2 -vf "+file.getAbsolutePath();  // linux
        }
       
        Process pr = rt.exec(executeSqlCommand);
       
        BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
    System.out.println(line);
 }
//pause for 15se
Thread.sleep(15000);
       
     } catch (Exception e) {
     e.printStackTrace();
     }
}

Script in OrdersDataExtract.sql is as follows:


connect to dbname user dbusername using password
set schema db2inst1

-- extract data
EXPORT TO /opt/IBM/WebSphere/AppServer/temp/OrdersDataExtract.csv OF DEL MODIFIED BY NOCHARDEL striplzeros decplusblank select with ur
terminate


Friday, 11 March 2016

ShippingModeListDataBean does not return Shipping modes and Charges


If store reference data is all setup correctly and ShippingModeListDataBean still does not return allowed shipping modes and corresponding charges for a store then potential root cause could be that the shipping calcode for all products is not set for in table CATENCALCD.
A row in this table indicates that a CalculationCode is attached to a CatalogEntry. And it is also attached to the CatalogEntry's PRODUCT_ITEM children (or all CatalogEntries) for the specified Store. And also it is attached to TradingAgreement (or all TradingAgreements).

WCS applyCalculation Charges logic looks for indirectly attached calcode for a product and for that it looks into this table. There could also be directly attached calcode for 10% off promotion applied to a specific product then this calcode is attached to product directly.

Wednesday, 24 February 2016

IBM WCS tables used while creating new content as URL Asset

ATCHTGT -- ATTACHMENT TARGET
ATCHTGT (ATCHTGT_ID, STOREENT_ID, MEMBER_ID, IDENTIFIER, ATTACHUSG_ID, FIELD1, FIELD2, FIELD3, FIELD4, OPTCOUNTER)

ATCHAST -- This table holds the asset content url if is it url asset etc.
ATCHAST (ATCHAST_ID, STOREENT_ID, ATCHTGT_ID, ATCHASTPATH, DIRECTORYPATH, MIMETYPE, MIMETYPEENCODING, TIMECREATED, TIMEUPDATED, IMAGE1, IMAGE2, OPTCOUNTER)

COLLATERAL -- This table holds the content name and other info
COLLATERAL (COLLATERAL_ID, STOREENT_ID, COLLTYPE_ID, NAME, URL, FIELD1, FIELD2, OPTCOUNTER, BEHAVIOR)

COLLDESC -- other language dependent data for content
COLLDESC (COLLATERAL_ID, LANGUAGE_ID, LOCATION, MARKETINGTEXT, FIELD1, FIELD2, OPTCOUNTER, LONGMKTGTEXT)

ATCHREL -- This table holds the attachment relation between a business object and an attachment target; OBJECT_ID is same as COLLATERAL_ID
ATCHREL (ATCHREL_ID, OBJECT_ID, ATCHOBJTYP_ID, ATCHTGT_ID, ATCHRLUS_ID, LASTUPDATE, SEQUENCE, BIGINTOBJECT_ID, OPTCOUNTER)

List of IBM WCS tables related with e-marketing activity and asset content

atchast          
atchastlg              
atchrel                    
atchtgt                  
atchtgtdsc            
collateral              
colldesc                
dmactivity            
dmelement              
dmelementnvp        
dmemspotdef      
dmtriglstn              
folderitem

Tuesday, 16 February 2016

Solr Search Index setup for new languages in WCS v7

1.     Add the new supported language in the STORELANG database table for Extended Site Catalog Asset Store (storeId=10051).

2.    Perform the following steps for the following files:
WC_installdir/components/foundation/subcomponents/search/solr/home/template/CatalogEntry/conf/locale
WC_installdir/components/foundation/subcomponents/search/solr/home/template/CatalogEntry/unstructured/conf/locale
WC_installdir/components/foundation/subcomponents/search/solr/home/template/CataloGroup/conf/locale
2.1.   Create a folder for your locale. For example, nl_NL indicates a Dutch language locale for Netherlands.
2.2.  Create the necessary files for your new locale directory.
a.    If language is already included in the existing locale files, copy the files from the original locale directory. For example, fr_FR, to the new directory, fr_NL.
b.    If language is not included in the existing locale files, use the file names and structure from another locale as a sample for its supported structure and organization for example en_GB.
2.3.  Optional: If there are any stop words for the language, create a file, stopwords.txt under the new directory for the schema.xml file. Save your changes and close the file.
2.4.  Copy the schema.xml file under new locale directory created in above step 2.2  file from Search project in SVN repository trunk
CatalogEntry Path: Search/solr/home/MC_10001/en_GB/CatalogEntry/conf/schema.xml
CatalogGroup Path:
Search/solr/home/MC_10001/en_GB /CatalogGroup/conf/schema.xml

3.    Update the following files for customizations if any for a specific project. Latest customized copy of these files can be found in the solrhome (WC_installdir/instances/instance_name/search/solr/home) for each core (e.g.
Search/solr/home/MC_10001/en_GB/CatalogEntry/conf/ wc-data-config.xml)
WC_installdir/components/foundation/subcomponents/search/solr/home/template/CatalogEntry/conf/database/db2/wc-data-config.xml
WC_installdir/components/foundation/subcomponents/search/solr/home/template/CatalogEntry/unstructured/conf/ database/db2/wc-data-config.xml
WC_installdir/components/foundation/subcomponents/search/solr/home/template/CataloGroup/conf/ database/db2/wc-data-config.xml

           
4.    Update the following files for customizations if any for a specific project.
Directory: WC_installdir/components/foundation/samples/dataimport/catalog/db2
Files:   wc-dataimport-preprocess-attribute.xml
wc-dataimport-preprocess-fullbuild.xml
wc-dataimport-preprocess-unstructured-content.xml
Latest customized copy of these files can be found in the solr pre-processConfig directory WC_installdir/instances/instance_name/search/ pre-processConfig)
WC_installdir/components/foundation/subcomponents/search/solr/home/template/CatalogEntry/conf/database/db2/wc-data-config.xml
WC_installdir/components/foundation/subcomponents/search/solr/home/template/CatalogEntry/unstructured/conf/ database/db2/wc-data-config.xml
WC_installdir/components/foundation/subcomponents/search/solr/home/template/CataloGroup/conf/ database/db2/wc-data-config.xml

           
5.    Run the setupSearchIndex utility asper the process provided in HCL commerce documentation
For Local Dev environments need to run below script:
C:\WCDE_ENT70\components\foundation\subcomponents\search\bin>
setupSearchIndex.bat  -masterCatalogId 10001 –setupWebContent false
This script will also update database tables SRCHCONFEXT and SRCHCONF
6.    solr.xml config file will be updated with new locale cores once setupSearchIndex utility executes successfully.
File Location: solrhome (WC_installdir/instances/instance_name/search/solr/home)/MC_10001/solr.xml
7.    wc-search.xml config file will be updated with new locale cores once setupSearchIndex utility executes successfully.
File Location: WC/xml/config/ com.ibm.commerce.catalog-ext/wc-search.xml


8.    Once everything is done we need to run the solr pre-process and build-index scripts for new locales.

Saturday, 29 March 2014

WCS Component Service strusts configuration and invocation Details

1. Component Plugin Configuration in  struts-config-order-services.xml


<plug-in className="com.ibm.commerce.struts.ComponentPlugIn">
 <set-property property="componentId" value="order"/>
  <set-property property="clientFacadeClassName"        value="com.ibm.commerce.order.facade.client.OrderFacadeClient"/>
</plug-in>

2. Struts Action Mapping Configuration:

<action parameter="order.addOrderItem" path="/OrderChangeServiceItemAdd" type="com.ibm.commerce.struts.ComponentServiceAction">
<set-property property="authenticate" value="0:0"/>
<set-property property="https" value="0:1"/>
</action>

3. ComponetServiceAction.java class invokeService(ActionMapping mapping,HttpServletRequest request) method has following code which calls the appropriate method on component client facade

{
RequestHandle handle = (RequestHandle)request.getAttribute("EC_requestHandle");
Map responseMap = ComponentPlugIn.invokeComponentService(handle, inMap, mapping.getParameter());
}

Wednesday, 6 November 2013

Virtual Host Changes for WebServicesRouter Project: Default Port is 8000 which is secure port



HTTPServer plugin-cfg.xml path on app server or httpserver based on environments:
C:\IBM\WAS\profiles\wc_instancename\config\cells\cell_name\nodes\WC_instancename_node\servers\webserver1

Change
1. First open the commerce deployment manager admin console and update the virtual host mapping for WebServicesRouter project from VH_instancename_Tools to VH_instancename.
2. Click on enterprise application link and then click on save configuration link on this page. Don’t check synchronize with node check box and click OK.
3. Now click on nodes under system administration link and then select the appropriate node and click synchronize
4. Check logs , this project should bound to new virtual host group VH_wc_instancename not VH_wc_instancename_Tools

<UriGroup Name="VH_wc_instancename_wc_instancename_Cluster_URIs">
      <Uri AffinityCookie="JSESSIONID" AffinityURLIdentifier="jsessionid" Name="/webapp/wcs/stores/*"/>
      <Uri AffinityCookie="JSESSIONID" AffinityURLIdentifier="jsessionid" Name="/InitializationServlet/*"/>
<!-- added below uri so that webservicerouter project urls like /webapp/wcs/services/   can also be handled by virtual host group VH_wc_instancename-->
<Uri AffinityCookie="JSESSIONID" AffinityURLIdentifier="jsessionid" Name="/webapp/wcs/*"/>
</UriGroup>
<Route ServerCluster="wc_instancename_Cluster" UriGroup="VH_wc_instancename_wc_instancename_Cluster_URIs" VirtualHostGroup="VH_wc_instancename"/>







It can also be achieved through following way:

httpd.conf file path on sefags840:   C:\IBM\WCS\instances\wc_instancename\httpconf

<VirtualHost sefags840.secotools.net:8000>
SSLEnable
SSLClientAuth 0
ServerName sefags840.secotools.net
Alias /wcsstore "C:\IBM\WAS\profiles\wc_instancename\installedApps\WC_wc_instancename_cell\WC_wc_instancename.ear/Stores.war"
Alias /accelerator "C:\IBM\WAS\profiles\wc_instancename\installedApps\WC_wc_instancename_cell\WC_wc_instancename.ear/CommerceAccelerator.war/tools/common/accelerator.html"
Alias /wcs "C:\IBM\WAS\profiles\wc_instancename\installedApps\WC_wc_instancename_cell\WC_wc_instancename.ear/CommerceAccelerator.war"
Alias /wcwkspcadmin "C:\IBM\WAS\profiles\wc_instancename\installedApps\WC_wc_instancename_cell\WC_wc_instancename.ear/WorkspaceAdministration.war"
Alias /workspaceadmin "C:\IBM\WAS\profiles\wc_instancename\installedApps\WC_wc_instancename_cell\WC_wc_instancename.ear/WorkspaceAdministration.war/tools/workspaceadmin/wkspcadmin.html"
</VirtualHost>

Change
Comment out SSLEnable & SSLClientAuth 0 lines in above configuration like this 
#SSLEnable
#SSLClientAuth 0

Thursday, 31 October 2013

WCS Code to find storeId from user LogonId (Expecting that user has registereigd customer role from one store only)

MemberRoleAccessBean m = new MemberRoleAccessBean();
Enumeration mEnum = m.findByMemberIdRoleId(cmdContext.getUserId(),Integer.valueOf("-29"));
Enumeration sEnum = null;
if(mEnum.hasMoreElements()){
   m =(MemberRoleAccessBean)mEnum.nextElement();
   StoreEntityAccessBean stAb = new StoreEntityAccessBean();
   sEnum = stAb.findByMember(Long.valueOf(m.getOrgEntityId()));
   if (sEnum.hasMoreElements()){
   stAb =(StoreEntityAccessBean)sEnum.nextElement();
   storeId = stAb.getStoreEntityId();
}
}

Wednesday, 30 October 2013

WCS developer toolkit , WC.ear deployment files location

Error: SRVE0017W: A WebGroup/Virtual Host to handle localhost:443 has not been defined.

It could be the reason that WC application is not deployed to Websphere Test Server; we can see that in app server admin console enterprise application section if it is installed or not. This sometimes happens when we do add/remove wc project in toolkit.

In WCS developer toolkit , C:\IBM\WCToolkitEE60\wasprofile\config\cells\localhost\applications folder contains the WC.ear file which contains deployment files like deployment.xml, resources.cml and variables.xml

if in above file location applications folder is missing then copy it from backup toolkit.

C:\IBM\WCToolkitEE60\wasprofile\config\cells\localhost\nodes\localhost\serverindex.xml contains wc.ear deployment configuration for app server

serverindex.xml should look like this



<?xml version="1.0" encoding="UTF-8"?>

<serverindex:ServerIndex xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:serverindex="http://www.ibm.com/websphere/appserver/schemas/5.0/serverindex.xmi" xmi:id="ServerIndex_1" hostName="localhost">

<serverEntries xmi:id="ServerEntry_1224144829726" serverName="server1" serverType="APPLICATION_SERVER">

<deployedApplications>WC.ear/deployments/WC</deployedApplications>

<specialEndpoints xmi:id="NamedEndPoint_1224144829726" endPointName="BOOTSTRAP_ADDRESS">

<endPoint xmi:id="EndPoint_1224144829726" host="localhost" port="2809"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144829727" endPointName="SOAP_CONNECTOR_ADDRESS">

<endPoint xmi:id="EndPoint_1224144829727" host="localhost" port="8880"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144829728" endPointName="SAS_SSL_SERVERAUTH_LISTENER_ADDRESS">

<endPoint xmi:id="EndPoint_1224144829728" host="localhost" port="9401"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144829729" endPointName="CSIV2_SSL_SERVERAUTH_LISTENER_ADDRESS">

<endPoint xmi:id="EndPoint_1224144829729" host="localhost" port="9403"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144829730" endPointName="CSIV2_SSL_MUTUALAUTH_LISTENER_ADDRESS">

<endPoint xmi:id="EndPoint_1224144829730" host="localhost" port="9402"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144829731" endPointName="WC_adminhost">

<endPoint xmi:id="EndPoint_1224144829731" host="*" port="9060"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144829732" endPointName="WC_defaulthost">

<endPoint xmi:id="EndPoint_1224144829732" host="*" port="80"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144829733" endPointName="DCS_UNICAST_ADDRESS">

<endPoint xmi:id="EndPoint_1224144829733" host="*" port="9353"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144829734" endPointName="WC_adminhost_secure">

<endPoint xmi:id="EndPoint_1224144829734" host="*" port="9043"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144829735" endPointName="WC_defaulthost_secure">

<endPoint xmi:id="EndPoint_1224144829735" host="*" port="443"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144829736" endPointName="SIB_ENDPOINT_ADDRESS">

<endPoint xmi:id="EndPoint_1224144829736" host="*" port="7276"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144829737" endPointName="SIB_ENDPOINT_SECURE_ADDRESS">

<endPoint xmi:id="EndPoint_1224144829737" host="*" port="7286"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144829738" endPointName="SIB_MQ_ENDPOINT_ADDRESS">

<endPoint xmi:id="EndPoint_1224144829738" host="*" port="5558"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144829739" endPointName="SIB_MQ_ENDPOINT_SECURE_ADDRESS">

<endPoint xmi:id="EndPoint_1224144829739" host="*" port="5578"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144830117" endPointName="ORB_LISTENER_ADDRESS">

<endPoint xmi:id="EndPoint_1224144830117" host="localhost" port="9100"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144901755" endPointName="WC_PORT_1">

<endPoint xmi:id="EndPoint_1224144901755" host="*" port="8000"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144901817" endPointName="WC_PORT_2">

<endPoint xmi:id="EndPoint_1224144901817" host="*" port="8002"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144901880" endPointName="WC_PORT_3">

<endPoint xmi:id="EndPoint_1224144901880" host="*" port="8004"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144901927" endPointName="WC_PORT_4">

<endPoint xmi:id="EndPoint_1224144901927" host="*" port="8006"/>

</specialEndpoints>

<specialEndpoints xmi:id="NamedEndPoint_1224144901958" endPointName="WC_PORT_5">

<endPoint xmi:id="EndPoint_1224144901974" host="*" port="8007"/>

</specialEndpoints>

</serverEntries>

</serverindex:ServerIndex>

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.

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 ...