Documentation Home

Order Submit Workflow For Heat Clinic Tutorial

NOTE: This tutorial requires you to complete the Extending Customer For Heat Clinic Tutorial first.

Hooking into the submit order workflow

First, let's look at the default checkout workflow provided by broadleaf:

<!-- Checkout Workflow Configuration -->
<bean id="blCheckoutWorkflow" class="org.broadleafcommerce.core.workflow.SequenceProcessor">
<property name="processContextFactory">
    <bean class="org.broadleafcommerce.core.checkout.service.workflow.CheckoutProcessContextFactory"/>
<property name="activities" ref="blCheckoutWorkflowActivities"/>
<property name="defaultErrorHandler">
    <bean class="org.broadleafcommerce.core.workflow.DefaultErrorHandler">
        <property name="unloggedExceptionClasses">

<bean id="blCheckoutWorkflowActivities" class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
        <ref bean="blValidateCheckoutActivity"/>
        <ref bean="blVerifyCustomerMaxOfferUsesActivity" />
        <ref bean="blValidateProductOptionsActivity" />
        <ref bean="blValidateAndConfirmPaymentActivity" />
        <ref bean="blRecordOfferUsageActivity" />
        <ref bean="blCommitTaxActivity" />
        <ref bean="blDecrementInventoryActivity" />
        <ref bean="blCompleteOrderActivity" />

This is a copy of the default workflow. You can find the default workflows in the following place in the Broadleaf codebase: core/broadleaf-framework/src/main/resources/bl-framework-applicationContext-workflow.xml

Create a new activity

We need to add a new activity to record the average heat level for a given customer. Let's create that activity. In the site project, we'll create in the com.mycompany.checkout.service.workflow package with the following contents:

public class RecordHeatRangeActivity extends BaseActivity {
    private static final Log LOG = LogFactory.getLog(RecordHeatRangeActivity.class);

    public static final int ORDER = 4500;

    public RecordHeatRangeActivity() {

    @Resource(name = "blCustomerService")
    protected CustomerService customerService;

    public ProcessContext execute(ProcessContext context) throws Exception {
        CheckoutSeed seed = (CheckoutSeed) context.getSeedData();
        Order order = seed.getOrder();
        int orderTotalHeatRating = 0;
        int productCount = 0;

        for (DiscreteOrderItem doi : order.getDiscreteOrderItems()) {
            ProductAttribute heatRating = doi.getProduct().getProductAttributes().get("heatRange");
            try {
                orderTotalHeatRating += (doi.getQuantity() * Integer.parseInt(heatRating.getValue()));
                productCount += doi.getQuantity();
            } catch (Exception e) {
                LOG.warn("Unable to parse the heat range. Product id: " + doi.getProduct().getId());

        HCCustomer customer = (HCCustomer) CustomerState.getCustomer();
        customer.setNumSaucesBought(customer.getNumSaucesBought() + productCount);
        customer.setTotalHeatRating(customer.getTotalHeatRating() + orderTotalHeatRating);
        customer = (HCCustomer) customerService.saveCustomer(customer);

        return context;

Note: You should choose org.broadleafcommerce.core.order.domain.Order, org.apache.common.logging.Log, and org.apache.common.logging.LogFactory as imports.

Notice that the activity loops through all current products in the order and assigns the appropriate heat range to the customer.

Add our activity to the workflow

We want to add our new activity between the RecordOfferUsageActivity (order is 4000) and the CommitTaxActivity (order is 5000).
In this example, within applicationContext.xml, we merge our custom activity into the blCheckoutWorkflowActivities.


<bean id="customCheckoutActivities" class="org.broadleafcommerce.core.workflow.SequenceProcessor">
    <property name="activities">
            <ref bean="recordHeatRangeActivity"/>
<bean class="org.broadleafcommerce.common.extensibility.context.merge.LateStageMergeBeanPostProcessor">
    <property name="sourceRef" value="customCheckoutActivities"/>
    <property name="targetRef" value="blCheckoutWorkflowActivities"/>


public List<?> customCheckoutActivities(RecordHeatRangeActivity recordHeatRangeActivity) {
    return Arrays.asList(recordHeatRangeActivity);

Notice that we did not have to specify the order of the RecordHeatRangeActivity because the activity itself specifies its own implicit order.

Our checkout workflow is complete. Check out the end result after checking out an order that had (1) level 6 sauce and (1) level 8 sauce:

Averaged Heat Range