Saturday 21 July 2012

Error Codes - Some of the frequently issues




1. 403 - Cannot Serve URLs with character in them


The HTMLServlet and the FileFinderServlet servlets in the request handling servlet pipeline check for the characters '..' and 'null'. If these appear in the URL the "Cannot serve URLs" error message is shown.


These characters are hard coded in the source and cannot be parametrized.


Source Code Snippet: - FileFinderPipelineServlet


 if(pPathInfo.indexOf("..") != -1)
                {
                    sendError(pResponse, 403, "Cannot serve URLs with ..'s in them");
                    return false;
                }
                if(pPathInfo.indexOf('\0') != -1)
                {
                    sendError(pResponse, 403, "Cannot serve URLs with nulls in them");
                    return false;
                }


2. 404 Error Pages Rendered From web.xml Definition Not Multisite Aware 


A 404 error-page was added to the application's web.xml  file
<error-page> 
    <error-code>404</error-code> 
    <location>/error.jsp</location>
</error-page>


However, the request does not appear to be processed by the pipleline, as none of the site formatting or branding for Multisite is being displayed with the 404 error.jsp


The 404 exceptions are handled via the Application Server (ie WebLogic, JBoss, WebShpere). If the web.xml file does not include instructions for how the Applications Servers, Dispatcher should handle ERRORs, the Application Server will not forward the Request to the PageFilter servlet -> DynamoHandler -> SiteContextPipelineServlet , and on down the pipeline. Hence, none of the Formatting/Branding handled by Multisite and the SiteContextPipelineServlet are triggered.


We need to abide to the pattern followed in CRS web.xml when we define the error pages for error codes:


1. Define the filters
<filter>
    <filter-name>PageFilter</filter-name>
    <filter-class>atg.filter.dspjsp.PageFilter</filter-class>
 </filter>
 <filter>
    <filter-name>ErrorFilter</filter-name>
    <filter-class>atg.servlet.ErrorFilter</filter-class>
  </filter>


2. Define the filter mappings
 <filter-mapping>
    <filter-name>ErrorFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>ERROR</dispatcher>
  </filter-mapping>
  <filter-mapping>
    <filter-name>PageFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>ERROR</dispatcher>
    <dispatcher>FORWARD</dispatcher>
  </filter-mapping>


3. Include all the error page elements
 <error-page>
    <error-code>404</error-code>
    <location>/global/pageNotFound.jsp</location>
  </error-page>
  <error-page>
    <error-code>500</error-code>
    <location>/global/serverError.jsp</location>
  </error-page>

Thursday 19 July 2012

AccessControlServlet and Profile's SecurityStatus


We normally use Profile.transient property to determine if a user is loggedIn. The method is not secure as users that have been logged in automatically have transient property set to false. You should check the profile's security status before displaying secured data such as user's profile or credit card information.


The securityStatus property of the Profile component is used to indicate the type of verification the user has passed through. When a user logs in (or is automatically logged in), the Personalization module sets the value of this property to an integer that indicates the login method used. This can be used to have a tiered login structure where a user can be automatically logged in but they must enter in their login credentials before being able to view certain information such as their address, order history, or credit card information.


The securityStatus property is set according to this table: 
  


Value

Login Method Used

0

Anonymous login

1

Auto-login by URL parameter

2

Auto-login by cookie

3

Login by http-(basic-authentication)

4

Explicit login or registration in the Personalization module via form handler

5

Explicit login or registration in the Personalization module via form handler underhttps protocol.

6

Certificate (not supported by ATG at this time).


AccessControlServlet 

This servlet checks the requestURI to see if it matches any of the requestedURLs identified in it's accessController map. The accessControllermap is made up of URLs matched to an AccessController instance that governs the rules to determine when a URL is requested whether the active Profile is permitted to view the page. When access is denied by an AccessController it calls the AccessControllerServlet which 
redirects the user to the URL in the deniedAccessURL.


Example of instance of AccessController that is invoked when the URL requested is present in the accessController map. allowAccess method uses the Profile's security Status



public boolean allowAccess(Profile pProfile, DynamoHttpServletRequest pRequest){
boolean isLoggedIn = false;
try {
Integer securityStatus = getProfileTools().getSecurityStatus(pProfile);
if(securityStatus >= getProfileTools().getPropertyManager().getSecurityStatusLogin()){
isLoggedIn = true;
}
} catch (PropertyNotFoundException propExc) {
if(isLoggingError()){
logError("PropertyNotFoundException", propExc);
}
}
return isLoggedIn;
}

public String getDeniedAccessURL(Profile pProfile){
DynamoHttpServletRequest dynamoRequest = ServletUtil.getCurrentRequest();
String requestURI = ServletUtil.getCurrentRequestURI(dynamoRequest);
StringBuffer requestURL = new StringBuffer();
if(!StringUtils.isBlank(requestURI)){
requestURL.append(requestURI);
}
String queryString = dynamoRequest.getQueryString();
if(!StringUtils.isBlank(queryString)){
StringBuffer modifiedQueryString = new StringBuffer();
String[] queryStringTokens = StringUtils.splitStringAtString(queryString, "&");
if(queryStringTokens!=null && queryStringTokens.length > 0){
StringTokenizer queryParamAndValue = null;
String paramName = "";
int maxCount = queryStringTokens.length;
for(int i=0;i<maxCount;i++){
queryParamAndValue = new StringTokenizer(queryStringTokens[i],"=");
if(queryParamAndValue.hasMoreTokens()){
paramName = queryParamAndValue.nextToken();
}
if(!"_Dargs".equalsIgnoreCase(paramName)){
if(i<maxCount){
modifiedQueryString.append(queryStringTokens[i]+"&");
}else{
modifiedQueryString.append(queryStringTokens[i]);
}
}
}
}
queryString = modifiedQueryString.toString();
requestURI = requestURL.append("&").append(queryString).toString();
}
return requestURI;
}


Updating Orders in Commerce Code

When you are using the Order object with synchronization and transactions, there is a specific usage pattern that is critical to follow. Not following the expected pattern can lead to unnecessary ConcurrentUpdateExceptions, InvalidVersionExceptions and deadlocks. The following sequence must be strictly adhered to:

1. Obtain local lock on profile id
2. Begin transaction
3.Synchronize on order
4.Perform all modifications to the order object
5.Call OrderManager.updateOrder
6.End Synchronization
7.End Transaction
8.Release local lock on profile id

Steps 1,2,7 and 8 are done for you in beforeSet and afterSet methods for ATG form handlers where order updates are expected. These include formhandlers that extend PurchaseProcessFormHandler.

If you write a custom code updating an order outside of PurchaseProcessFormHandler (Eg: coupon. droplet, pipeline servlet) etc you code should acquire the lock before updating the order.

The following code snippet is an example to load cookied order and depicts the pattern that is useful to prevent ConcurrentUpdateExceptions, InvalidVersionExceptions and dead locks when multiple threads attempt to update the same order on the same ATG instance.



public void service(DynamoHttpServletRequest request,
DynamoHttpServletResponse response) throws IOException,
ServletException {

ClientLockManager lockManager = getLocalLockManager(); // Should be configured as /atg/commerce/order/LocalLockManager
Profile profile = (Profile)request.resolveName("/atg/userprofiling/Profile");
boolean acquireLock = false;
try
{
 acquireLock = !lockManager.hasWriteLock( profile.getRepositoryId(), Thread.currentThread() );
 if ( acquireLock )
 lockManager.acquireWriteLock( profile.getRepositoryId(), Thread.currentThread() );
 TransactionDemarcation td = new TransactionDemarcation();
 td.begin( getTransactionManager(),TransactionDemarcation.REQUIRES_NEW );
 boolean shouldRollback = false;
 try
 {
 String cookieOrderId =getCookieManager().getCookie("orderIdCookie",request);
Order order = (Order)getOrderManager().loadOrder(cookieOrderId);
OrderHolder orderHolder = (OrderHolder)request.resolveName("/atg/commerce/ShoppingCart");
synchronized (order) {
orderHolder.setCurrent(order);
order.setProfileId(profile.getRepositoryId());
CommerceProfileTools profileTools = getProfileTools();
if(order.getCommerceItemCount() > 0){
profileTools.repriceShoppingCarts(profile,orderHolder,profileTools.getRepriceOrderPricingOp(),request,response);
}
getOrderManager().updateOrder(order);
}
 }
 catch (CommerceException commException) {
shouldRollback = true;
if(isLoggingError()){
logError("CommerceException which loading order", commException);
}
}
 finally
 {
   try
   {
     td.end( shouldRollback );
   }
   catch ( Throwable th )
   {
     logError( th );
   }
 }
} catch (DeadlockException deadLockExc) {
if(isLoggingError()){
logError("DeadLockException", deadLockExc);
}
} catch (TransactionDemarcationException transDemExc) {
if(isLoggingError()){
logError("TransactionDemarcationException", transDemExc);
}
}
finally
{
 try
 {
   if ( acquireLock )
     lockManager.releaseWriteLock( profile.getRepositoryId(), Thread.currentThread(), true );
 }
 catch( Throwable th )
 {
   logError( th );
 }
}
}

Thursday 12 July 2012

WHAT'S NEW IN ATG 10.1


We have been waiting for 10.1 to released to see the changes Oracle would bring about in ATG Products Suite and here it is


WHAT'S NEW IN ATG 10.1

  • ATG Platform-Localization of Business Tools
  • ATG Platform-External Caching using Coherence 
  • ATG Commerce-B2B with B2C Commerce Merge
  •  ATG Merchandising -Visual Merchandising
  •  ATG Merchandising-Preview By Date and Time 
  •  ATG Merchadinsing-Workbench
  •  ATG Merchadinsing-Multi‐edit Using Workbench
  • ATG Promotions-Exclusion and Stacking rules 
  • ATG Promotions-Coupon Tracking
  • ATG Promotions-Serialised Coupons
  • ATG Promotions-Gift With Purchase 
  • ATG CRS-Mobile Refernce Applications 
  • ATG CRS-Fluoroscope (Allows developmers to examine which elements of the page relate to which JSP files, the  stack of included files, and parameters being used.)
  • ATG CRS-Gift with Purchase Promotions
  • ATG CRS-Integration with ATG Recommendations
  • ATG CRS-Recently Viewed Items
  • ATG Search-Now for legacy customers only, Endeca recommended for new customers.
  • ATG Commerce Business Intelligence, Oracle BI (Enterprise Edition) replaces Cognos.
  • ATG Campaign Optimizer and Outreach, for legacy customers only.
  • ATG Knowledge and Self Service, for legacy customers only. 

Sunday 8 July 2012

Changing the default Big String Editor in Merchandising - Oracle ATG 10

The default big string editor creates many problems such as simple ' in Merchandising transforms to &apos on the store front and in the assets tab which loads the HTML content in the EditLive! editor. 

The above stated issue which is because of the Flex html editor can be fixed by following the below steps

(1) Load up the ACC and connect it to your CA/Merch server.

(2) When the ACC has loaded, navigate to the Publishing > View Mapping tab.

(3) The next step is to find the text editors available to the AssetManager. Do this by performing the following search in the ACC:
(a) List Items of type propertyView whose name contains "big string"
You will see a list of 4 items when you issue this query. The relevant ones are named "AA AssetManager plain text big string propertyView" and "AssetManager big string propertyView"

(b) If you select "AA AssetManager plain text big string propertyView" you should see that it has the property isDefault set to false.
You need to set this to true and then save the change.

(c) You then need to select "AssetManager big string propertyView"and set isDefault to false.
Save this change.

(4) Now open up the BCC and create a new Merchandising project.

(5) Within this project, create or edit an asset that has a property of type 'big string' and add some HTML content.
     You should now see that the HTML tags are saved correctly by the plain text editor

Customizing Merchandising UI - Oracle ATG 10

As we are all aware Merchandising UI in ATG 10 has been delivered using Flex UI


Below are the steps that need to be followed to made to edit Ids while creating product asset withing Flex


1. Go to Dynamo Administration of BCC
2. Navigate to /atg/web/viewmapping/ViewMappingRepository component
3. Run this XML Operation Tags on the Repository:
<print-item item-descriptor="itemMapping" id="AmImPrdt" />



------ Printing item with id: AmImPrdt
<add-item item-descriptor="itemMapping" id="AmImPrdt">
 <set-property name="itemName"><![CDATA[product]]></set-property>
 <set-property name="description"><![CDATA[AssetManager product itemMapping]]></set-property>
 <set-property name="attributes"><![CDATA[resourceBundle=AmAvPrdtBnd]]></set-property>
 <set-property name="mode"><![CDATA[AmMmDef]]></set-property>
 <set-property name="viewMappings"><![CDATA[AmIvmPrdtGen,AmIvmPrdtSkus,AmIvmPrdtCat,AmIvmPrdtMedia,AmIvmPrdtPrice,AmIvmPrdtCrossEdit,AmIvmPrdtAdv]]></set-property>
 <set-property name="formHandler"><![CDATA[AmFhDef]]></set-property>
 <set-property name="itemPath"><![CDATA[/atg/commerce/catalog/ProductCatalog]]></set-property>
 <set-property name="name"><![CDATA[AssetManager]]></set-property>
</add-item>

4. Run this XML Operation Tags on the Repository:
<add-item item-descriptor="attributeValue" id="AmAvPrdtCreateId">
 <set-property name="value"><![CDATA[true]]></set-property>
</add-item>



5. Append newly created attributeValue into attributes property of AmImPrdt itemMapping using this XML Operation Tags on the Repository:
IMPORTANT NOTE: There shouldn't be any carriage return (ENTER) or white space signs inside ![CDATA[..]]
<update-item item-descriptor="itemMapping" id="AmImPrdt">
 <set-property name="attributes"><![CDATA[resourceBundle=AmAvPrdtBnd,showCreationId=AmAvPrdtCreateId]]></set-property>
</update-item>