Programming Standard

Guideline for writing secure, optimized and scalable extensions.

Table of contents

  1. Extension Types
    1. Trigger Extensions
    2. Utility Extensions
    3. Transaction Extensions
    4. Table Extensions
  2. Indentation and Formatting
  3. Naming
    1. Extensions
      1. Trigger Extensions
      2. Utility Extensions
      3. Transaction Extensions
      4. Table Extensions
      5. Methods
      6. Variables and Constants
  4. Extension Structure
    1. Utility Extensions
  5. Programming Practices
    1. Logging
      1. Log levels
    2. Database Access
    3. Loops
    4. Data Storage
      1. In Memory
      2. In Customer Extension Table
      3. In Dynamic Database
      4. In Text/XML/JSON File
    5. API Call
      1. ION API
      2. M3 API
    6. XML / JSON Parsing
    7. Date and Time
  6. Testing
    1. Local
    2. Live
  7. Version Controlling
    1. Framework
    2. Structure
    3. Hosting
  8. Documentation

Extension Types

Extension can be created in any of the four types:

Trigger Extensions

Trigger extensions are used to hook or inject our own code in a specific method in M3 Java through an extension point. These extensions extend the ExtendM3Trigger class.

Utility Extensions

Utility extensions are used to create an extension program with collection of methods that can be called in other extensions. These extensions extend the ExtendM3Utility class. utility, String method, Object... arguments)

Transaction Extensions

Transaction Extensions are used to create custom M3 API transactions. These extensions extend the ExtendM3Transaction class.

Table Extensions

Table Extensions are used to create dynamic table. In BE 15.x version, this is the equivalent of the MAK custom tables. It is possible to add columns, assign data types, unique keys, and indices.

Indentation and Formatting

Tab size: 2 spaces
Indent size: 2 spaces
Continuation indent: 4 spaces
Charset: utf-8

XtendM3 uses Groovy programming and ending code lines with semicolons are optional.



Extension names should be a valid Java class name. There is no restriction on extension names and will run with no error when compiled. However, when creating extensions, these naming conventions should be followed for readability and maintenance:


Program Type
IW Interactive
Fnc Fnc Batch
Batch Batch, Autostart Batch
MI MI Batch

Specification/Extension ID


  • Description should be in UpperCamelCase
  • Try to keep extension description names simple and descriptive
  • Avoid acronyms of abbreviations unless the word is a common jargon such as CO, DO, MO

Trigger Extensions

Format: <Module>_<Type>_<EXT ID>_<Description>

TypeProgramExtension name
Fnc BatchAPS450FncFIM_Fnc_1784_ValidateInvoice
MI BatchMMS100MISCE_MI_1784_ValidateDO

Utility Extensions

Format: <Description>Utils


Transaction Extensions

  • EXT9XXMI is reserved for standard extensions and should not be used
  • When extending standard API, use same number suffix as standard program
    OIS100MI - EXT100MI

  • If there are same number suffix for standard API that needs to have extensions, use increment in number suffix
    MMS100MI - EXT101MI

Table Extensions

Format: EXT<XXX>

  • When extending standard table or creating custom table, include the following standard fields
Column NameDescriptionData TypeLength
RGDTEntry dateDecimal8
LMDTChange dateString8
CHIDChanged byString10
RGTMEntry timeDecimal6
CHNOChange numberDecimal3
  • For standard table extension, use EXT

  • For custom table extension, use EXT same suffix as extension API Table - EXT001 API - EXT001MI


  • Method name should follow Java naming convention for methods
  • Names should be in lowerCamelCase, using no underscores and starting with a letter
  • Only alphanumeric characters should be used. Alphanumeric characters include the letters a-z, either upper case or lower case, and the numerals 0-9
  • Should be simple and descriptive: validateDate, validateType

Variables and Constants

  • Variables and constants should follow Java naming convention
  • Variables should be in lowerCamelCase and constants in CAPITAL_CONSTANTS

Extension Structure

  • Global variables and main method are declared at the beginning of the program as compared to M3 Java where these are declared at the end of the program <to add example>

Utility Extensions

  • Utility extensions cannot contain global variables
  • It is not possible to declare and create instance of API in utility extensions, instead API should be passed as parameters in utility methods <to add example>

Programming Practices


  • LoggerAPI is used for logging messages
  • It is encouraged to add logs in extensions to help in debugging and troubleshooting issues particularly on non-development environments (TRN, PRD) where there is restriction on modifying extensions
  • Use proper level of logging – If extension is to be deployed in PRD, it should be limited to DEBUG level. Using INFO/WARNING/ERROR/TRACE on production environment can cause huge log size and impact MT Cloud environment
  • Avoid logging values of all returned fields in a database query
  • Logs can be accessed through Administration tool - Business Engine Jobs <to add screen>

Log levels

  • warning
  • error
  • info
  • trace
  • debug

Database Access

  • It is recommended to use standard API if transactions are available instead of direct database access on WRITE/UPDATE/DELETE where the program uses multiple tables to update. This could cause corrupt data if any on the logic, validation, or database update was missed or incorrectly updated
  • Make sure when using readLock that it is released at the end of the extension to avoid blocking another program access
  • When reading table with partial keys, verify that this will not return too many records
  • When reading table, if possible, specify only the required column fields and avoid selectAllFields on querying tables particularly on tables which contains many fields


  • In M3 Java old programming, there are codes such as while(true) and performs multiple break inside the loop. When using while loop, avoid using condition=true and provide condition that will break the loop

Data Storage

In Memory

  • SessionAPI is used to store information in key-value mapping that can be accessed between multiple extensions in the same session
  • Make sure to use unique identifier as key names to avoid conflicts with other extensions when adding content to the cache
  • Reassess when there is too many information that needs to be stored in a session. It may be more practical to add the information using XtendM3 tables instead

In Customer Extension Table

  • Customer extension table refers to CUGEX1, CUGEX2 and CUGEX3 tables and can be accessed through standard API, CUSEXTMI
  • Customer extension table should not be used for high volume data and high number of reads, updates, and deletes instead replace with XtendM3 tables

In Dynamic Database

  • Dynamic Database or XtendM3 table is the equivalent of MAK custom table
  • Table name uses prefix EXT and can have specific columns and logical keys
    to add example

In Text/XML/JSON File

  • TextFilesAPI is the equivalent of MvxTextFile in M3 Java which can be used to read, write, or delete file
    to add example

API Call

  • M3 API can be run using IonAPI or MICallerAPI
  • It is preferred to use MICallerAPI which runs M3 API internally in the same layer as business engine instead of having another layer to execute M3 API


  • ION API provides secure access to M3 API and other registered application APIs through web services
  • When using IonAPI in extension, the response should be parsed XML/JSON Parsing
  • If standard M3 API is not available and an existing interactive program can be used to perform M3 update, ION API can be used to run IPS(Interactive Programming Services) which wraps the functionality of the program to perform M3 updates


  • MICallerAPI is the equivalent of utility program cMICaller in M3 Java

XML / JSON Parsing

Date and Time

  • Use classes LocalDate, LocalTime, LocalDateTime if required to retrieve current date or manipulate date or time
    int entryDate ="yyyyMMdd")).toInteger()
    int entryTime ="HHmmss")).toInteger()


Extension approval requires submission of approved Unit test and Functional test documents


  • Extensions can be locally tested using XtendM3 SDK which provides the interfaces for the internal APIs available to XtendM3 Extensions. This SDK can be used to build, test and debug Extensions locally without needing to have any M3 environment up and running
  • A sample repository ACME Corp. XtendM3 Extensions is provided to get you started on setting up project directories for the source codes, test scripts and XtendM3 SDK


  • If the program extension has been activated in the tenant, it automatically runs and the changes to the program are seen by the users. During unit testing, it is recommended that the extension should execute only for specific users until it is verified working to avoid interrupting other users when running the same program
  • Provided is an example of validating extension to run for specific user/s
    to add example

Version Controlling

More details are provided at Version Controlling page


Git version control system should be used


Refer to the example of an XtendM3 Extension Repository to version control extensions


Any git provider that the customer prefers GitHub, GitLab, Bitbucket and etc.


  • Extension JavaDoc on top of extension classes is required
  • Extension Methods JavaDoc on top of methods (except for main) is recommended