Monday, October 28, 2013

Enabling SOLR search engine for Madisons Store

Enabling SOLR search engine for Madisons Store





I have been working on this article for some time and had to face multiple issues, here are some steps if you want to get going and explore WCS Search (Apache SOLR) which was introduced in FEP1, I have tested this with Feature Pack 4 installation.

You may follow these steps to enable SOLR for Madisons sample store which has been published as a standalone B2C store, you can do the same with Madisons extended sites store as well.
Step 1

Enable Search feature by following instruction from this link
I happened to enable features while upgrading my toolkit to Feature pack 3 and hence did not follow these steps.

You can Enable Store enhacements by using following command
c:\IBM\WCDE_ENT70\bin>enableFeature.bat -DfeatureName=store-enhancements
Ensure you are able to view following output from the URL, this is an indication of successful enablement of SOLR search engine, SOLR engine will initialize the very first time you hit this url, this can be noticed in application server log.

https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2GRC8PXXcijzu5gg3aiHfX1UnUdb6De6ZSK8FirTfbpqJ_1fK_ggMzR18EJOBTRbp7rPtpUH5wdSAV80LO3MCcVfqqFol_ZmRgPji-PFoBUO3Yg3hPr8LdNNSlJnwXt85HwhA_ucFh2uM/s640/solr.png




Step 2
Publish the started store included in feature pack to test advanced functionality, for instance Madisons ConsumerDirect Store can be used for testing new features.

2. 1 Publish Madisons Store Archive
Depending on your feature pack version you need to publish the Madisons store in following sequence


For Feature Pack 1 name for the store is Madisons.sar
For Feature Pack 2 and above the store is Madisons-FEP.sar

Publish as shows in the screenshot below
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-xkrITtaIVGFwMFFTqIeJbpyJtrf_RJexRwbyqZjuTIgypxEbynLTFUVwoMHW_YGO8VX7feZVkd3pdxctN6gTU5zDaRZ1hv_-3sIcU83ZL7fZQe8bMM2Hwi-zUHbGdsx0ajgg6tZOZj3g/s640/Madisons1.png

https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi285gFlJLfOPs8FO1BJxKk0jpJydwuvLJyiKqkQeRtaci_ZdkPYm5Jdc4ypq7s9Oht2gGX9lxH8II__mJ1OSBgU02fFjHtA7PnfLm1Q0Kc1Du70o9K3darjjzhCjLwJEJ5v-BHTiWYPwbp/s640/Madisons2.png






















2. 2 Publish MadisonsEnhancements Store Archive
In this sample I have published Madisons-FEP.sar as a normal store (not an extended sites store), hence while publishing MadisonsEnhancements SAR file I have selected 
Marketing Store Identifier, catalog and customer facing store identifier as "Madisons-FEP" as shown in the screen shot below.

https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj2tZ3tuP_JStipQeMx7gB33QJDcXVmJSBple2cgZ1jgU343iRoOt2P1gSIL3avFNmbyp6JF6BX-FGa1BLt06jFFZ90SOZUC6M5OsnOErL2VO3DnKNMeMaYu_NY7KL-VZMvqZH7WIIwynq/s640/store_selection.png




















Login to CMC to validate search functionality is visible for the new Store.
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGSEwY6WOm7bYZxOBTCssIuXbDIuQPkBaZVBBvaB42rBruX-yvAiKo5Ji7kDRQvdvjT84Wyvto1SAl7rd6nqSaJ9A1SzYvnvHMf73aRZ3skceqXwySsJGl1b9usETDFqRWtpM-LIucH1DY/s640/cmc_after.png























Now validate search functionality for the new store.
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEV3HsvcBpkU_4dMoL78UKtarN24NKyzxMjzQbOg6tjtg6neam2N79ZzXsQntwDU6m6clv0JBinT7pXLxVyHULEqA8vrnInCDKbC8IN-IxsWII-16vehhtliS9X1bQJqSOouiscUqjxIxj/s640/Madisons3.png



















Optional Steps
I have noticed that the store publish process in previous step will accomplish Step 3, 4 and 5, hence skip these steps is SOLR index was setup in previous step. 

You should notice something similar in store publish logs in Step 2

[5/13/12 20:13:21:447 CDT] 000001dd task          I com.ibm.commerce.search.indexsetup.execution.task.ConfigWCforSolrCatalogEntrySayHelloTask performExecute

**************************************************************
Started configuring WebSphere Commerce for Solr cores
**************************************************************
Master Catalog Id: 10351
Index Type: CatalogEntry
Languages: [en_US]
Step 3

3. 1 Retrieve Master catalog ID
-- For normal store (not an extended sites store)
select * from catalog where IDENTIFIER='MadisonsFEP';

-- For extended sites store
select * from storeent where IDENTIFIER='MadisonsFEP';
--Use the storeent_id as the store_id in the following SQL to find the Catalog Asset store ID of this Extended Site store
select * from storerel where store_id=11001 and streltyp_id=-4 and relatedstore_id not in (11001);
-Get the master catalog ID
select * from storecat where storeent_id=YYYYYY and mastercatalog='1'


https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ6p6TXC3j67iB-POq0yaTq8BYeBqXF27WpnKW5tN2GT4UHW7tOrkMJ6PJVln0VIVUJ4-mCMu9gOEUThbjKdJlbgXGfF0n-lb2-NEI_q4dJ1RlWaZ_fPWHIZ9wNnPJ9Jh5SDq08woPiUl2/s640/storeid.png


3. 2 Stop the test server if it is running


Step 4
Setting up the WebSphere Commerce search index structure for a specific master catalog locally

C:\IBM\WCDE_ENT70\components\foundation\subcomponents\search\bin\setupSearchIndex.bat -masterCatalogId 10001


C:\IBM\WCDE_ENT70\components\foundation\subcomponents\search\log\wc-search-index-setup.log
Should create pre-process XML in C:\IBM\WCDE_ENT70\search\pre-processConfig\MC_10001\Cloudscape


Step 5
Preprocessing the WebSphere Commerce search index data

c:\IBM\WCDE_ENT70\bin>di-preprocess.bat C:\IBM\WCDE_ENT70\search\pre-processConfig\MC_10001\Cloudscape

review C:\IBM\WCDE_ENT70\logs\wc-dataimport-preprocess.log
you should see following message towards the end of log file


Program exiting with exit code: 0.
Data import pre-processing completed successfully with no errors.



Step 6
Build Search Index

Restart the WebSphere Commerce search server after preprocessing is complete
and hit following URL from browser


Ensure you can visit SOLR over http by checking following URL in your browser

Start the test server, this time around you would notice lot of logging related to SOLR search engine in your start up log

[12/16/11 11:41:27:935 CST] 00000011 SolrResourceL I org.apache.solr.core.SolrResourceLoader locateSolrHome No /solr/home in JNDI
[12/16/11 11:41:27:937 CST] 00000011 SolrResourceL I org.apache.solr.core.SolrResourceLoader locateSolrHome using system property solr.solr.home: C:/IBM/WCDE_E~1/search/solr/home
[12/16/11 11:41:27:938 CST] 00000011 SolrResourceL I org.apache.solr.core.SolrResourceLoader <init> Solr home set to 'C:\IBM\WCDE_E~1/search/solr/home\'
[12/16/11 11:41:28:045 CST] 00000011 CoreContainer I org.apache.solr.core.CoreContainer load loading shared library: C:\IBM\WCDE_E~1\search\solr\home\lib
[12/16/11 11:41:28:078 CST] 00000011 SolrResourceL I org.apache.solr.core.SolrResourceLoader <init> Solr home set to 'C:\IBM\WCDE_E~1\search\solr\home\default\'
[12/16/11 11:41:28:119 CST] 00000011 SolrConfig    I org.apache.solr.core.SolrConfig initLibs Adding specified lib dirs to ClassLoader
[12/16/11 11:41:28:622 CST] 00000011 Config        I org.apache.solr.core.SolrConfig <init> Loaded SolrConfig: solrconfig.xml
[12/16/11 11:41:28:631 CST] 00000011 IndexSchema   I org.apache.solr.schema.IndexSchema readSchema Reading Solr Schema
[12/16/11 11:41:28:651 CST] 00000011 IndexSchema   I org.apache.solr.schema.IndexSchema readSchema Schema name=example

[12/16/11 11:41:32:055 CST] 00000011 SolrResourceL I org.apache.solr.core.SolrResourceLoader <init> Solr home set to 'C:\IBM\WCDE_E~1\search\solr\home\MC_10051\en_US\CatalogEntry\'
[12/16/11 11:41:32:199 CST] 00000011 SolrConfig    I org.apache.solr.core.SolrConfig initLibs Adding specified lib dirs to ClassLoader

di-buildindex.bat -masterCatalogId masterCatalogId

c:\IBM\WCDE_ENT70\bin>di-buildindex.bat -masterCatalogId 10001

You should notice something similar at the end of this command execution..


May 11, 2012 8:33:43 PM com.ibm.commerce.foundation.dataimport.process.DataImpor
tProcessorMain logExitCode
INFO:

-----------------------------------------------

May 11, 2012 8:33:43 PM com.ibm.commerce.foundation.dataimport.process.DataImpor
tProcessorMain logExitCode(int)
INFO:
Program exiting with exit code: 0.
Data import process completed successfully with no errors.

May 11, 2012 8:33:43 PM com.ibm.commerce.foundation.dataimport.process.DataImpor
tProcessorMain logExitCode
INFO:
-----------------------------------------------


May 11, 2012 8:33:43 PM com.ibm.commerce.foundation.dataimport.process.DataImpor
tProcessorMain logEndDateAndTime
INFO: Data import process ended:Fri May 11 20:33:43 CDT 2012
May 11, 2012 8:33:43 PM com.ibm.commerce.foundation.dataimport.process.DataImpor
tProcessorMain logEndDateAndTime
INFO: Data import process completed in 81.565 seconds.


Reference Links

Setting up WebSphere Commerce search

WebSphere commerce search in starter stores


Tutorial : E-mail Templates & Custom Placeholders


E-mail templates define the structure and content of marketing e-mails that you send to customers using an e-mail or dialog activity. 
E-mail templates can contain placeholders for content, such as e-Marketing Spots, links, unique promotion codes, and the customer's first and last name. When it is time to deliver the e-mail, the server replaces the placeholders with actual content.


While using the email templates , we may be faced with providing custom placeholders , as per the client requirements.

Below are the steps to do so. For demonstration purposes , we would be introducing the customer's phone number as a custom placeholder attribute.

1. Customize the Management Center Open-laszlo files to include the new custom tag for your new custom attribute.

 File
/LOBTools/WebContent/WEB-INF/src/lzx/commerce/marketing/restricted/widgets/EmailTemplateRichTextEditor.lzx

Step 1: Modify the  open lazlo file to introduce "Customer Phone Number" in the selection dropdown.

1. Locate the text "<mktTextlistitem value="lastName" displayName="${mktMarketingResources['lastName'].string}"/>"

2. Add the below text in the next line
<mktTextlistitem value="phoneNumber" displayName="Customer Phone Number"/>

The completed code will look as follows :

https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8Ff5H9oTbsSdRzscBrFDkHzenaRCmpCwCDksfoFTwUbrk5BfvHK1L98ECXJCZut9Wx9jXctZWpOcmTJSgw7D-tCvdFhqQNpmOnjldQQiNNSX0c8gPk5aLKmoEW8_9OQtKEbAjHsmD2piY/s640/Fig1.PNG

Step 2: Modify the  on-click handler to insert the custom tag <e-mail:PhoneNumber /> in the editor when the user selects "Customer Phone Number" and clicks on "Insert"

1. Locate the text "<handler name="onclick">"

2. Add the below text in the function implementation
  else if(selected == "phoneNumber") {
     classroot.insertTextAtSelection("<e-mail:PhoneNumber />");
   }

The completed code will look as follows :

https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivXaoXIdGm8HBQcZYJQpRrYxkWWssXzQkbRJQbZKGBCo0TmW6NRdTtBd9je8c8KaDWorzZl5oR5q8etEO1fpbCbkLGQoUjT5GPHCW6qp2Uu_UUodRHzoLeWpzK05aDE8HeZrxJBfDsaFK7/s640/Fig2.PNG
Step 3: Build the Open Lazlo project - LOBTools
Right Click "LOBTools" project and click on "Build OpenLaszlo Project" as show in the figure below. Restart server.
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghq53tTS2xvOMoLIDPoJIwks_EBtOoe3eLXiGvy3BxqdPpn6PeeJxy-2f5z01XBkmiijgWa_j561_1zkZmZaWkdGd-QdVwNRoQaS5ewgYqawejv3FcW6APEHTmZZ0Xsoiw9gVLXbTZ8GEe/s320/Fig3.png.

This concludes the Management Center customizations.

https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6oKV3YEUbVVmU4TIxuwVyrr0vmRRh90x9p_KXb0IebtM06RIe14MrNDZYTph443RHDDW6vClL18T9Da906QSTWOVMSVT-Pb25x9LE_ooFr_o6WJnItV3qqJFmia9EvFEgNI5q6Qyy0XIg/s640/Figure4.PNG  
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqjFp6MaJBKZ04epMEYO0HIB1s2Qhu8Gqz-1D9tKxJGv_dawGEMr1556gt_NxogfZVbt8IHzFaxZxO8x73Q_bCxHNT2Fdn2PhEq_Yv6ikPYPEPf4Pk7SGqrajoTXdFoneFw2vyhCPCI-3K/s640/Fig5.png



2. Introduce a Tag implementation class

1. Create a tag implementation class which would contain the logic to replace the placeholder tag <e-mail:PhoneNumber /> with actual content.

This class should implement the "com.ibm.commerce.emarketing.emailtemplate.tag.Tag" interface. Follow the link to understand the interface methods which need to be implemented.

For the pupose of this tutorial , let the fully qualified name of this class be :

'com.wcshub.commerce.emarketing.emailtemplate.tag.TagPhoneNumber'  

2. Make an database entry in the table TAGCLASS.
To more about this table , follow the Infocenter link.  The sample query is provided below:

 insert into tagclass values ('PhoneNumber',  'com.wcshub.commerce.emarketing.emailtemplate.tag.TagPhoneNumber' ,  'Implementation class for Phone Number Tag' , NULL  );

The tutorial is now complete. Test the customizations.


WebSphere Commerce Search Cookbook

WebSphere Commerce Search Cookbook


Below link covers the explanation on various common customization for WCS Search

https://www.ibm.com/developerworks/community/blogs/CommerceSearch/?lang=en
Good reference place for SOLR issues and solutions

Thursday, October 24, 2013

Some Basics on Order subsystem


In IBM WCS both cart and orders are managed in the same table for a user, a cart transitions through various states and this is used to identify the cart state.
For example a pending order would have orders.state as "P", while a submitted order will have ORDERS.state as "M"

Review following link for more information on Order state transition

In general checkout flow supports both AJAX and non AJAX version of server side processing, review AJAX URL's defined in following OOB Struts configuration files for supported AJAX actions
/Stores.war/WEB-INF/struts-config-order-services.xml has all the AJAX versions of the command defined in it.

1. Add to Cart: User is browsing the site as anonymous, guest or authenticated user and adds an item from browse pages to cart

You can call the OOB non AJAX version "/OrderChangeServiceItemAdd" which is mapped as follows in struts-config

<action parameter="com.ibm.commerce.orderitems.commands.OrderItemAddCmd" path="/OrderChangeServiceItemAdd" type="com.ibm.commerce.struts.BaseAction">
</action>
If you want to use AJAX version use "/AjaxOrderChangeServiceItemAdd" command

<action parameter="order.addOrderItem" path="/AjaxOrderChangeServiceItemAdd" type="com.ibm.commerce.struts.AjaxComponentServiceAction">
</action>
Refer following link for various AJAX actions supported by this Fascade
http://publib.boulder.ibm.com/infocenter/wchelp/v7r0m0/topic/com.ibm.commerce.madisons-starterstore.doc/refs/rsmmadisonorderservices.htm

Both AJAX and non AJAX finally make use of following implementation This uses following OOB controller command
com.ibm.commerce.orderitems.commands.OrderItemAddCmdImpl
 - Extends com.ibm.commerce.orderitems.commands.OrderItemBaseCmdImpl

Any customization would require extension of OOB OrderItemAddCmdImpl

2. View Cart: User clicks on View Cart Page

At this step you want to display guest the cart content with list of order items with pending order status

You can use following OOB Struts action url "/OrderItemDisplay"
<action
    parameter="com.ibm.commerce.orderitems.commands.OrderItemDisplayCmd"
    path="/OrderItemDisplay" type="com.ibm.commerce.struts.BaseAction">
    <set-property property="https" value="0:1"/>
    <set-property property="authenticate" value="0:0"/>
</action>
Review following link for more details on optional and mandatory input parameters for this URL
http://publib.boulder.ibm.com/infocenter/wchelp/v7r0m0/topic/com.ibm.commerce.developer.doc/refs/rosorderitemdisplay.htm

This action internally makes use of following OOB controller command      
com.ibm.commerce.orderitems.commands.OrderItemDisplayCmdImpl
Control the various calculations that needs to be performed before you display the Cart Page
E.g by passing following in URL calculationUsageId=-1&calculationUsageId=-2&calculationUsageId=-7 you are triggering calculation of Tax, discount, Shipping

Any customization would require extension of OOB OrderItemDisplayCmdImpl

3. Shipping Page: User clicks on checkout and is navigated to shipping page

        <action
            parameter="com.ibm.commerce.orderitems.commands.OrderItemUpdateCmd"
            path="/OrderItemUpdate" type="com.ibm.commerce.struts.BaseAction">
            <set-property property="https" value="0:1"/>
            <set-property property="authenticate" value="0:0"/>
        </action>
     
http://publib.boulder.ibm.com/infocenter/wchelp/v7r0m0/topic/com.ibm.commerce.developer.doc/refs/rosorderitemupdate.htm

This action used following OOB command com.ibm.commerce.orderitems.commands.OrderItemUpdateCmdImpl

4. Payments Page: User navigates to payments page

This flow typically includes adding single/multiple payment information to an order, once the payment information is submitted
we can use following command for processing before forwarding user to review order screen

The OOB /OrderProcess should be used for this purpose,
it is implemented by following OOB command com.ibm.commerce.order.commands.OrderPrepareCmdImpl

Pass appropriate payment parameters to add the payment information entered to an Order.
http://publib.boulder.ibm.com/infocenter/wchelp/v7r0m0/topic/com.ibm.commerce.developer.doc/refs/rosorderprocess.htm


5. Review Order User navigates to review order page and submits order
The OOB /OrderProcess should be used for final Order submission, as mentioned in previous step this URL
implements OOB com.ibm.commerce.order.commands.OrderProcessCmdImpl command.

6. Submit Order: Order Submission and post processing

Once an Order is submitted OrderProcessCmdImpl Calls RaiseOrderEventCmd to raise ORDER_SUBMISSION_EVENT
com.ibm.commerce.order.event.RaiseOrderSubmitEventCmd

any customization to this command would require extension of
com.ibm.commerce.order.event.RaiseOrderSubmitEventCmdImpl command which is the default implementation.

com.ibm.commerce.order.event.ProcessOrderSubmitEventCmdImpl which is default implementation of OOB
com.ibm.commerce.order.event.ProcessOrderSubmitEventCmd listens to ORDER_SUBMISSION_EVENT and takes care
of transferring the order to the external system.

This is the appropriate command for customization If you need any customization in Order XML which is posted to external system