Saturday, April 20, 2013

ByPassHttpAdapter | XML post to commerce URL

This is a very useful extension when you need to build an extension where if SOAP is not accepted and authToken based authentication is not an option for inbound request.
if you want an external site to post XML into commerce. This would be a good approach.

Sample code and wc-server.xml

public class BypassHttpProgramAdapterImpl extends HttpProgramAdapterImpl implements
HttpAdapter, HttpAdapterFactory {

/*override the method to return a null if bypass condition is true, you can add bypass condition as a custom XML element in wc-server.xml*/
public HttpAdapter createAdapter(HttpServletRequest request, HttpServletResponse  response, TypedProperty param ) {
    //check for extension code.
}


}

<HttpAdapter
      deviceFormatId="-10000"
      deviceFormatType="XmlHttp"
      deviceFormatTypeId="-10000"
      enabled="true"
      factoryClassname="com.custom.programadapter.XXBypassHttpProgramAdapterImpl" name="XML/HTTP">
      <ProgramAdapter>
        <SessionContext ....
          <SessionContextConfig/>
        </SessionContext>
        <Configuration
          supportedCharacterEncoding="ISO8859-1, UTF-8, utf-8"
          supportedContentTypes="text/xml, text/xml; charset=UTF-8, text/xml-SOAP, text/xml; charset=utf-8"
          supportedMessageMappers="WCS.SOAPINTEGRATION, WCS.INTEGRATION" supportedMethods="POST, M-POST"/>
      </ProgramAdapter>
    </HttpAdapter>

Thursday, April 11, 2013

Pros and Cons of Ajax

Ajax Simplified: I have been meaning to put this together, even for my own understanding and pros and cons and the SEO impact of using Ajax.

Pros:
1. Ajax does a great job of not fully loading the page, so refresh smaller areas/faster
2. A lot of fancy things auto complete\Edit in place\ratings\RSS reader and also sorts of gimmicks.
3. On refresh, it does not trigger a HTTP Post as opposed to traditional web apps.
4. Simpler actions makes the over all site faster, things like e.g. Facebook like

Cons:
1. SEO suffers as most crawlers are links based and have limited JS support so if you use fewer URL's to do a lot of actions, this is bad for SEO visibility of the site.
2. User experience, can not navigate to the path on refresh, so this could be bad user experience, if the Ajax is heavily used and you navigate to 3-4 levels and if you need to go back or forward.

Good Example of Ajax implemented site with SEO friendly URLs:  https://github.com/
As you would see here with github, even though it is Ajax, the links are changing which is kind of best of both worlds: https://github.com/karmi/tire
Limitation of the above approach: Only HTML5 supports this feature--History supported browsers (most modern browsers). Push the URL to the browsers and ajax takes care of all the handling.You need to implement If\Else for older browsers and fortunately there is an API available, please find below link

https://github.com/browserstate/history.js

Top 10 Ajax applications in commerce (WCS):  I will fill this soon.

Sunday, March 10, 2013

Transaction timeout error | Long running feeds| New transaction

If you had to run feeds that would take longer than appserver transaction timeout or any process that runs for ever and if you have see the transaction timeout exception as below for any long running processes

0ddf0003a SystemErr     R Caused by: org.omg.CORBA.TRANSACTION_ROLLEDBACK: javax.transaction.TransactionRolledbackException:  ; nested exception is:
      javax.transaction.TransactionRolledbackException: Transaction is ended due to timeout  vmcid: 0x0  minor code: 0  completed: No
0ddf0003a SystemErr     R    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
0ddf0003a SystemErr     R    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:80)


I would not advise this code solution for all scenarios and only after considering all scenarios, If you need to add code to create new transaction and manage your transactions. Find below code example.


Solution: Using new transaction in your code.

int transactionSize=5000; //example transaction size

try{
for (int recordCount=0; recordCount <= recordsFromDB.length; recordCount++)
    TransactionManager.begin();

    //do business logic
    if ( (transactionSize != null) && (recordCount%transactionSize.longValue() == 0) ) {
                TransactionManager.commit();              
    } 

catch (Exception e) {
                TransactionManager.rollback();
                logging(METHOD_NAME, "Exception at performExecute" + e.getMessage());
 }
           
   

Friday, February 8, 2013

Facebook meta tags using commerce JSP

This post goes through an example from commerce JSP to generate, FaceBook meta tags. The code snippet below prints the meta tags for 2 different kinds of commerce product types, Items and Packages. Based on the type of the product, a different commerce data bean is selected.

Thursday, January 31, 2013

Optimistic locking implementation in EJB

If you are using EJB's in WCS and optimistic locking avoids database deadlocks and helps lower locks placed on the database and allows more applications to run concurrently against the database.Optimistic locking is implemented by creating OPTCOUNTER column for each table.

1) Add OPTCOUNTER column in the table and optCounter CMP field with unchecked getter\setter methods option in creating new field in CMP bean.
2) Map the table OPTCOUNTER to the optCounter field as a CMP managed field, I see this step missing for all EJB's currently implemented so I did not add optCounter mapping either for the new EJB.
3) Adding this.initializeOptCounter(new XCustomKey(this.customId))  in ejbCreate method()
4) Adding optimistic locking in DeploymentDescriptor --> Bean tab, by checking the Concurrency Control (Enable Optimistic locking)
 5) Adding triggers for optCounter and also a file to add these.

CREATE or REPLACE TRIGGER perf_xcustom_1 before update ON XCUSTOM for each row
WHEN ((new.optcounter is null) or (new.optcounter = old.optcounter))
begin if (:old.optcounter < 32767) then :new.optcounter := :old.optcounter + 1; else :new.optcounter := 1; end if; END;

From Infocenter explanation for implementing trigger:
For optimistic locking to work properly, every query that updates a database table row must increment the OPTCOUNTER column value, or reset it to 1 when the current value is 32767. The WebSphere Commerce server uses this technique. However, if database table rows are updated by other code or manual procedures that do not update the OPTCOUNTER column values, then the database triggers defined in the WC_installdir/schema/db_type/wcs.perf.trigger.sql (where db_type is the database type (DB2, Oracle)) schema files ensure that the OPTCOUNTER column values are incremented properly.

Reference:
http://pic.dhe.ibm.com/infocenter/wchelp/v7r0m0/topic/com.ibm.commerce.admin.doc/concepts/cpmoptlock.htm

On redirect removing properties from request


Removing parameters from request when redirecting in commerce is an interesting problem and this is not something that needs to be implemented in regular flows.
In the scenario when you have logonId and logonPassword  passed into form post, removing logonId/logonPassword from request properties in perform execute or creating a new request property and setting in command context does not fix the issue.

responseProp.put(ECConstants.EC_VIEWTASKNAME,ECConstants.EC_GENERIC_REDIRECTVIEW);
responseProp.put(ECConstants.EC_REDIRECTURL,"RedirectViewSample");
setResponseProperties(responseProp);

Solution: OverRide setViewInputProperties and remove the properties from request to the redirect view.

   public void setViewInputProperties(TypedProperty reqProperties){
        reqProperties.remove("logonId");
        reqProperties.remove("logonPassword");       
        this.viewReqProperties = reqProperties;
    }

Tuesday, December 4, 2012

Access control for Views

The data load project in V7 makes, it really easy to load the access control changes. This blog explains a sample custom view access policies for guest and registered user and how this can be verified in the database using the query below. Even for guest users to access views, it is required for the view to belong to AllSiteUsersViews policy. If one tries to create a view and  access it, you would get the following error below and -1002 is (generic user). The first time user comes on a site, it would run user as generic user and as soon as it tries to perform any action specific to a user such as add to cart, it is converted to a guest user.

Error without policy:
AccManager isAllowed CMN1501E: User -1002 does not have the authority to perform action "NewView" on resource "com.ibm.commerce.command.HttpForwardViewCommandImpl" for command "null".

view_acpolicies.xml

<!DOCTYPE Policies SYSTEM "../dtd/accesscontrolpolicies.dtd">
<Policies>
<Action Name="GuestView" CommandName="GuestView" />
        <Action Name="RegisteredView" CommandName="RegisteredView" />
   <!-- Guest USERS VIEWS -->
<ActionGroup Name="AllSiteUsersViews" OwnerID="RootOrganization">
<ActionGroupAction Name="GuestView" />
</ActionGroup>

  <!-- REGISTERED USERS VIEWS -->
<ActionGroup Name="RegisteredUserViews" OwnerID="RootOrganization">
<ActionGroupAction Name="RegisteredView" />
  </ActionGroup>

</Policies>
-------------------------------------------------
select * from acpolicy where acactgrp_id in (select acactgrp_id
from acactactgp where acaction_id
in (select ACACTION_ID from ACACTION where ACTION = 'GuestView'))