How to Set an Array Property in an ATG Form

Cool Blue Hive on Flickr
(Photo: Cool Blue Hive by jurvetson)

In the Setting Property Values in Forms section of the ATG Page Developer’s Guide there are two examples for setting values of array properties in forms.

  1. Grouped Checkboxes
  2. Multiple-Selection List Box

Both examples are for a simple form.  But what if you are generating a form using a ForEach droplet and want to set an array property in each iteration of the loop.  Fortunately it turns out to be relatively easy.

Hidden or Text Inputs

<dsp:droplet name="/atg/dynamo/droplet/ForEach">
  <dsp:oparam name="output">
    <dsp:input type="hidden" paramvalue="element.id" bean="MyFormHandler.ids"/>
  </dsp:oparam>
</dsp:droplet>

Select Inputs

<dsp:droplet name="/atg/dynamo/droplet/ForEach">
  <dsp:oparam name="output">
    <dsp:select bean="MyFormHandler.answers">
     <dsp:option value="foo">foo</dsp:option>
     <dsp:option value="bar">bar</dsp:option>
    </dsp:select>
  </dsp:oparam>
</dsp:droplet>

By the way if you try to set the array element directly using the param:index notation as in the following example it will not work.

<dsp:droplet name="/atg/dynamo/droplet/ForEach">
  <dsp:oparam name="output">
    <dsp:select bean="MyFormHandler.answers[param:index]">
     <dsp:option value="foo">foo</dsp:option>
     <dsp:option value="bar">bar</dsp:option>
    </dsp:select>
  </dsp:oparam>
</dsp:droplet>

When submitting the above form you will get this exception.

atg.droplet.DropletException:
  Can't set an element of the array property without a set <name> (int index, Object value) method.

The exception message is a red herring, there is no way you can set the element of an array property no matter what kind of set method you create.  Trust me, I spent many hours delving into the ATG code to verify this. 🙂

ATGLogColorizer for Colorizing ATG Server Outputs and Logs

ATGLogColorizer

Color is wonderful.  With color we can immediately recognize patterns, signals, warnings, etc.  By using a utility that color codes your logs and server outputs to highlight errors in red, warnings in yellow, etc. you can be much more efficient about how you monitor and search.

Back in the day we used to use DynamoFilter.exe to color code the output of running ATG on the Dynamo Application Server (DAS).  Now that people no longer use DAS that application is no longer useful.

Today though I found out about the open source project ATGLogColorizer.  This fantastic utility works with JBoss, WebLogic, DAS and WebSphere.  It works on Windows, Mac OSX, Solaris and other UNIX variants.  It even works on Cygwin.

This is how I start JBoss with ATGLogColorizer on Cygwin.

${ATG}/home/bin/startDynamoOnJBOSS.bat -f -run-in-place -c default -m Foo | ATGLogColorizer.exe'

And this is how I start JBoss with ATGLogColorizer on Mac OS X.

${ATG}/home/bin/startDynamoOnJBOSS.sh -f -run-in-place -c default -m Foo | ATGLogColorizer_v1_2_OSX'

Life has become a little better. 🙂

For further reading please see and ATGLogColorizer and ATG Log Colorizer for JBoss.

How to Debug an InvalidVersionException from Updating an ATG Order

I thought I saw a puddy cat.... on Flickr

If you ever update an order outside of a transaction then the next time you update it within a transaction you will get the infamous, dreaded InvalidVersionException.

WARN  atg.commerce.order.ShoppingCartModifier
atg.commerce.order.InvalidVersionException: This order (o3830002) is out of date. Changes have been made to the order and the operation should be resubmitted. Order version 333, Repository item version 334.
   at atg.commerce.order.OrderManager.updateOrder(OrderManager.java:2557)

For example this could happen if you update your order in your JSP page.

<dsp:setvalue bean=”order.foo” value=”bar” />

To fix this problem you must always make sure to update an order within a transaction like this.

Transaction tr = null;
try {
  tr = ensureTransaction();
  synchronized (getOrder()) {
    getOrder().setFoo("bar");
    try {
      getOrderManager().updateOrder(order);
    }
    catch (Exception exc) {
      processException(exc, MSG_ERROR_UPDATE_ORDER, pRequest, pResponse);
    }
  }
}
finally {
  if (tr != null) commitTransaction(tr);
}

In some cases you might find a method is called within a transaction by another method and in other cases it is not.

public boolean handleFoo(DynamoHttpServletRequest req, DynamoHttpServletResponse res) {
  Transaction tr = null;
  try {
    tr = ensureTransaction();
    synchronized (getOrder()) {
      setFoo("bar");
      try {
        getOrderManager().updateOrder(order);
      }
      catch (Exception exc) {
        processException(exc, MSG_ERROR_UPDATE_ORDER, pRequest, pResponse);
      }
    }
    return checkFormRedirect(getSuccessUrl(), getErrorUrl(), req, res);
  }
  finally {
    if (tr != null) commitTransaction(tr);
  }
}

public void setFoo(String foo) {
  getOrder().setFoo(foo);
}

In the above example the handleFoo method properly updates the order within the transaction.  However calling the setFoo method directly will cause a problem since the order is not updated within a transaction.  To fix this you use the same pattern again to ensure the order is updated within a transaction.  It is okay to do this more than once during a request.

To debug this problem you can use Eclipse to make sure that wherever you update an order is always within a transaction. You can use the debugger to find which methods are called and/or you can use the call hierarchy to find out how methods are called.

Another way to help debug this is adding JSP code similar to the one I list below. It outputs the version of the order that the form handler has and the version that is in the repository.  If there is a difference then you know that the action you took before at some point updated the order outside of a transaction.

<dspel:getvalueof bean="ShoppingCartModifier.order.id" var="orderId" />
FORM HANDLER ORDER ID: ${orderId}<br/>
FORM HANDLER ORDER VERSION: <dsp:valueof bean="ShoppingCartModifier.order.version" /><br/>
<dsp:droplet name="/atg/dynamo/droplet/RQLQueryForEach">
  <dsp:param name="queryRQL" value="ID IN { \"${orderId}\" }"/>
  <dsp:param name="repository" value="/atg/commerce/order/OrderRepository"/>
  <dsp:param name="itemDescriptor" value="order"/>
  <dsp:oparam name="output">
    REPOSITORY ORDER VERSION: <dsp:valueof param="element.version"/><br/>
  </dsp:oparam>
</dsp:droplet>

For further reading please see Nabble – ATG Dynamo – Commerce Assist Returns and the Transaction Management section in the ATG Programming Guide.

ATG Currency Converter Not Working With JSTL c:set

Currency conversion confusion on Flickr!

This JSP code was not outputting the properly formatted amount.

<dspel:valueof value="${dollars}" converter="currency" />

I tried forcing it by specifying the conversion parameters.

<dspel:valueof value="${dollars}" converter="currency" locale="en-CA" format="#.00" currency="$" />

I then debugged atg.droplet.CurrencyTagConverter using Eclipse and found this code being executed.

public String convertObjectToString(DynamoHttpServletRequest pRequest,
                                 Object pValue, Properties pAttributes)
  throws TagConversionException
{
  if ((pValue == null) || (pValue instanceof String))
    return (String)pValue;

It turns out pValue was a String which is why it was never being formatted.  But why is it a String?

Well the code that sets dollars looks like this.

<dspel:tomap var="paymentGroup" param="commerceItem.paymentGroups[1]" />
<c:set var="dollars" value="0" />
<c:if test="${not empty paymentGroup}">
  <c:set var="dollars" value="${paymentGroup.amount}" />
</c:if>

Apparently c:set converts the Double to a String.

To work around this problem I did this.

$<dspel:valueof number="0.00" value="${dollars}" />

For further reading please see Tag Converters in the ATG Page Developer’s Guide.

How to Add Products to Categories using Content Groups

Typically after you create a category in your catalog you then add products to the category.  The simple way to do that in ATG eCommerce is to use the ACC and add products to the child products property of the category.  However there is another way.

In the ATG Commerce Guide to Setting Up a Store documentation you can see in the Viewing the Product Catalog section that a category can have child products but also child product groups.

Product Catalog

Child product groups are actually content groups which are described in the Creating Content Groups chapter of the ATG Personalization Guide for Business Users.

Targeting > Profile and Content Groups window

Though the documentation shows a content group composed of features you can easily create a content group using the ProductCatalog as a content source and product as a content type.

To create a content group follow the steps in the ATG documentation for Creating New Content Groups except use an item from the ProductCatalog when specifying the Content Type.  Then create the targeting rules for this Content Group.  Now you can specify this group in the Child products (group) property of a category.

ATG Product Bundles

what's in my sxsw schwag bag - photo by joey.parsons - Flickr

Out of the box ATG eCommerce does not support product bundles.  It does support SKU bundles, i.e. a product can consist of multiple SKU’s.

To support product bundles is pretty simple to implement.

First you create a new type of product for bundles in /atg/commerce/catalog/productCatalog.xml.

<item-descriptor name="product">
 <table name="dcs_product">
  <property name="type" data-type="enumerated" default="regular">
   <attribute name="useCodeForValue" value="false"/>
   <option value="regular" code="0"/>
   <option value="bundle" code="1" />
 </property>
 </table>


Then you define your bundles product to have the new products property. This property is simply a list of products that the bundle contains, e.g. Costco organic cotton polo shirt and Nike athletic shorts.

<item-descriptor name="bundle" super-type="product" sub-type-value="bundle">
 <table name="betweengo_product_bundle" multi-column-name="seq_num"
  type="multi" id-column-names="product_bundle_id">
  <property name="products" column-name="product_id" data-type="list"
   component-item-type="product" display-name="Products" category="Bundle" />
 </table>
</item-descriptor>

A few years ago I did a more advanced version of this implementation which allowed for different numbers of products in one bundle, e.g. two different kinds of shirts and one pair of pants.  I did this using the concept of product links which is similar to SKU links that ATG supports.

If you are interested in wanting to implement a more advanced version please contact us.

How to Debug No Output for ATG ForEach

foreach

Today I added a feature in my shopping cart JSP page but nothing was showing up.  This was because the output of ATG ForEach droplet was blanks.

To debug this I did the following steps.

  1. I added an empty oparam to see if the ForEach droplet thought the collection was empty.
    <dsp:oparam="empty">Empty?</dsp:oparam>

    It did not.

  2. I outputted the count in the output oparam to see if it was looping through the collection.
    <dsp:oparam="output"><dsp:valueof param="count"/> <dsp:valueof param="element"/></dsp:oparam>

    It was looping through the collection.

  3. Finally I debugged using Eclipse the ForEach code.  The ForEach code can be found in <ATG>/DAS/src/Java/atg/droplet/ForEach.java

    Using the debugger I realized that the element name of the loop was being set to something else which is why <dsp:valueof param=”element”/> was blank.

It turned out that the ForEach droplet was inside another ForEach droplet and in that droplet they set the element name like this.

<dsp:param name="elementName" value="CommerceItem" />

By setting the elementName parameter to something else in my ForEach droplet and then referencing it properly I was finally able to get the expected output.

<dsp:droplet name="/atg/dynamo/droplet/ForEach">
 <dsp:param name="array" param="CommerceItem.auxiliaryData.productRef.dvds"/>
 <dsp:param name="elementName" value="dvd" />
 <dsp:oparam name="output">
  <dsp:valueof param="dvd.name" />
 </dsp:oparam>
</dsp:droplet>

By the way ATG documentation suggests not using elementName.

elementName and indexName allow you to provide a parameter name other than element and index, respectively. A better way to provide a different parameter name is to use the dsp:setvalue tag.

In our example we would do this instead of setting the elementName param.

 <dsp:setvalue param="dvd" paramvalue="element" />

Debug ATG running on JBoss with Eclipse

Configuring Eclipse for Remote Debugging - O'Reilly Media 

With Eclipse debugging an ATG application running on JBoss is fairly straightforward.

  1. Configure JBoss to start up with Java options for debugging.

    On UNIX you do this by uncommenting this line in <JBoss>/bin/run.conf.

    #JAVA_OPTS="$JAVA_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y"

    On Windows you do this by uncommenting this line in <JBoss>/bin/run.bat.

    rem set JAVA_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y %JAVA_OPTS%
  2. Create a remote Java application debug configuration using the port you specified in step 1.  The default port is 8787.

For further reading please see Debugging Nucleus components in JBoss with Eclipse or Remote Debugging with Eclipse.  There is also a very complete tutorial from O’Reilly Media called Configuring Eclipse for Remote Debugging.

ATG ForEach Output with Separators Between Items

Pez Collection

Sometimes you want to list each item in the collection with a separator in between like a comma or slash.  However the trick is to have the separator only in between items.

In ATG DSP you can use the ForEach droplet to iterate through each item in a collection.  However to put a separator between each item is not straight-forward with this droplet.  To do this I used JSTL to test if we are at the end of the collection.  If we are then I don’t add the separator, otherwise I do.

Here is an example.

<dspel:droplet name="/atg/dynamo/droplet/ForEach">
 <dspel:param name="array" param="dvds"/>
 <dspel:setvalue param="dvd" paramvalue="element" />
 <dspel:oparam name="outputStart">
  <dspel:getvalueof var="size" param="size" />
 </dspel:oparam>
 <dspel:oparam name="output">
  <dspel:valueof param="dvd.title" valueishtml="true"/>
  <dspel:getvalueof var="count" param="count" />
  <c:if test="${size != count}"> , </c:if>
 </dspel:oparam>
</dspel:droplet>

And here is the output for this example.

The Incredibles, Ratatouille, Cars

Do you have a better or more elegant solution?  Please feel free to let me know in the comments?

How to Get Permission to Create Scenarios in ACC

This is Happening without your Permission

Sometimes you will find that you cannot create or duplicate scenarios.  You keep clicking on the grayed out New Scenario button and right-clicking on scenarios you want to duplicate but nothing happens.

Fortunately the solution is rather simple and is alluded to in the ATG Personalization Programming Guide – Configuring the Process Editor Server.

First you create a scenarioManager.xml file in your <ATG>/home/localconfig/atg/scenario directory like the following.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<process-manager-configuration>

  <process-editor-server>
    <server-name>foobar:8850</server-name>
  </process-editor-server>

</process-manager-configuration>

Next you replace foobar:8850 with the value of /atg/dynamo/service/ServerName.serverName.  You may want to configure the serverName value to something you want because sometimes it might change if for example when you connect via VPN.

Then you restart ATG and reconnect or restart the ACC and you should be able to create and duplicate scenarios.

(Note that when you create the workflowProcessManager.xml file in your <ATG>/home/localconfig/atg/epub/workflow/process directory it can have the exact same contents as the scenarioManager.xml file.)