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);

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