Broadleaf Microservices
  • v1.0.0-latest-prod

Catalog Provider

Overview

Provider for interfacing with Catalog entities. This is used to populate information on the cart items from a trusted source since the frontend is the typical caller of Cart Operations and any item details it provides are suspect.

Usage

Catalog info is used to:

  • Perform item configuration validation. This is to ensure that required ProductOptions have correct values (for attribute choices) or quantities (for item choices)

  • Determine item-specific merging strategies.

    • If the same item is added to the cart multiple times, some products should not be merged into the same line item.

    • See CartItemMergingService for more info.

  • Determine item-specific inventory check and reservation strategies

    • Should this item have inventory availability checked on add-to-cart?

    • Should this item have inventory reserved on add-to-cart? or during checkout?

  • Determine item-specific fulfillment flat rates

    • Some items can have specific rates for different fulfillment types

  • Update name and description translations if the user switches locales.

  • Hydrate items when passed to the offer and pricing engines, which need items to be richer than a persisted cart should maintain

Default Implementation Details

The default implementation, ExternalCatalogProvider, is designed to interact with the Catalog Browse Services, which fully hydrates the entire product hierarchy for 1 or more requested products. This ensures that the fewest number of HTTP requests are made as possible and Cart Operations does not need to handle as much of the complexity related to the Product domain hierarchy. Catalog Browse will also hydrate correct pricing from the Pricing Services as a starting point, which can further simplify Cart Operations' logic for some cases.

Configuration

ExternalCatalogProperties defines the properties used to configure ExternalCatalogProvider. These include:

  • broadleaf.cartoperation.catalogprovider.url: The base url for an external catalog service.

  • broadleaf.cartoperation.catalogprovider.productsUri: The context path for reading product information. This is appended to the url property.

  • broadleaf.cartoperation.catalogprovider.variant-hydration-behavior: What behavior to use for hydrating variants onto requested products.

    • This is DefaultProductVariantHydrationBehavior.NONE by default since only specific variants are ever added to the cart, causing any others to be extraneous information. This will improve performance if a Product has many variants.

    • Since 2.3.0. Requires Catalog Service 2.3.0 for full functionality.

Example of building request from properties
UriComponentsBuilder.fromHttpUrl(properties.getUrl())
        .path(properties.getProductsUri())
        .queryParam("productIds", productIds)
        .toUriString();

Integrating with a Non-Broadleaf Catalog Service

To resolve catalog items from an external ERP, CMS, or PIM, register a custom implementation of CatalogProvider.

Request Construction

Your custom provider must extract the lookup criteria from the method parameters of retrieveCatalogItems(Collection<CatalogItemRequest> requests, PriceContext priceContext, ContextInfo context).

  • Product & Variant IDs: Loop through the Collection<CatalogItemRequest> parameter. Extract the catalog lookup keys (e.g. product IDs via request.getProductId() and/or variant IDs via request.getVariantId()).

  • Locale & Currency: Extract locale via priceContext.getLocale() and target currency via priceContext.getCurrency() to query language-specific product copy or currency-matched rates from your external PIM.

  • Tenant Scopes: Read multi-tenancy and contextual metadata from ContextInfo.

Custom CatalogItem Domain & Null Base Prices

Your implementation should define a domain class that implements the CatalogItem interface. This class holds the shape of the external catalog record.

If your external catalog doesn’t provide a base price, getPriceInfo() must still return a non-null PriceInfo — just set its price field to null.

Example CatalogItem implementation with no base price available
public class MyExternalCatalogItem implements CatalogItem {
    private String id;
    private String sku;
    private String pricingKey;

    @Override public String getId() { return id; }
    @Override public String getSku() { return sku; }
    @Override public String getPricingKey() { return pricingKey; }

    @Override
    public PriceInfo getPriceInfo() {
        // This external catalog doesn't provide a base price for this item
        PriceInfo priceInfo = new PriceInfo();
        priceInfo.setPriceType(BASE_PRICE);
        priceInfo.setPrice(null);
        return priceInfo;
    }
}

Mapping CatalogItems to CartItems

Implement CartItemCatalogInformationService to map your CatalogItem fields onto the CartItem.

At minimum, your implementation must set the following on the CartItem:

  • CartItem.setSku(String), from CatalogItem.getSku(). Inventory availability checks key their lookups by this SKU; leaving it unset means the item always resolves as inventory-unavailable.

  • A Map<String, PriceInfo> keyed by SKU, from CatalogItem.getPriceInfo(), stored on CartItem.getInternalAttributes() under CartItemAttributeConstants.Internal.DIRECT_SKU_PRICE_INFOS. Without this, no SKU-based pricing target is ever built for the item, so it’s never priced. PriceInfo.getPriceType() must be non-blank (e.g. BASE_PRICE) even when PriceInfo.getPrice() is null.

If your external catalog contains custom properties, this is also where you’d map and persist those as cart item attributes.

You’ll also need a custom CartItemConfigurationService to validate the mapped cart item against your catalog data — for example, confirming a requested configuration (selected options or choices) is actually valid, enforcing quantity thresholds, etc.