Announcement: You can find the guides for Commerce 7.5 and later on the new Elastic Path Documentation site. The Developer Center continues to support Commerce 6.13.0 through 7.4.1.Visit new site

2 - Extending the Storefront

2 - Extending the Storefront

In the Storefront, Form Bean classes represent the forms a customer fills out. Form Bean classes store the information a user provides before passing the information into the Elastic Path Core.

In this section, you will extend the Storefront and create a T-shirt form bean to store the personalized T-shirt's text.

Creating the personalized T-shirt form bean

To create the T-shirt form bean:

  1. Navigate to the ext-storefront project, found in the extensions/storefront directory.
  2. In the ext-storefront project's src/main/java directory (create java folder if it does not exist), create a new package named com.extensions.tshirt.sfweb.formbean
  3. In com.extensions.tshirt.sfweb.formbean, create an interface named TshirtFormBean and add the following code:
                      package com.extensions.tshirt.sfweb.formbean;
    
    import java.util.Map;
    
    import com.elasticpath.common.dto.ShoppingItemDto;
    import com.elasticpath.sfweb.formbean.EpFormBean;
    
    /**
     * Defines the form shoppers fill out to personalize their T-shirts.
     */
    public interface TshirtFormBean extends EpFormBean {
    
    	/**
    	 * Returns a T-shirt's front text.
    	 *
    	 * @return The T-shirt's front text
    	 */
    	String getFrontText();
    
    	/**
    	 * Sets the T-Shirt's front text.
    	 *
    	 * @param frontText - a String to set to this property
    	 */
    	void setFrontText(String frontText);
    
    	/**
    	 * Returns a T-shirt's back text.
    	 *
    	 * @return The T-shirt's back text
    	 */
    	String getBackText();
    
    	/**
    	 * Sets the T-Shirt's back text.
    	 *
    	 * @param backText - a String to set to this property
    	 */
    	void setBackText(String backText);
    
    	/**
    	 * Returns a map of T-shirt fields.
    	 *
    	 * @return The fields
    	 */
    	Map<String, String> getAsItemFields();
    
    	/**
    	 * Initializes all T-shirt fields from the fields in the {@code ShoppingItem}.
    	 *
    	 * @param shoppingItem - The item's ShoppingItemDto
    	 */
    	void initFromShoppingItemDto(ShoppingItemDto shoppingItem);
    }
                   
  4. In com.extensions.tshirt.sfweb.formbean, create a package named impl
  5. In com.extensions.tshirt.sfweb.formbean.impl, create a new class named TshirtFormBeanImpl and add the following code:
                      package com.extensions.tshirt.sfweb.formbean.impl;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import com.extensions.tshirt.sfweb.formbean.TshirtFormBean;
    
    import com.elasticpath.common.dto.ShoppingItemDto;
    import com.elasticpath.sfweb.formbean.impl.EpFormBeanImpl;
    
    /**
     * Implements {@link TshirtFormBean}.
     */
    public class TshirtFormBeanImpl extends EpFormBeanImpl implements TshirtFormBean {
    
    	private static final long serialVersionUID = 1L;
    
    	/**
    	 * Key for getting a Tshirt's front text.
    	 */
    	public  static final String TSHIRT_FRONT_TEXT_KEY = "Front text";
    
    	/**
    	 * Key for getting a Tshirt's back text.
    	 */
    	public static final String TSHIRT_BACK_TEXT_KEY = "Back text";
    
    	private String frontText;
    	private String backText;
    
    	@Override
    	public String getBackText() {
    		return backText;
    	}
    
    	@Override
    	public String getFrontText() {
    		return frontText;
    	}
    
    	@Override
    	public void setBackText(final String backText) {
    		this.backText = backText;
    	}
    
    	@Override
    	public void setFrontText(final String frontText) {
    		this.frontText = frontText;
    	}
    
    	@Override
    	public Map<String, String> getAsItemFields() {
    		HashMap<String, String> map = new HashMap<String, String>();
    		map.put(TSHIRT_BACK_TEXT_KEY, this.backText);
    		map.put(TSHIRT_FRONT_TEXT_KEY, this.frontText);
    		return map;
    	}
    
    	@Override
    	public void initFromShoppingItemDto(final ShoppingItemDto shoppingItem) {
    		if (shoppingItem == null) {
    			return;
    		}
    
    		Map<String, String> itemFields = shoppingItem.getItemFields();
    		this.frontText = itemFields.get(TSHIRT_FRONT_TEXT_KEY);
    		this.backText = itemFields.get(TSHIRT_BACK_TEXT_KEY);
    	}
    }
                   

Extending Storefront Classes

You need to extend a few Storefront classes to include the t-shirt form bean in the checkout process:

ShoppingItemFormBean

The ShoppingItemFormBean is the top level form bean for storing product information.

To include the personalized text fields from the t-shirt form bean:

  1. In com.extensions.tshirt.sfweb.formbean, create an interface named ExtShoppingItemFormBean and add the following code:
                         package com.extensions.tshirt.sfweb.formbean;
    
    import com.elasticpath.sfweb.formbean.ShoppingItemFormBean;
    
    /**
     * Adds getTshirtFields() method to the ShoppingItemFormBean.
     */
    public interface ExtShoppingItemFormBean extends ShoppingItemFormBean {
    
    	/**
    	 * Returns the special fields for a T-shirt.
    	 *
    	 * @return a TshirtFormBean with the T-shirt's fields.
    	 */
    	TshirtFormBean getTshirtFields();
    }
                      
  2. In com.extensions.tshirt.sfweb.formbean.impl create a class named ExtShoppingItemFormBeanImpl and add the following code:
                         package com.extensions.tshirt.sfweb.formbean.impl;
    
    import com.extensions.tshirt.sfweb.formbean.ExtShoppingItemFormBean;
    import com.extensions.tshirt.sfweb.formbean.TshirtFormBean;
    
    import com.elasticpath.sfweb.formbean.impl.ShoppingItemFormBeanImpl;
    
    /**
     * Implements {@link ExtShoppingItemFormBean}.
     */
    public class ExtShoppingItemFormBeanImpl extends ShoppingItemFormBeanImpl implements ExtShoppingItemFormBean {
    
    	private static final long serialVersionUID = 1L;
    
    	private final TshirtFormBean tshirtFormBean = new TshirtFormBeanImpl();
    
    	@Override
    	public TshirtFormBean getTshirtFields() {
    		return tshirtFormBean;
    	}
    }
                      

ShoppingItemFormBeanContainerFactoryImpl

The ShoppingItemFormBeanContainerFactoryImpl class builds cart update form beans from the ShoppingItemFormBean.

To create cart update form beans from ExtShoppingItemFormBean:

  1. In the ext-storefront project's src/main/java directory, create a new package named com.extensions.tshirt.sfweb.controller.impl
  2. In com.extensions.tshirt.sfweb.controller.impl, create a class named ExtShoppingItemFormBeanContainerFactoryImpl and add the following code:
                         package com.extensions.tshirt.sfweb.controller.impl;
    
    import java.util.Collections;
    import java.util.Map;
    
    import com.extensions.tshirt.sfweb.formbean.ExtShoppingItemFormBean;
    
    import com.elasticpath.common.dto.ShoppingItemDto;
    import com.elasticpath.domain.catalog.Price;
    import com.elasticpath.domain.catalog.Product;
    import com.elasticpath.domain.catalog.ProductBundle;
    import com.elasticpath.domain.catalogview.StoreProduct;
    import com.elasticpath.domain.pricing.PriceAdjustment;
    import com.elasticpath.domain.shoppingcart.ShoppingCart;
    import com.elasticpath.sfweb.controller.ShoppingItemFormBeanContainerFactory;
    import com.elasticpath.sfweb.controller.impl.ShoppingItemFormBeanContainerFactoryImpl;
    import com.elasticpath.sfweb.formbean.ShoppingItemFormBean;
    import com.elasticpath.sfweb.formbean.ShoppingItemFormBeanContainer;
    import com.elasticpath.sfweb.formbean.impl.CartFormBeanImpl;
    
    /**
     * Extended ShoppingItemFormBeanContainerFactoryImpl that utilizes the {@link ExtShoppingItemFormBean}.
     */
    public class ExtShoppingItemFormBeanContainerFactoryImpl extends ShoppingItemFormBeanContainerFactoryImpl
    		implements ShoppingItemFormBeanContainerFactory {
    
    	@Override
    	public ShoppingItemFormBeanContainer createCartFormBean(final StoreProduct storeProduct,
    			final int quantity, final ShoppingCart shoppingCart) {
    		String defaultSkuCode = storeProduct.getDefaultSku().getSkuCode();
    
    		// BEGIN OVERRIDE ------------------------------------------------------------
    		ExtShoppingItemFormBean rootFormBean =
    				(ExtShoppingItemFormBean) createShoppingItemFormBean(shoppingCart.getStore(),
    						storeProduct, defaultSkuCode, quantity, "", 0, 0);
    		rootFormBean.getTshirtFields().initFromShoppingItemDto(null);
    		// END OVERRIDE ------------------------------------------------------------
    
    		// by default, the root form bean should always be set to be selected
    		rootFormBean.setSelected(true);
    
    		Product product = storeProduct.getWrappedProduct();
    		Map<String, PriceAdjustment> priceAdjustmentsForBundle = Collections.emptyMap();
    
    		if (product instanceof ProductBundle) {
    			ProductBundle bundle = (ProductBundle) product;
    			priceAdjustmentsForBundle = getPriceLookupFacade().getPriceAdjustmentsForBundle(bundle,
    					shoppingCart.getStore().getCatalog().getCode(), shoppingCart.getShopper());
    
    			if (bundle.getSelectionRule() != null) {
    				rootFormBean.setSelectionRule(bundle.getSelectionRule().getParameter());
    			}
    			if (bundle.isCalculated()) {
    				setPriceAndQuantityForCalculatedBundle(rootFormBean, product, shoppingCart);
    			}
    		}
    
    		addConstituentShoppingItemFormBeansFromProduct(shoppingCart,
    				rootFormBean, storeProduct, "", 1, priceAdjustmentsForBundle);
    
    		ShoppingItemFormBeanContainer cartFormBean = new CartFormBeanImpl();
    		cartFormBean.addShoppingItemFormBean(rootFormBean);
    
    		rootFormBean.setMinQty(calculateMinQty(shoppingCart, rootFormBean));
    
    		return cartFormBean;
    	}
    
    	private void setPriceAndQuantityForCalculatedBundle(
    			final ShoppingItemFormBean rootFormBean, final Product product,
    			final ShoppingCart shoppingCart) {
    		rootFormBean.setCalculatedBundle(true);
    		Price promotedPriceForSku = this.getPriceLookupFacade().getPromotedPriceForSku(
    				product.getDefaultSku(), shoppingCart.getStore(),
    				shoppingCart.getShopper(), shoppingCart.getAppliedRules());
    		if (promotedPriceForSku != null) {
    			int firstPriceTierMinQty = promotedPriceForSku.getFirstPriceTierMinQty();
    			rootFormBean.setPrice(promotedPriceForSku);
    			rootFormBean.setQuantity(firstPriceTierMinQty);
    		}
    	}
    
    	@Override
    	public ShoppingItemFormBeanContainer createCartFormBean(final ShoppingItemDto existingShoppingItemDto,
    			final ShoppingCart shoppingCart, final boolean dependent) {
    
    		final StoreProduct storeProduct = findProductByGuid(existingShoppingItemDto.getProductCode(),
    				shoppingCart.getStore());
    
    		// BEGIN OVERRIDE ------------------------------------------------------------
    		ExtShoppingItemFormBean rootFormBean = (ExtShoppingItemFormBean) createShoppingItemFormBean(
    				shoppingCart.getStore(), storeProduct, existingShoppingItemDto.getSkuCode(),
    				existingShoppingItemDto.getQuantity(), "", 0,
    				existingShoppingItemDto.getShoppingItemUidPk());
    
    		rootFormBean.setDependent(dependent);
    		rootFormBean.setPrice(existingShoppingItemDto.getPrice());
    		rootFormBean.setTotal(existingShoppingItemDto.getTotal());
    		rootFormBean.setSelected(existingShoppingItemDto.isSelected());
    		rootFormBean.getGiftCertificateFields().initFromShoppingItemDto(existingShoppingItemDto);
    		rootFormBean.getTshirtFields().initFromShoppingItemDto(existingShoppingItemDto);
    		// END OVERRIDE ------------------------------------------------------------
    
    		Product product = storeProduct.getWrappedProduct();
    		Map<String, PriceAdjustment> priceAdjustmentsForBundle = Collections.emptyMap();
    
    		if (product instanceof ProductBundle) {
    			ProductBundle bundle = (ProductBundle) product;
    			priceAdjustmentsForBundle = getPriceLookupFacade().getPriceAdjustmentsForBundle(bundle,
    					shoppingCart.getStore().getCatalog().getCode(), shoppingCart.getShopper());
    
    			if (bundle.isCalculated()) {
    				rootFormBean.setCalculatedBundle(true);
    				rootFormBean.setPrice(existingShoppingItemDto.getPrice());
    			}
    		}
    
    		addConstituentShoppingItemFormBeansFromShoppingItemDto(shoppingCart,
    				rootFormBean, existingShoppingItemDto, storeProduct, "", 1, priceAdjustmentsForBundle);
    
    		ShoppingItemFormBeanContainer cartUpdateFormBean = new CartFormBeanImpl();
    		cartUpdateFormBean.addShoppingItemFormBean(rootFormBean);
    
    		rootFormBean.setMinQty(calculateMinQty(shoppingCart, rootFormBean));
    
    		return cartUpdateFormBean;
    	}
    }
                      

ShoppingItemDtoMapper

The ShoppingItemDtoMapper transfers data between the Storefront's ShoppingItemFormBean and the Elastic Path Core's ShoppingItemDto.

To transfer data from ExtShoppingItemFormBean to the ShoppingItemDto:

  • In com.extensions.tshirt.sfweb.controller.impl, create a class named ExtShoppingItemDtoMapperImpl and add the following code:
                         package com.extensions.tshirt.sfweb.controller.impl;
    
    import com.extensions.tshirt.sfweb.formbean.ExtShoppingItemFormBean;
    
    import com.elasticpath.common.dto.ShoppingItemDto;
    import com.elasticpath.sfweb.controller.impl.ShoppingItemDtoMapperImpl;
    import com.elasticpath.sfweb.formbean.ShoppingItemFormBean;
    
    /**
     * Extended Dto mapper that includes mapping for Tshirt fields.
     */
    public class ExtShoppingItemDtoMapperImpl extends ShoppingItemDtoMapperImpl {
    
    	@Override
    	protected void doItemFieldsMapping(final ShoppingItemDto parentDto, final ShoppingItemFormBean parentBean) {
    		parentDto.setItemFields(parentBean.getGiftCertificateFields().getAsItemFields());
    
    		if (parentBean instanceof ExtShoppingItemFormBean) {
    			ExtShoppingItemFormBean formBean = (ExtShoppingItemFormBean) parentBean;
    			parentDto.setItemFields(formBean.getTshirtFields().getAsItemFields());
    		}
    	}
    }