ATG Commerce provides several form handlers to support a checkout process that uses any number or type of shipping group and payment group. If your site has this type of complex checkout process, then you should use the form handlers described in this section instead of ExpressCheckoutFormHandler. (For more information on ExpressCheckoutFormHandler, see Preparing a Simple Order for Checkout.)
The form handlers described in this section manage different subprocesses in the pre-checkout process, which makes it easier for you to extend them when necessary. Separate form handlers exist to support the following tasks:
Creating Shipping Groups
ATG Commerce provides two implementations of the CreateShippingGroupFormHandler interface to support the form-driven creation of hard good and electronic shipping groups. These form handler classes create the ShippingGroups and optionally add them to the ShippingGroupMapContainer. Once the shipping groups are added to the ShippingGroupMapContainer, the user can then select from among them for use in the current Order.
The two default implementations of CreateShippingGroupFormHandler are:
CreateHardgoodShippingGroupFormHandler
This form handler class creates a
HardgoodShippingGroupand exposes it via agetHardgoodShippingGroup()method, which makes it possible for users to edit its properties directly via JSP forms. ATG Commerce provides an instance ofatg.commerce.order.purchase.CreateHardgoodShippingGroupFormHandler; it is located in Nucleus at/atg/commerce/order/purchase/CreateHardgoodShippingGroupFormHandler.To create the
HardgoodShippingGroup, thehandleNewHardgoodShippingGroup()method invokes thecreateHardgoodShippingGroup()method, which actually creates the shipping group. The form handler’shardgoodShippingGroupTypeproperty determines the type of shipping group to create; by default, this property is set tohardgoodShippingGroup. The form handler’shardgoodShippingGroupNameproperty determines the name of the new shipping group, as referenced in theShippingGroupMapContainer.CreateHardgoodShippingGroupFormHandleris configured to use/atg/commerce/util/AddressValidatorto validate the shipping address before creating the shipping group. The default configuration is:validateFirstName=truevalidateLastName=truevalidateAddress1=truevalidateCity=truevalidateCounty=falsevalidateState=truevalidatePostalCode=truevalidateCountry=truevalidateEmail=falsevalidatePhoneNumber=falsevalidateFaxNumber=false
This validation can be performed every time the shipping group is updated, via the
UpdateHardgoodShippingGroupFormHandlerclass.Finally, the form handler’s
addToContainerproperty determines whether the new shipping group is added to theShippingGroupMapContainerand made the default shipping group; by default, this property is set to True. Once theHardgoodShippingGroupis added to theShippingGroupMapContainer, the user can use it when checking out theOrder.After creating the
HardgoodShippingGroup, you can use theUpdateHardgoodShippingGroupFormHandlerto handle shipping address changes.UpdateHardgoodShippingGroupFormHandlercan update this information in any or all of three places, based on these properties:updateContainer—Updates theHardgoodShippingGroupin theShippingGroupMapContainer.updateProfile—Updates the shipping address in the profile.updateOrder—Updates theHardgoodShippingGroupin the order.
CreateElectronicShippingGroupFormHandler
This form handler class creates an
ElectronicShippingGroupand exposes it via agetElectronicShippingGroup()method, which makes it possible for users to edit its properties directly via JSP forms. ATG Commerce provides an instance ofatg.commerce.order.purchase.CreateElectronicShippingGroupFormHandler; it is located in Nucleus at/atg/commerce/order/purchase/CreateElectronicShippingGroupFormHandler.To create the
ElectronicShippingGroup, thehandleNewElectronicShippingGroup()method invokes thecreateElectronicShippingGroup()method, which actually creates the shipping group and sets the shipping group’semailAddressproperty. The form handler’selectronicShippingGroupTypeproperty determines the type of shipping group to create; by default, this property is set toelectronicShippingGroup. The form handler’selectronicShippingGroupNameproperty determines the name of the new shipping group, as referenced in theShippingGroupMapContainer. Finally, the form handler’saddToContainerproperty determines whether the new shipping group is added to theShippingGroupMapContainerand made the default shipping group; by default, this property is set to True. Once theElectronicShippingGroupis added to theShippingGroupMapContainer, the user can use it when checking out theOrder.After creating the
ElectronichippingGroup, you can use theUpdateShippingGroupFormHandlerto handle updates to the shipping group.UpdateShippingGroupFormHandlercan update shipping group information in the container and/or the order, based on these properties:updateContainer—Updates theElectronicShippingGroupin theShippingGroupMapContainer.updateOrder—Updates theElectronicShippingGroupin the order.
You can also create Profile-derived ShippingGroups and add them to the ShippingGroupMapContainer by using the ShippingGroupDroplet servlet bean (class atg.commerce.order.purchase.ShippingGroupDroplet). The input parameters passed into ShippingGroupDroplet determine what types of ShippingGroups are created (hard good, electronic, or both) and whether the ShippingGroupMapContainer is cleared before they are created. For a detailed list of these input parameters, as well as output parameters, open parameters, and a code example, see the Adding Shipping Information to Shopping Carts section of the Implementing Order Retrieval chapter of the ATG Commerce Guide to Setting Up a Store.
To initialize the ShippingGroup objects, the service method of ShippingGroupDroplet calls initializeUsersShippingMethods(), which initializes one or more ShippingGroups for the current user and adds them to the ShippingGroupMapContainer. For each entry in ShippingGroupDroplet.shippingGroupTypes (which is supplied via an input parameter), its corresponding ShippingGroupInitializer is obtained from the ServiceMap in ShippingGroupDroplet.shippingGroupInitializers (keyed by ShippingGroup type). The initializeShippingGroups() method of the ShippingGroupInitializer is then used to initialize the ShippingGroup and add it to the ShippingGroupMapContainer.
Note that ATG Commerce provides two implementations of the ShippingGroupInitializer interface, namely HardgoodShippingGroupInitializer and ElectronicShippingGroupInitializer. The former creates HardgoodShippingGroups based on their existence in the user’s Profile, and the latter creates ElectronicShippingGroups based on the existence of an e-mail address in the user’s Profile.
To use this framework with a new ShippingGroup type that you create, first, write a new ShippingGroupInitializer implementation. Its initializeShippingGroups() method should gather the user’s ShippingGroups by type and add them to the ShippingGroupMapContainer referenced by the ShippingGroupFormHandler. For example, the ElectronicShippingGroupInitializer queries the Profile’s email property and applies the result to a new ElectronicShippingGroup, which is subsequently added to the ShippingGroupMapContainer. Second, register a Nucleus component for the new ShippingGroupInitializer implementation and add it to the ServiceMap in ShippingGroupDroplet.shippingGroupInitializers, which is keyed by ShippingGroup type. Finally, include the new ShippingGroup type in the ShippingGroupDroplet.shippingGroupTypes parameter on those site pages where the new ShippingGroup type is utilized.
Associating Shipping Groups with an Order and Its Items
When the user has supplied the shipping information for an Order, the ShippingGroupFormHandler can be used to create and manage the associations between the ShippingGroups and the items in the Order. ATG Commerce provides a request-scoped instance of atg.commerce.order.purchase.ShippingGroupFormHandler, which is located in Nucleus at /atg/commerce/order/purchase/ShippingGroupFormHandler.
The ShippingGroupFormHandler works in conjunction with the ShippingGroupDroplet to manipulate the relationships between CommerceItems and ShippingGroups in the order. Handling Instructions and their relationships to CommerceItems and ShippingGroups are also manipulated based on the relationship between each CommerceItem and the ShippingGroups.
By default, this form handler invokes the validateShippingInfo pipeline chain to validate ShippingGroup information. To skip validation, set the validateShippingGroups property to false. To learn more about the pipeline chain, see the validateShippingInfo Pipeline Chain section.
It should be noted that ShippingGroupFormHandler does not reprice the given Order. Consequently, if you enable customers to make order changes that affect order price through this form handler, you should then reprice the given Order using the RepriceOrderDroplet servlet bean before displaying its price to the customer. For more information on RepriceOrderDroplet, see Repricing Orders section of the ATG Commerce Guide to Setting Up a Store.
The ShippingGroupFormHandler is composed of the following containers:
atg.commerce.order.purchase.ShippingGroupMapContainer, which defines aMapof user-assignedShippingGroupnames toShippingGroups. This container stores the user’s potentialShippingGroupsfor theOrder.atg.commerce.order.purchase.CommerceItemShippingInfoContainer, which defines aMapofCommerceItemstoCommerceItemShippingInfoLists. This container stores the user’sCommerceItemShippingInfoobjects for theCommerceItemsin theOrder.
Additionally, the ShippingGroupFormHandler uses the following helper classes:
atg.commerce.order.purchase.CommerceItemShippingInfo, which represents the association between aCommerceItemand its shipping information and includes properties such asquantity,splitQuantity, andrelationshipType. These objects store the information needed to createShippingGroupCommerceItemRelationshipsfor theOrder.atg.commerce.order.purchase.HandlingInstructionInfo, which is used to associate handling instruction information with eachCommerceItemShippingInfoobject. HandlingInstructionInfois stored in ahandingInstructionInfoslist property of theCommerceItemShippingInfoobject.atg.commerce.order.purchase.ShippingGroupDroplet, which contains a reference to both theShippingGroupMapContainerandCommerceItemShippingInfoContainer. TheShippingGroupDropletservlet bean is used to initializeShippingGroupobjects andCommerceItemShippingInfoobjects for use by theShippingGroupFormHandler. The resulting collections ofShippingGroupsandCommerceItemShippingInfosare exposed via the output parameters of the servlet bean. For more information on using theShippingGroupDropletto initializeShippingGroupobjects, see the previous section, Creating Shipping Groups. For more information on initializingCommerceItemShippingInfoobjects, see below.atg.commerce.order.purchase.CommerceItemShippingInfoTools, which contains helper methods for creating, modifying, removing and applying theCommerceItemShippingInfoandShippingGroupobjects in the CommerceItemShippingInfoContainer andShippingGroupMapContainercontainers respectively.CommerceItemShippingGroupToolsincludes theincludeGiftsflag, which determines how gift items are handled when split across shipping groups.
With these helper classes and containers, the ShippingGroupFormHandler adds the necessary ShippingGroups to the Order, establishes their relationships to the CommerceItems, performs validation, and updates the Order. The following table describes the handle methods used in these processes:
Method | Description of Functionality |
|---|---|
| This handle method splits the quantities of The handle method calls |
| This handle method is used to let the user specify a default Setting the default |
| This handle method adds the The handle method calls The Next, if the form handler’s Then, the handle method calls Finally, the handle method calls |
As previously mentioned, the ShippingGroupDroplet servlet bean is used to initialize CommerceItemShippingInfo objects and add them to the CommerceItemShippingInfoContainer, so they can be used by the ShippingGroupFormHandler. To initialize the CommerceItemShippingInfo objects, the service method calls initializeCommerceItemShippingInfos() which, by default, creates and initializes a CommerceItemShippingInfo for each CommerceItem in the Order and adds them to the CommerceItemShippingInfoContainer. Each new CommerceItemShippingInfo references the default ShippingGroup in the ShippingGroupMapContainer.
The paragraph above describes the default behavior of the ShippingGroupDroplet. The droplet, however, has several input parameters that control whether and how CommerceItemShippingInfo objects are created. An additional parameter controls whether the CommerceItemShippingInfoContainer is cleared before the objects are created. For a detailed list of these input parameters, as well as ShippingGroupDroplet output parameters, open parameters, and a code example, see the Adding Shipping Information to Shopping Carts section of the Implementing Order Retrieval chapter of the ATG Commerce Guide to Setting Up a Store.
The HandlingInstructionInfo class makes it possible to split, merge, and apply handling information along with the CommerceItemShippingInfo objects with which it is associated. When the ShippingGroupDroplet initializes a container based on the current contents of an Order, HandlingInstructionInfo objects are automatically generated for any handling instructions currently in the Order. These HandlingInstructionInfo objects are then associated with the appropriate CommerceItemShippingInfo objects based on the CommerceItem referenced in the handling instruction.
Gift items in an order are identified by a special handling instruction (GiftHandlingInstruction), and therefore the ShippingGroupDroplet and ShippingGroupFormHandler automatically handle splitting and merging of gift items in the order.
If the CommerceItemShippingInfoToolsincludeGifts property is set to false (the default), it has the following effects:
CommerceItemShippingInfoobjects don’t include the quantity of the items designated as gifts. For example, if an item is quantity 3, and 1 is a gift, aCommerceItemShippingInfowill be created for a quantity of 2.GiftHandlingInstructionsare not included in theHandlingInstructionInfosassociated with theCommerceItemShippingInfosShippingGroupsthat contain only gifts are not added to theShippingGroupMapContainer
The result is that none of the gift-related objects in the Order are added to the CommerceItemShippingInfoContainer and ShippingGroupMapContainer when initializing based on the Order, and after applying, they remain unchanged in the Order.
Creating Payment Groups
ATG Commerce provides two implementations of the CreatePaymentGroupFormHandler interface to support the form-driven creation of credit card and invoice payment groups. These form handler classes create the payment groups and optionally add them to the PaymentGroupMapContainer. Once the payment groups are added to the PaymentGroupMapContainer, the user can then select from among them for use in the current Order.
The default implementations of the CreatePaymentGroupFormHandler are:
CreateCreditCardFormHandler
This form handler creates a
CreditCardpayment group and exposes it via agetCreditCard()method, which makes it possible for users to edit its properties directly via JSP forms. ATG Commerce provides an instance ofatg.commerce.order.purchase.CreateCreditCardFormHandler; it is located in Nucleus at/atg/commerce/order/purchase/CreateCreditCardFormHandler.To create the
CreditCardpayment group, thehandleNewCreditCard()method invokes thecreateCreditCard()method, which actually creates the payment group. The form handler’screditCardTypeproperty determines the type ofCreditCardpayment group to create; by default, this property is set tocreditCard. The form handler’screditCardNameproperty determines the name of the new payment group, as referenced in thePaymentGroupMapContainer. The form handler’saddToContainerproperty determines whether the new payment group is added to thePaymentGroupMapContainerand made the default payment group; by default, this property is set to True. (Once the payment group is added to thePaymentGroupMapContainer, the user can use it when checking out theOrder.)CreateCreditCardFormHandlercan optionally validate credit card information using the credit card’s verification number. To validate credit cards, set thevalidateCreditCardproperty totrue. Finally, the form handler’scopyToProfileproperty determines whether the payment group is copied to theProfile; by default, this property is set totrue.After creating the credit card information, you can use the
UpdateCreditCardFormHandlerto deal with any changes the user makes to their credit card information.UpdateCreditCardFormHandlercan update this information in any or all of three places, based on these properties:updateContainer—Update the credit card in thePaymentGroupMapContainer.updateProfile—Update the credit card in the profile.updateOrder—Update the credit card in the order.
CreateInvoiceRequestFormHandler
(ATG Business Commerce only) This form handler creates an
InvoiceRequestpayment group and exposes it via agetInvoiceRequest()method, which makes it possible for users to edit its properties directly via JSP forms. ATG Business Commerce provides an instance ofatg.b2bcommerce.order.purchase.CreateInvoiceRequestFormHandler; it is located in Nucleus at/atg/commerce/order/purchase/CreateInvoiceRequestFormHandler.To create the
InvoiceRequestpayment group, thehandleNewInvoiceRequest()method first invokes thecheckRequiredProperties()method. By default, this method checks that apoNumberfor the invoice has been specified and throws an exception if one has not been provided. The handle method then callscreateInvoiceRequest(), which actually creates the payment group.The form handler’s
invoiceRequestTypeproperty determines the type ofInvoiceRequestpayment group to create; by default, this property is set toinvoiceRequest. The form handler’saddToContainerproperty determines whether the new payment group is added to thePaymentGroupMapContainerand made the default payment group; by default, this property is set to True. (Once the payment group is added to thePaymentGroupMapContainer, the user can use it when checking out theOrder.) The form handler’sbillingAddressPropertyNamedetermines the billing addressProfileproperty to copy into theInvoiceRequest; by default, this property is set todefaultBillingAddress. Finally, the form handler’sinvoiceRequestPropertiesproperty determines what additionalProfileproperties to dynamically add to theInvoiceRequest.
You can also create Profile-derived PaymentGroups and add them to the PaymentGroupMapContainer by using the PaymentGroupDroplet servlet bean (class atg.commerce.order.purchase.PaymentGroupDroplet). The input parameters passed into PaymentGroupDroplet determine what types of PaymentGroups are created (credit card, store credit, gift certificate) and whether the PaymentGroupMapContainer is cleared before they are created. For a detailed list of these input parameters, as well as its output parameters, open parameters, and a code example, see the Adding Payment Information to Shopping Carts section of the Implementing Shopping Carts chapter of the ATG Commerce Guide to Setting Up a Store.
To initialize the PaymentGroup objects, the service method of PaymentGroupDroplet calls initializeUserPaymentMethods(), which initializes one or more PaymentGroups for the current user and adds them to the PaymentGroupMapContainer. For each entry in PaymentGroupDroplet.paymentGroupTypes (which is supplied via an input parameter), its corresponding PaymentGroupInitializer is obtained from the ServiceMap in PaymentGroupDroplet.paymentGroupInitializers (keyed by PaymentGroup type). The initializePaymentGroups() method of the PaymentGroupInitializer is then used to initialize the PaymentGroup and add it to the PaymentGroupMapContainer.
Note that ATG Commerce provides four implementations of the PaymentGroupInitializer interface. They are:
CreditCardInitializerGiftCertificateInitializerStoreCreditInitializerInvoiceRequestInitializer(ATG Business Commerce only)
To use this framework with a new PaymentGroup type that you create, first, write a new PaymentGroupInitializer implementation. Its initializePaymentGroups() method should gather the user’s PaymentGroups by type and add them to the PaymentGroupMapContainer referenced by the PaymentGroupFormHandler. For example, the StoreCreditInitializer queries the Claimable Repository for the user’s StoreCreditPaymentGroups, instantiates objects for them, and then adds them to the PaymentGroupMapContainer. Second, register a Nucleus component for the new PaymentGroupInitializer implementation and add it to the ServiceMap in PaymentGroupDroplet.paymentGroupInitializers, which is keyed by PaymentGroup type. Finally, include the new PaymentGroup type in the PaymentGroupDroplet.paymentGroupTypes parameter on those site pages where the new PaymentGroup type is utilized.
Associating Payment Groups with an Order and Its Items
When the user has supplied the payment information for an Order, the PaymentGroupFormHandler can used to create and manage the associations between the PaymentGroups and the various parts of the Order. Any Order that has been successfully processed by the PaymentGroupFormHandler is ready for the next phase of the purchase process, which is typically order confirmation. ATG Commerce provides a request-scoped instance of atg.commerce.order.purchase.PaymentGroupFormHandler, which is located in Nucleus at /atg/commerce/order/purchase/PaymentGroupFormHandler.
The PaymentGroupFormHandler adds the PaymentGroups to the Order, adds the CommerceItems, ShippingGroups, tax, cost amount and cost remaining information to the PaymentGroups, validates the PaymentGroup information, and finally saves the Order in its present state to the Order Repository. If you’d prefer for items to be priced according to a pricelist rather than the default behavior provided by the pricing engine, set the priceListId property to the appropriate pricelist. When it is finished, the Order is ready to proceed to the next step in the purchase process, which typically is Order checkout. (See Submitting an Order for Checkout.)
The PaymentGroupFormHandler is composed of the following containers:
atg.commerce.order.purchase.PaymentGroupMapContainer, which defines aMapof user-assignedPaymentGroupnames toPaymentGroups. This container stores the user’ potentialPaymentGroupsfor theOrder.atg.commerce.order.purchase.CommerceIdentifierPaymentInfoContainer, which defines aMapofCommerceIdentifierstoCommerceIdentifierPaymentInfoLists. This container stores the user’sCommerceIdentifierPaymentInfoobjects for theOrder.
Additionally, the PaymentGroupFormHandler uses the following helper classes:
atg.commerce.order.purchase.CommerceIdentifierPaymentInfo, which represents the association between aCommerceIdentifierand its payment information and includes properties that allow the cost of a given quantity or even a single item to be spread across multiple payment groups. These objects store the information need to create paymentRelationshipsfor theOrder.atg.commerce.order.purchase.PaymentGroupDroplet, which implements both thePaymentGroupMapContainerandCommerceIdentifierPaymentInfoContainerinterfaces. ThePaymentGroupDropletservlet bean is used to initializePaymentGroupobjects andCommerceIdentifierPaymentInfoobjects for use by thePaymentGroupFormHandler. The resulting collections ofPaymentGroupsandCommerceIdentifierPaymentInfoobjects are exposed via the output parameters of the servlet bean. (For more information on usingPaymentGroupDropletto initializePaymentGroupobjects, see Creating Payment Groups. For more information on initializingCommerceIdentifierPaymentInfoobjects, see below in this section.)
With these helper classes and containers, the PaymentGroupFormHandler adds the necessary PaymentGroups to the Order, validates them, and updates the Order. The following table describes the handle methods used in these processes:
Method | Description of Functionality |
|---|---|
| This handle method is used when the user wants to split a particular The handle method calls In a form, the user might request to split $50 of an original |
| This handle method is used to let the user specify a default Setting the default |
| This handle method adds the The handle method calls Next, the Next, if the form handler’s Then, Next, the handle method calls Finally, the handle method calls |
As previously mentioned, the PaymentGroupDroplet servlet bean is used to initialize CommerceIdentifierPaymentInfo objects and add them to the CommerceIdentifierPaymentInfoContainer, so they can be used by the PaymentGroupFormHandler. To initialize the CommerceIdentifierPaymentInfo objects, the service method of PaymentGroupDroplet calls initializePaymentInfos(), which creates and initializes CommerceIdentifierPaymentInfo objects for the Order, as well as the Order’s CommerceItems, ShippingGroups, and tax. These objects are then added to the CommerceIdentifierPaymentInfoContainer.
The input parameters passed into PaymentGroupDroplet determine whether the CommerceIdentifierPaymentInfo objects are created and whether the CommerceIdentifierPaymentInfoContainer is cleared before they are created. For a detailed list of these input parameters, as well as its output parameters, open parameters, and a code example, see the Adding Payment Information to Shopping Carts section of the Implementing Order Retrieval chapter of the ATG Commerce Guide to Setting Up a Store.
Submitting an Order for Checkout
The CommitOrderFormHandler (class atg.commerce.order.purchase.CommitOrderFormHandler) submits the user’s current Order for checkout. ATG Commerce includes an instance of CommitOrderFormHandler, which is located in Nucleus at /atg/commerce/order/purchase/CommitOrderFormHandler.
The form handler’s handleCommitOrder() method ensures that the user is not trying to double-submit the order by checking if the ID of the current Order is equal to the ID of the user’s last Order (in ShoppingCart.last). If the IDs are not equal, then the current Order can be submitted. The handle method then calls the OrderManager.processOrder() method, which executes the processOrder pipeline. (See Checking Out an Order below.)
If no errors occur during the validation or checkout of the Order, then handleCommitOrder() sets the submitted Order as the user’s last Order in ShoppingCart.last, and it constructs a new, empty Order and sets it as the user’s current Order in ShoppingCart.current.

