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. You can find the catalog in the Tutorials repository. In the repository, expand the ep-commerce-examples
directory for this version of Commerce, select the examples
branch and then search for pattern catalog
. 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 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 Extesion 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 Extension Point in 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 attributepoint
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 createIt can be one of the following:
<Page>
Adds a new page to an Editor. Attributes are:
editorName
– The Editor to add the page toclassName
– Where the code for the extended or additional page is foundThis must refer to a class that implements
com.elasticpath.cmclient.core.helpers.extenders.EpPageCreator
<TableColumn>
Adds a column to a table. Attributes are:
table
– The Table to add a column toclassName
– Where the code for the extended table is foundThis must refer to a class that implements
com.elasticpath.cmclient.core.helpers.extenders.EpTableColumnCreator
<Section>
Adds a section to a page. Attributes are:
pageId
– The Page to add the section toclassName
– Where the code for the extended page section is foundThis must refer to a class that implements
com.elasticpath.cmclient.core.helpers.extenders.EpSectionCreator
<Dialog>
Adds a new dialog. Attributes are:
dialogName
– The class name of the of the Dialog to attach toThis dialog must extend
AbstractEpDialog
.className
– Where the code for the additional dialog is foundThis 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. Attributes are:
policyToApplyTo
– The class name of the policy to extendcontainerName
– The policy container nameclassName
– Where the code for the additional or extended State Policy Determiner is foundThis must refer to a class that implements
com.elasticpath.cmclient.policy.StateDeterminer
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:
<Messaging>
Name of the extended messaging class. Attributes are:
className
– where the code for the extended Messaging class can be foundThis 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 foundThis must refer to a class that implements
com.elasticpath.cmclient.core.helpers.extenders.PromotionWidgetCreator
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
ConditionRowCompositeCreatorFactory
Name of the factory class extension plugin used to create
ConditionRowComposites
. Attributes are:className
– where the code for the extendedConditionRowCompositeCreatorFactory
class is locatedThis 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
. Attributes are:className
– where the code for the extendedConditionModelAdapterFactory
class is locatedThis 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 Extending 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
To extend
BaseAmount
extend the following classes atextensons/core/
:ExtBaseAmountDTO
: Extends theBaseAmountDTO
ExtBaseAmountDTOCreator
: Overrides the default DTO (Data Transfer Object) creator to use theExtBaseAmountDTO
Ensure that the
plugin.xml
andMANIFEST.MF
files are updated as required. For more information see,MANIFEST.MF
andpom.xml
sections.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
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); } }
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>
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); } }
Update the
plugin.xml
file with the following for theBaseAmountDialog
class extension:<extension point="com.elasticpath.cmclient.pricelistmanager.Extender"> <Dialog dialogName="BaseAmountDialog" className="com.extensions.baseamount.impl.BaseAmountDialogExtension"/> </extension>
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 the extensions/
module.
MANIFEST.MF
As with all OSGi bundles, your plugin must have a MANIFEST.MF
file in the META-INF
directory with 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-17
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 must be listed in the extensions/cm/ext-cm-plugins
pom.xml
file as a <module>
:
<modules>
<module>your-extended-plugin</module>
...
</modules>
feature.xml
Reference the plugin in the extensions/cm/ext-cm-webapp/feature.xml
file as in the following example code:
<plugin id="your-extended-plugin" download-size="0" install-size="0" version="0.0.0" unpack="false"/>
config.ini
Add your new plugin to the extensions/cm/ext-cm-webapp/config.ini
file using the following syntax:
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.