Automating Setup of ATG Content Admin

When setting up ATG Content Admin for the first time one of the first steps to follow is to import a deployment topology and initialize with a first deployment. This is so that you are able to initialize deployments.

Both steps can be automated.

To import a deployment topology automatically we can set importAndInitializeTopologyOnStartup on the /atg/epub/DeploymentServer component to true and then specify deployment topology file on the topologyDefinitionFile property in the same component.

#/atg/epub/DeploymentServer
importAndInitializeTopologyOnStartup=true
topologyDefinitionFile=/atg/epub/deploymentTopology.xml

To automate the initial deployment some custom java code is required using the public methods in the DeploymentServer component.

Excluding unwanted SKUs from Endeca

When using the ATG-Endeca Integration it is simple and clear how to filter out products from Endeca but not so obvious how to filter out SKUs from the index.

Suppose that your data model has more than one sub-type of SKU and that each product’s childSKU property contains more than one sub-type of SKU. Here are the steps required to only index the SKU types that you want:

  1. Create a separate indexed items group for the childSKUs property. You can then reference the indexed items group in the product-sku-output-config.xml
    <item property-name="childSKUs" repository-item-group="/component/path/SpecificSkusIndexedItemGroups">
        ...
    </item>
  2.  

  3. Create the SpecificSkusIndexedItemsGroup component
    SpecificSkusIndexedItemsGroup<
    $basedOn=/atg/commerce/search/IndexedItemsGroup 
    # The name of the RepositoryItemGroup 
    groupName=Specific Skus Indexed Items Group 
    # The product item-descriptor name 
    repositoryViewName=sku 
    # The RuleSet that defines the set of items to be indexed. 
    rules= <ruleset> <accepts> <rule op=eq> <valueof target="type"> <valueof constant="someSkuType"> </rule> </accepts> </ruleset>
  4. Restart and do a baseline using the ProductCatalogSimpleIndexingAdmin component

 
You should now have only the SKUs that you want in the index. Enjoy.

How to use the Cache Droplet in Oracle ATG to improve performance

The main page of a typical ATG Commerce Website often has many targeters and other rich content which is computer-resource intensive.
Often, the easiest way to speed up the load time of a home page is to wrap any targeters within a
Cache droplet:

<dsp:droplet name="/atg/dynamo/droplet/Cache">
<dsp:param name="key" value="${category.repositoryId}_${userLocale}"/>
<dsp:oparam name="output">
....
</dsp:oparam>
</dsp:droplet>

The key parameter needs to be sufficiently unique. For example if your home page has a version for each locale then a key should be part of the cache key.

The following caveats apply:

1. Ideally, no personalization rules should exist in the targeters. I.e. targeter rules should apply to all users.
2. Using the cache droplet increases the memory usage of the application.
3. Any deployment from CA will invalidate all the items in the cache droplet. This means that after a deployment, the home page load times will sharply increase.
4. Product availability changes will not be visible in the home page until the cache entry expires.

The following properties control the behavior of the cache:

cacheCheckSeconds – the number of seconds which an entry in the cache takes to expire
purgeCacheSeconds – the number of seconds for the whole cache content to be purged

Integrating ATG with Adobe Flex using BlazeDS

I have had a few inquiries about whether it is possible to integrate Adobe Flex with ATG via AMF. My short answer is Yes. It should be possible. The only issue that needs to be solved though is to access the nucleus components from flex. You need a factory for that e.g. the equivalent of ejbfactory(used for EJB 3) for ATG. At some stage when I have a bit of time in my hands I will create a factory for ATG Nucleus, if nobody creates one in the mean time.

Creating a servlet with ServletPathServlet and ServletPathDispatcher in ATG 9

Imagine that you want to create a servlet in ATG 9 that processes a POST request from an external website. Normal ATG Form Handlers are not of any use here because they use dynamic url parameters to be invoked. What you need is a plain old Java servlet. You can create one in ATG using two methods:

Option 1: What you would do in any other Application server without ATG

  • Create a class that extends javax.servlet.http.HttpServlet
  • Implement the doPost() and doGet() methods.
  • Add servlet mapping to web.xml

The disadvantage of the above method is that if you need access to the DynamoHttpRequest, DynamoHttpResponse objects, you need to extract them from the request using atg.servlet.ServletUtil.

public class ExampleServlet extends HttpServlet
{

    public doGet(HttpServletRequest request, HttpServletResponse response) {
       DynamoHttpServletRequest dRequest = ServletUtil.getDynamoRequest(request);
       DynamoHttpServletResponse dResponse= dRequest.getResponse();
      ...
     }
   public doPost(HttpServletRequest request, HttpServletResponse response) {
      ...
    }
}
web.xml
 <servlet>
     <servlet-name>exampleServlert</servlet-name>
     <servlet-class>com.spltech.co.uk.ExampleServlet</servlet-class>
 </servlet>

<servlet-mapping>

 <servlet-name>exampleServlet</servlet-name>

 <url-pattern>/exampleServlet</url-pattern>

 </servlet-mapping>

Option 2: The ATG Way – Using ServletPathServlet and ServletPathDispatcher

If you are developing in ATG, chances are is that you want to do things the ATG way. Here is how you do it:

  • Create a property file for /atg/dynamo/servlet/pipeline/ServletPathServlet. Override the servletPaths property and add the path that you want the servlet to be called for (e.g. /complete-payment).
  • Create a property file for /atg/dynamo/servlet/pipeline/ServletPathDispatcher. Override the dispatcherServiceMap property and add the mapping between the path that you added in the previous step and the ATG component that you want to be called.
  • Create a class that extends DynamoServlet. Override the service(DynamoHttpServletRequest req, DynamoHttpServletResponse resp) method and place here the code that does the business logic for your servlet.
  • Restart ATG and try to access your servlet at /dyn/complete-payment. In this case dyn is the default prefix added to all servlet paths called by the ServletPathDispatcher.

ServletPathServlet.properties:

##############################
#
# This splits the pathInfo of an incoming request into
# a servletPath/pathInfo combination, if the pathInfo
# starts with one of the servletPaths.  You can later
# dispatch off one of these paths using the
# ServletPathDispatcher component
#

servletPaths+=
			/example-servlet

ServletPathDispatcher.properties:

#
# This dispatcher will send any requests with a
# servletPath of "/exittracking" to the ExitTracking
# component.  If you add more servletPaths here, you
# should also remember to add those paths to the
# ServletPathServlet
#
dispatcherServiceMap+=
					/example-servlet=/uk/co/spltech/servlet/ExampleServlet

ExampleServlet.java:

/**
 * Example Servlet  
 * @author spltech
 *
 */
public class ExampleServlet extends DynamoServlet {
    public void service(DynamoHttpServletRequest req, DynamoHttpServletResponse res)
        throws ServletException, IOException
    { 
       ....
    }
}

ExampleServlet.properties:

$class=spltech.commerce.order.purchase.PaymentResponseServlet
$scope=global
...