SoftSlate Commerce
Home » Documentation » HTML Documentation

Extending SoftSlate Commerce's Business Objects

One of the most common needs in terms of customizing SoftSlate Commerce is to extend the application's business objects to include additional data beyond what's supported by default. For example, in the case of a bookstore, you may need to store additional fields like subtitle, author, and publisher with your products. In other cases, for customers, you may need to track how they first found out about your store or other idiosyncratic fields.

Fortunately, SoftSlate Commerce provides three ways to extend its built-in objects. As you will see, each of the methods has its advantages and disadvantages. We hope that the first two methods are fairly self-explanatory: they require minimal or no custom programming to use. For the last method, we'll go through a detailed example.

A number of the database tables feature 'Extra' fields named extra1, extra2, extra3, etc. These fields are intended to store any custom, generic data not supported by the built-in fields. To use the various 'Extra' fields, simply populate them in the database, or by using the Administrator as you add and edit your objects.

Supported Objects. 

Advantages. 

  • The 'Extra' fields are placeholders meant to be used for any custom, generic data, so no database schema changes are necessary.
  • The 'Extra' fields get copied from product tables into the correponding fields of the order tables (e.g. sscProduct.extra1 -> sscOrderItem.extra1) with each order, so they can be used during order processing in addition to being displayed in the product catalog.
  • The 'Extra' fields can be manipulated in the Administrator alongside the other fields.

Disadvantages. 

  • It may not be clear within programming code or in the Administrator what each of the different 'Extra' fields represents.
  • The data types of the 'Extra' fields are each VARCHAR(255), so there is no flexibility in terms of the fields' data types.
  • There are a limited number of 'Extra' fields in each table that supports them, so you may run out.

The two objects that most commonly need to be extended are categories and products. For these objects, you have the option to define custom settings, which are stored for each product and category respectively in the sscProductSetting and sscCategorySetting tables.

Supported Objects. 

Advantages. 

  • Good for storing information that only needs to be used during the display of the product catalog. Product settings are loaded lazily on the product page, so no database programming is required to use them.
  • The Administrator has an interface to create and modify any number of product settings for each product. (Navigate to Product Catalog -> Products -> Details -> More -> Custom Settings)
  • A similar interface, at Product Catalog -> Categories -> Details -> Custom Settings, is available for categories.

Disadvantages. 

  • Product settings are not copied into the order item objects as an order is placed, so they cannot easily be used during order processing.
  • Even if multiple products or categories have the same set of settings, you must create them individually under each individual object.

To populate sscProductSetting and sscCategorySetting with custom data related to products and categories, the easiest way may be to use the Administrator's interface. For products, this interface is found by navigating to Product Catalog -> Products -> Details -> More -> Custom Settings.

Product Settings Form.

On this screen, you find the following text input fields:

  • Code: A unique string identifying this setting with the product. On the product page, use the code to display the value of the setting. For example, if you create a setting with a code of Custom you can display it by placing this tag in a custom product.jsp template: <c:out value="${productSettings.Custom.value}"/>
  • Name: Used only in the Administrator, to explain to admin users what the setting is used for.
  • Description: Also used only in the Administrator, to explain further to admin users what the setting represents.
  • Type: Determines the data type of the setting. (Determines which field in sscProductSetting is used to store the value.)
  • Value: The value of the setting for this product.

The method is both the most flexible and powerful, and also the one that takes the most work.

Supported Objects. 

Advantages. 

  • Data can be stored as it ideally should - in the database table, with the correct data type. Queries can be designed to leverage the additional fields.
  • If you add fields to one of the product tables, adding the same fields to the corresponding order table will allow the data to be copied over automatically with each order, and it can therefore be used during order processing logic. (E.g. sscProduct.newField -> sscOrderItem.newField.)

Disadvantages. 

  • Requires creating a number of customizations to support the additional fields, including a custom Java bean, a custom Hibernate mapping, and custom Administrator screens. (Much of the code is designed to support additional fields generically, however.)
  • The table can get large if a large number of additional fields are required, possibly affecting performance or maintainability.

Let's go through an example of adding a field to a database table. In this example, we'll imagine we are running a bookstore, and that we've decided to add a field to sscProduct to store each book's author.

Example 18.1. Extending the Product Object by Adding a Field to sscProduct

  1. Create a new class that extends the built in com.softslate.commerce.businessobjects.product.ProductBean class. To keep things clean, we strongly recommend you place all your custom classes in a separate Java package. We'll call our class CustomProduct and we'll put it in a new package named com.softslate.commerce.demo . Here's the source code for our new class:

    									
    package com.softslate.commerce.demo;
    
    import com.softslate.commerce.businessobjects.product.ProductBean;
    
    public class CustomProduct extends ProductBean {
    	
    	private static final long serialVersionUID = 6874908321131548936L;
    	
    	String author = null;
    
    	public String getAuthor() {
    		return author;
    	}
    
    	public void setAuthor(String author) {
    		this.author = author;
    	}
    
    }
    									

    Note that we are extending the built-in com.softslate.commerce.businessobjects.product.ProductBean class. Strictly speaking, you don't have to extend the built-in class, but you must implement the com.softslate.commerce.businessobjects.product.Product interface.

  2. Create the Hibernate mapping file for the new class. The Hibernate mapping file tells Hibernate how to map a class' properties to the columns of the database table it corresponds to. Name the file CustomProduct.hbm.xml, and place it next to the new CustomProduct.class class. Put the following into the contents of the file (note the "extends" attribute):

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
    	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>						
    	<subclass 
    		name="com.softslate.commerce.demo.CustomProduct"
    		extends="com.softslate.commerce.businessobjects.product.ProductBean">
    		<property name="author" length="255"/>
    	</subclass>
    </hibernate-mapping>
    									

    If you are adding more than one property to your extended class, include all of them inside the <subclass> tag.

    As of version 3.0 there is no need to add a lazy="false" attribute to the Hibernate mapping (all the built in classes have the attribute set as false by default).

  3. Now add the new column to the product database table:

    									
    ALTER TABLE sscProduct ADD author VARCHAR(255);
    									
  4. Update the product database table's class field to use the new custom class. This tells Hibernate to instantiate instances of the new class when loading data from the database:

    									
    UPDATE sscProduct SET class = 'com.softslate.commerce.demo.CustomProduct';
    									
  5. In the /WEB-INF/src/appComponents-custom.properties file, add a new property for the customization. In it set the value of the productImplementer property with the fully-qualified classname of our new custom class.

    									
    productImplementer = com.softslate.commerce.demo.CustomProduct
    									

    This tells the application to load the CustomProduct.hbm.xml file as part of the Hibernate initialization process.

  6. To display our new author field, first put some data into the new column of the database:

    									
    UPDATE sscProduct SET author = 'Truman Capote' WHERE productID = 1;
    									
  7. Then, create a custom version of the product.jsp JSP template in the /WEB-INF/layouts/custom/product directory. Paste some JSP code into the custom template that displays the value of the new field if it is defined:

    									
    <c:if test="${!empty product.author}">
    	<tr>
    		<td class="productLabel" valign="top" nowrap="nowrap">
    			Author:
    		</td>
    		<td class="productData" valign="top">
    			<bean:write name="product" property="author"/>
    		</td>
    	</tr>
    </c:if>
    									
  8. Finally, restart your application server or reload the application for your changes to take effect.

After extending the product object to add new properties, you may need to make them accessible in the Administrator so they can be viewed and edited there. The following example takes us through the steps required to add a new field to the Administrator interface.

Example 18.2. Adding a New Product Field to the Administrator Screens

  1. Create a new class that extends the built in com.softslate.commerce.administrator.product.ProductForm class. This will handle the processing and display of the the control screen in the administrator. We'll call our class CustomProductForm and we'll put it in a package named com.softslate.commerce.demo . Here's the source code for our new CustomProductForm class:

    									
    package com.softslate.commerce.demo;
    
    import java.util.Arrays;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.apache.struts.action.ActionErrors;
    import org.apache.struts.action.ActionMapping;
    import org.apache.struts.action.ActionMessage;
    import org.apache.struts.action.ActionMessages;
    
    import com.softslate.commerce.administrator.product.ProductForm;
    
    /**
     * Adding author field
     * 
     * @author David Tobey
     */
    public class CustomProductForm extends ProductForm {
    
    	private static final long serialVersionUID = 1571534730516598703L;
    
    	static Log log = LogFactory.getLog(CustomProductForm.class);
    
    	// Add the new field to the list of fields
    	private String[] fields = { "productID", "code", "name", "keywords",
    			"shortDescription", "description", "isActive", "unitCost",
    			"unitPrice", "altPrice", "weight", "header", "footer", "isTaxed",
    			"smallImage", "mediumImage", "largeImage", "extra1", "extra2",
    			"extra3", "extra4", "extra5", "primaryCategoryID",
    			"manufacturerID", "productOrder", "author" };
    
    	// Add a human readable label for it
    	private String[] fieldLables = { "Product ID", "Code", "Name", "Keywords",
    			"Short Desc", "Description", "Active", "Cost", "Price",
    			"Alt Price", "Weight", "Header", "Footer", "Taxed", "Small Image",
    			"Medium Image", "Large Image", "Extra 1", "Extra 2", "Extra 3",
    			"Extra 4", "Extra 5", "Pri Category", "Manufacturer", "Order",
    			"Author" };
    
    	// Should it be displayed on the control screen by default? Yes.
    	private String[] displayFields = { "code", "name", "isActive", "unitPrice",
    			"productOrder", "author" };
    
    	private String[] searchableFields = { "code", "name", "keywords",
    			"shortDescription", "extra1", "extra2", "extra3", "extra4",
    			"extra5", "author" };
    
    	// Need a property for the control screen's power mode - a String[]
    	private String[] author = null;
    
    	public String[] getAuthor() {
    		return author;
    	}
    
    	public void setAuthor(String[] author) {
    		this.author = author;
    	}
    
    	public String[] getDisplayFields() {
    		return displayFields;
    	}
    
    	public void setDisplayFields(String[] displayFields) {
    		this.displayFields = displayFields;
    	}
    
    	public String[] getFieldLables() {
    		return fieldLables;
    	}
    
    	public void setFieldLables(String[] fieldLables) {
    		this.fieldLables = fieldLables;
    	}
    
    	public String[] getFields() {
    		return fields;
    	}
    
    	public void setFields(String[] fields) {
    		this.fields = fields;
    	}
    
    	public String[] getSearchableFields() {
    		return searchableFields;
    	}
    
    	public void setSearchableFields(String[] searchableFields) {
    		this.searchableFields = searchableFields;
    	}
    
    	// Let's say we must have an author - so let's add it to the validation
    	public ActionErrors validate(ActionMapping mapping,
    			HttpServletRequest request) {
    		if (log.isDebugEnabled())
    			log.debug("Starting validation.");
    		setProperties();
    		// Run the original validations
    		ActionErrors errors = super.validate(mapping, request);
    		if (getProductID() != null) {
    			for (int i = 0; i < getProductID().length; i++) {
    				if (Arrays.asList(getDisplayFields()).contains("code")) {
    					if (getAuthor().length < i + 1 || getAuthor()[i] == null
    							|| getAuthor()[i].equals("")) {
    						errors.add(ActionMessages.GLOBAL_MESSAGE,
    								new ActionMessage("errors.required", "Author"));
    					}
    				}
    			}
    		}
    		return errors;
    	}
    }
    									
  2. Similarly, create a new class that extends the built in com.softslate.commerce.administrator.product.ProductAddEditForm class. This will handle the processing and display of the the product detail screen in the administrator. We'll call our class CustomProductAddEditForm . Here's the source code for this class:

    
    package com.softslate.commerce.demo;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.apache.struts.action.ActionErrors;
    import org.apache.struts.action.ActionMapping;
    import org.apache.struts.action.ActionMessage;
    import org.apache.struts.action.ActionMessages;
    
    import com.softslate.commerce.administrator.product.ProductAddEditForm;
    
    /**
     * Adding author property
     * 
     * @author David Tobey
     * 
     */
    public class CustomProductAddEditForm extends ProductAddEditForm {
    
    	private static final long serialVersionUID = 4589930821507654940L;
    
    	static Log log = LogFactory.getLog(CustomProductAddEditForm.class);
    
    	private String author = null;
    
    	public String getAuthor() {
    		return author;
    	}
    
    	public void setAuthor(String author) {
    		this.author = author;
    	}
    
    	public ActionErrors validate(ActionMapping mapping,
    			HttpServletRequest request) {
    		if (log.isDebugEnabled())
    			log.debug("Starting validation.");
    		initializeProperties(mapping, request);
    		super.validate(mapping, request);
    		if (getCode() == null || getCode().equals("")) {
    			getErrors().add(ActionMessages.GLOBAL_MESSAGE,
    					new ActionMessage("errors.required", "Author"));
    		}
    		return getErrors();
    	}
    }
    									
  3. Now let's tell Struts to use our new form classes instead of the defaults. Add the following Action Form definitions to the <form-beans> section of /WEB-INF/conf/administrator/core/struts-config-custom.xml:

    		<!-- Adding an author field to the product admin screens  -->
    		<form-bean
    			name="productAddEditForm"
    			type="com.softslate.commerce.demo.CustomProductAddEditForm">
    		</form-bean>
    		<form-bean
    			name="productForm"
    			type="com.softslate.commerce.demo.CustomProductForm">
    		</form-bean>
    									
  4. Next is to add the HTML form elements for the new field to our JSP templates. Let's start with the product detail screen. The JSP template responsible for it is /WEB-INF/templates/administrator/default/product/productFormGuts.jsp. We want to create a custom version of that file, so create a new file of the same name in the custom directory: /WEB-INF/templates/administrator/custom/product/productFormGuts.jsp

    In our custom version of productFormGuts.jsp, place the following content to display a text box for the new author field. Note we'll include the original JSP file to avoid duplication:

    									
    <%@ include file="/WEB-INF/layouts/default/core/tagDefinitions.jsp" %>
    
    <!-- Start custom productFormGuts.jsp -->
    <tr>
    	<td class="genericLabel">Author:</td>
    	<td>
    		<html:text maxlength="100" name="productAddEditForm" property="author"/>
    	</td>
    </tr>
    <tr>
    	<td>
    		 
    	</td>
    	<td class="genericData">
    		Enter the author of this book.
    		<br />
    		<br />
    	</td>
    </tr>
    
    <jsp:include page="/WEB-INF/templates/administrator/default/product/productFormGuts.jsp"/>
    
    <!-- End custom productFormGuts.jsp -->
    									
  5. Next is the control screen for products. The JSP template responsible for displaying the product fields on that screen is /WEB-INF/templates/administrator/default/product/productFieldColumns.jsp. We want to use the same file, but just add some new logic for the author field. So let's place a copy of productFieldColumns.jsp in the custom directory: /WEB-INF/templates/administrator/custom/product/productFieldColumns.jsp

    In our copy of productFieldColumns.jsp, add the following lines in the appropriate spots in that file to display the new author field, both when "Power Edit" is on and when it is off. (Some analysis of the JSP tags is necessary here!)

    When Power Edit is on:

    									
    <logic:equal name="field" value="author">
    	<input type="text" size="15" maxlength="100" 
    		name="<bean:write name="field"/>" 
    		value="<bean:write name="item" 
    		property="<%= field %>"/>" 
    		class="genericGridData"/>
    </logic:equal>
    									

    When Power Edit is off:

    									
    <logic:equal name="field" value="partNumber">
    	<bean:write name="item" property="<%= field %>"/>
    </logic:equal>
    									
  6. Restart your application server or reload the application for your changes to take effect.

Copyright © 2009-2017 SoftSlate, LLC. All Rights Reserved.

Powered by SoftSlate Commerce

Foraker Design