Elastic Path Commerce Development

Extending Commerce Manager

Extending Commerce Manager

Commerce Manager's existing UI can be extended to display information and accommodate extended data objects from Commerce Engine. Commerce Manager UI extensions utilize Eclipse Extension Points.

Commerce Manager Pattern Catalog

The Commerce Manager Pattern Catalog offers working examples of all Commerce Manager extension types. The catalog can be loaded into /extensions as a standalone plugin.

When developing a new extension point, it is strongly recommended to use one of the working examples in the catalog as a starting point and modify it to suit your needs.

Creating an Extended Plugin

All extensions are created as a plugin in the extensions/cm/ext-cm-modules/ext-plugins folder, and extend the plugin in which the UI element you want to extend exists. For example, if you want to extend a table in the Price List Manager activity, your plugin should extend com.elasticpath.cmclient.pricelistmanager.

Your plugin should contain the following:

  • A META-INF/MANIFEST.MF file.
  • A plugin.xml in the root of the plugin's folder.
  • A pom.xml file in the root of the plugin's folder.
  • A build.properties file in the root of the plugin's folder.
  • Your extended Java classes, typically in a /src/main/java/com/elasticpath/extensions folder.

These property files are discussed in the Registering Your Plugin section in detail.

Understanding Extension Points

Commerce Manager plugins provide three types of Eclipse extension points: a generic Extender, a StatePolicyExtender and a PromotionsExtender. Each out of the box plugin defines which extension points it provides in its plugin.xml file.

Each extender refers to an .exsd schema located in com.elasticpath.cmclient.core, which defines which fields are needed for an extension point contribution to be recognized as valid.

Extender

The generic Extender is provided by all out of the box plugins as follows:

<extension-point id="Extender" name="Extender" schema="../com.elasticpath.cmclient.core/schema/extender.exsd"/>
        
Extender is used to extend the following functionality:
  • Tables (Additional Columns)
  • Editors (New Sections)
  • Editors (New Pages)
  • Pages (New Sections)
  • Dialogs/Wizards

State Policy Extender

The State Policy Extension Point is designed to handle specific information around extending and creating new state policy determiners. State Policy provides its own extension point and schema in all plugins' plugin.xml as follows:

<extension-point id="StatePolicyExtender" name="StatePolicyExtender" schema="../com.elasticpath.cmclient.core/schema/statePolicyExtender.exsd"/>
        

For more information, see State Policies.

Promotions Extender

The Promotions Extension Point is designed to handle specific information around extending and creating promotion rules. Promotions can only be extended from the com.elasticpath.cmclient.store plugin and also has its own extension point, defined within store's plugin.xml:

<extension-point id="PromotionExtender" name="PromotionExtender"   schema="../com.elasticpath.cmclient.core/schema/promotionExtender.exsd"/>
        

Defining an Extension Point in an Extended Plugin

In your plugin's plugin.xml, you will need to define an extension point using the .exsd schemas and Extenders above. Regardless of the type of extension point, when referring to an extender, the nomenclature is always a particular plugin's Extender class.

The basic requirements for defining an extension point in your plugin.xml file are as follows:

  • An <extension> element, which has a point attribute.
    • point should refer to the Extender class of the plugin you wish to extend.
  • A child element of <extension> which defines the type of extension you are trying to create. It can be one of the following:
    Element Description Attributes
    <Page> Adds a new page to an Editor.

    editorName – The Editor to add the page to.

    className – Where the code for the extended or additional page is found. This must refer to a class that implements com.elasticpath.cmclient.core.helpers.extenders.EpPageCreator.

    <TableColumn> Adds a column to a table.

    table – The Table to add a column to.

    className – Where the code for the extended table is found. This must refer to a class that implements com.elasticpath.cmclient.core.helpers.extenders.EpTableColumnCreator.

    <Section> Adds a section to a page.

    pageId – The Page to add the section to.

    className – Where the code for the extended page section is found. This must refer to a class that implements com.elasticpath.cmclient.core.helpers.extenders.EpSectionCreator.
    <Dialog> Adds a new dialog.

    dialogName – The class name of the of the Dialog to attach to. This dialog must extend AbstractEpDialog.

    className – Where the code for the additional dialog is found. This must refer to a class that implements com.elasticpath.cmclient.core.helpers.extenders.DialogExtension.

    <Determiners> Adds a new State Policy Determiner. For more on creating State Policy Determiners, see State Policies.

    policyToApplyTo – The class name of the policy to extend.

    containerName – The policy container name.

    className – Where the code for the additional or extended State Policy Determiner is found. This must refer to a class that implements com.elasticpath.cmclient.policy.StateDeterminer.

Examples of all extension points can be found in the Commerce Manager Pattern Catalog.

Example: A TableColumn Extension Point

The following example defines an extension point for a new table column in the catalog plugin's BrowseProductListView table:

<extension point="com.elasticpath.cmclient.catalog.Extender">
  <TableColumn
      table="BrowseProductListView"
      className="com.elasticpath.extensions.table.ExampleTableColumn"/>
</extension>          
        

Example: A Page Extension Point

EpPageCreator and EpSectionCreator are all implemented as an inner class to your extension class, typically named Creator. The extension declaration for these therefore refers to the Creator class directly as follows:

<extension point="com.elasticpath.cmclient.pricelistmanager.Extender">
  <Page
    editorName="PriceListEditor"
    className="com.elasticpath.extensions.page.ExamplePage$Creator"/>
</extension>          
        

Promotions Extension Points

The Promotions extension point follows a slightly different pattern. Within an <extension>, you must define all of the following:

Element Description Attributes
<Messaging> Name of the extended messaging class.

className – where the code for the extended Messaging class can be found. This must refer to a class that implements com.elasticpath.cmclient.core.helpers.extenders.MessageReader.

<Widget> Name of the Widget extension class.

className – where the code for the extended Widget class can be found. This must refer to a class that implements com.elasticpath.cmclient.core.helpers.extenders.PromotionWidgetCreator.

Example: A Promotions Extension Point

An example of a definition for a Promotions extension point in an extended store plugin's plugin.xml file is as follows:

<extension point="com.elasticpath.cmclient.store.Extender">
    <Messaging className="com.elasticpath.extensions.promotions.ExampleMessaging"></Messaging>
    <Widget className="com.elasticpath.extensions.promotions.ExampleWidget"></Widget>
</extension>            
          

Condition Builder Extension Points

Element Description Attributes
ConditionRowCompositeCreatorFactory Name of the factory class extension plugin used to create ConditionRowComposites className – where the code for the extended ConditionRowCompositeCreatorFactory class is located. This class name must refer to a class that implements com.elasticpath.cmclient.conditionbuilder.extenders.ConditionRowCompositeCreatorFactory..
ConditionModelAdapterFactory Name of the factory class extension plugin used to create ConditionModelAdapters className – where the code for the extended ConditionModelAdapterFactory class is located. This class name must refer to a class that implements com.elasticpath.cmclient.conditionbuilder.extenders.ConditionModelAdapterFactory.

Example: A Condition Builder Extension Point

The following is an example of a definition for a condition builder extension point in an extended store plugin's plugin.xml file:

 <extension point="com.elasticpath.cmclient.conditionbuilder.ConditionBuilderExtender">

        <ConditionRowCompositeCreatorFactory
                className="com.elasticpath.cm.conditionbuilder.ExtConditionRowCompositeCreatorFactory">

        </ConditionRowCompositeCreatorFactory>
        <ConditionModelAdapterFactory
            className="com.elasticpath.cm.conditionbuilder.ExtConditionModelAdapterFactory">

        </ConditionModelAdapterFactory>
    </extension>

    <extension point="com.elasticpath.cmclient.core.ModelExtender">
        <Condition
            className="com.elasticpath.cm.conditionbuilder.ExtCondition">

        </Condition>
    </extension>

Implementing an Extended Plugin

Depending on what you are extending, your class will either implement an interface or extend an abstract class from the com.elasticpath.cmclient.core.helpers.extenders package, or extend an abstract class from com.elasticpath.cmclient.core.editors.

For full examples, see the Commerce Manager Pattern Catalog.

Extending BaseAmount

  1. To extend BaseAmount. extend the following classes at extensons/core/:
    • ExtBaseAmountDTO: Extends the BaseAmountDTO.
    • ExtBaseAmountDTOCreator: Overrides the default DTO creator to use the ExtBaseAmountDTO.
    Note: Ensure that the plugin.xml and MANIFEST.MF files are updated as required. For more information see, META-INF/MANIFEST.MF and pom.xml sections.
  2. To display the new fields from the ExtendedBaseAmountDTO, extend the dialogs and tables.

    For more information about extending tables and dialogs, see Extending Tables and Extending Dialogs.

Example Procedure

  1. To extend the base amount, extend the ExtBaseAmountDTOCreator class:
    package com.extensions.baseamount.impl;
    
    import com.elasticpath.cmclient.core.helpers.extenders.EpModelCreator;
    import com.elasticpath.common.dto.pricing.BaseAmountDTO;
    import com.elasticpath.extensions.domain.impl.ExtBaseAmountDTO;
    
    /**
     * Example Base Amount DTO model creator.
     */
    public class ExtBaseAmountDTOCreator implements EpModelCreator<BaseAmountDTO> {
    
       @Override
       public BaseAmountDTO createModel() {
          return new ExtBaseAmountDTO();
       }
       @Override
    
       public BaseAmountDTO createModel(final BaseAmountDTO other) {
          return new ExtBaseAmountDTO(other);
    
       }
    
    }
    
  2. To implement the changes, update the plugin.xml file with the following:
    <extension point="com.elasticpath.cmclient.core.ModelExtender">
        <BaseAmountDTO
                className="com.extensions.baseamount.impl.ExtBaseAmountDTOCreator"/>
    </extension>
  3. To display the changes in a dialog, extend the BaseAmountDialog class as in the following example:
    package com.extensions.baseamount.impl;
    
    import org.eclipse.swt.widgets.Text;
    
    import com.elasticpath.cmclient.core.helpers.extenders.DialogExtension;
    import com.elasticpath.cmclient.core.ui.dialog.AbstractEpDialog;
    import com.elasticpath.cmclient.core.ui.framework.EpControlFactory;
    import com.elasticpath.cmclient.core.ui.framework.IEpLayoutComposite;
    import com.elasticpath.cmclient.core.ui.framework.IEpLayoutData;
    import com.elasticpath.extensions.domain.impl.ExtBaseAmountDTO;
    
    /**
     * Example Base Amount Dialog Extension.
     */
    public class BaseAmountDialogExtension implements DialogExtension {
    
       private Text extendedText;
    
       @Override
       public void bindControls(final AbstractEpDialog dialog) {
          //not used.
       }
    
       @Override
    
       public void populateControls(final AbstractEpDialog dialog) {
          ExtBaseAmountDTO model = (ExtBaseAmountDTO) dialog.getModel();
          this.extendedText.setText(model.getSomething());
       }
       @Override
    
       public void createEpDialogContent(final IEpLayoutComposite composite, final AbstractEpDialog dialog) {
          final IEpLayoutData labelData = composite.createLayoutData(IEpLayoutData.END, IEpLayoutData.FILL);
          final IEpLayoutData fieldData = composite.createLayoutData(IEpLayoutData.FILL, IEpLayoutData.BEGINNING, true, false);
    
          composite.addLabelBoldRequired("Extended Base Amount Field:", EpControlFactory.EpState.EDITABLE, labelData);
          extendedText = composite.addTextField(EpControlFactory.EpState.EDITABLE, fieldData);
       }
    }
    
  4. Update the plugin.xml file with the following for the BaseAmountDialog class extension:
    <extension point="com.elasticpath.cmclient.pricelistmanager.Extender">
        <Dialog
            dialogName="BaseAmountDialog"
            className="com.extensions.baseamount.impl.BaseAmountDialogExtension"/>
        </extension>
  5. Override the assembler:
    package com.elasticpath.extensions.domain.impl;
    
    import org.apache.log4j.Logger;
    
    import com.elasticpath.common.dto.assembler.pricing.BaseAmountDtoAssembler;
    import com.elasticpath.common.dto.pricing.BaseAmountDTO;
    
    /**
     * Extension BaseAmount DTO Assembler.
     */
    public class ExtBaseAmountDtoAssembler  extends BaseAmountDtoAssembler {
       private static final Logger LOG = Logger.getLogger(ExtBaseAmountDtoAssembler.class);
    
    
       @Override
       public BaseAmountDTO getDtoInstance() {
          LOG.warn("using extension assembler");
          return new ExtBaseAmountDTO();
       }
    }
    Ensure that the spring bean for the assembler is overridden as follows:
    <bean id="baseAmountDtoAssembler" class="com.elasticpath.extensions.domain.impl.ExtBaseAmountDtoAssembler">
       <property name="baseAmountFactory" ref="baseAmountFactory"/>
    </bean>
Note:

Follow the Commerce Manger extension guidelines and ensure that your extension plugin is started with the webapp, and that the plugin's MANIFEST.MF uses the com.elasticpath.cmclient.core package to extend the ModelCreator class, and com.elasticpath.cmclient.pricelistmanager package for the table and dialog extensions.

Extending Tables

Tables can be extended by adding a column heading and column values. You cannot add an entirely new table to Commerce Manager, only extend an existing table.

To extend a table, implement EPTableCreator and implement its methods:

ExampleTable implements EPTableCreator {
...
}
        

Extending Sections

Sections should extend com.elasticpath.cmclient.core.editors.AbstractCmClientEditorPageSectionPart.

Section extensions should also implement com.elasticpath.cmclient.core.helpers.extenders.EpSectionCreator as a static inner class, Creator. Creator's one method, instantiateSection(), should return an instance of your extended section:

ExampleSection extends AbstractCmClientEditorPageSectionPart {
          
  ...
          
    public static class Creator implements EpSectionCreator {
          
    public AbstractCmClientFormSectionPart instantiateSection(FormPage formPage, AbstractCmClientFormEditor abstractCmClientFormEditor) {
          
      return new ExampleSection(...);
    }
  }
}
        

Extending Pages

Pages should extend com.elasticpath.cmclient.core.editors.AbstractCmClientEditorPage.

Page extensions should also implement com.elasticpath.cmclient.core.helpers.extenders.EpPageCreator as a static inner class, Creator. Creator's one method, instantiatePage(), should return an instance of your extended page:

ExamplePage extends AbstractCmClientEditorPage {
          
  ...
          
    public static class Creator implements EpPageCreator {
    public AbstractCmClientEditorPage instantiatePage(AbstractCmClientFormEditor abstractCmClientFormEditor) {
          
      return new ExamplePage(...);
          
    }
  }          
}
        

Extending Dialogs

Dialogs should implement com.elasticpath.cmclient.core.helpers.extenders.DialogExtension and its methods:

public class ExampleDialog implements DialogExtension {
  ...
}
        

Extending State Policy Determiners

State Policy Determiner extensions should implement com.elasticpath.cmclient.policy.StateDeterminer and its method, determineState(). determineState() accepts a PolicyActionContainer object and must return EpState.READ_ONLY, EpState.EDITABLE, or EpState.DISABLED:

 public class ExampleDeterminer implements StateDeterminer {
/**
 *  Determine the state.
 * @param policyActionContainer
 * @return the state.
 */
  public EpControlFactory.EpState determineState(PolicyActionContainer policyActionContainer) {
      return EpControlFactory.EpState.READ_ONLY;
  }
}
        

For more details on creating or extending new state policies, see Creating a State Policy Extension Point.

Extending Promotion Rules

Rather than an outright extension of an existing promotion rule, promotions extensions typically take the form of adding a new kind of promotion rule to Commerce Manager. For more information on extending promotion rules, see Promotions.

Connecting to a Commerce Engine Database via an Extended Domain Object

In general, we do not recommend trying to directly consume anything from a Commerce Engine database via Commerce Manager extensions. Instead, feed in an extended domain object into one of the extension points described above.

Registering Your Plugin

Before starting up your extended plugin, you must reference it in the following files. The name you reference your plugin by is the Bundle-SymbolicName defined its META-INF/MANIFEST.MF file. After adding your plugin to the following files, rebuild your project using mvn clean install from commerce-extensions/.

META-INF/MANIFEST.MF

As with all OSGi bundles, your plugin must have a MANIFEST.MF file whit the following properties defined:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: table-examples
Bundle-SymbolicName: pattern-catalog;singleton:=true
Bundle-Version: 0.0.0.qualifier
Bundle-Vendor: %providerName
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
Bundle-Localization: plugin
Require-Bundle:  org.eclipse.core.runtime,
com.elasticpath.extensions.cm.ext-cm-libs,
com.elasticpath.cmclient.policy,
org.eclipse.core.databinding,
org.eclipse.rap.ui,
org.eclipse.rap.ui.forms
        
Note: The Bundle-SymbolicName you define is what you will refer to your plugin by in all other configuration files.

pom.xml

Your plugin should be listed in commerce-extensions/cm/ext-cm-plugins pom.xml file as a <module>:

<modules>
  <module>your-extended-plugin</module>
  ...
</modules>
        

feature.xml

Your plugin should be referenced in commerce-extensions/cm/ext-cm-webapp's feature.xml as follows:

<plugin id="your-extended-plugin" download-size="0" install-size="0" version="0.0.0" unpack="false"/>
        

config.ini

Add your new plugin to commerce-extensions/cm/ext-cm-webapp's config.ini as follows:

your-extended-plugin@start
        

Extensible Classes in Commerce Manager

Tables

All extensible tables extend a class parented by com.elasticpath.cmclient.core.views.AbstractCmClientView.

Sections

All extensible sections extend a class parented by com.elasticpath.cmclient.core.editors.AbstractCmClientEditorPage.

Pages

All extensible pages extend a class parented by com.elasticpath.cmclient.core.editors.AbstractCmClientFormEditor.

Dialogs

All extensible dialogs extend a class parented by com.elasticpath.cmclient.core.ui.dialog.AbstractEpDialog.

Including non-OSGi Libraries and Dependencies

Any new plugins, or plugins not found in the existing out of the box Commerce Manager need to be included in the deployment files. If your plugin depends on non-OSGi bundles, or additional libs, these have to be included as well.

For detailed instructions on including non-OSGi bundles or other external dependencies, see Adding Non-Plugin Modules to Commerce Manager.