Skip to content
CONTEXT MAPPER
  • Docs
  • Language Reference
  • Generators
  • News
  • Background
  • Get Involved
    Introduction
    • Welcome
    • Getting started
    • Create CML Project
    • Examples
    • Usage as Library
    • Frequently Asked Questions
    Language Reference (Core)
    • CML Reference - Introduction
    • Language Semantics
    • Context Map
    • Bounded Context
    • Domain and Subdomain
    • Domain Vision Statement
    • Partnership
    • Shared Kernel
    • Customer/Supplier
    • Conformist
    • Open Host Service
    • Anticorruption Layer
    • Published Language
    • Responsibility Layers
    • Knowledge Level
    • Aggregate
    • Tactic DDD Syntax
    • Application and Process Layer
    • User Requirements
    • Stakeholders
    • Value Registers
    • Imports
    Analysis and Design Transformations
    • Rapid Object-oriented Analysis and Design
    • Story Splitting (PoC)
    • Stakeholder and Value Modelling Transformations
    Architectural Refactorings (ARs)
    • Architectural Refactorings
    • AR-1: Split Aggregate by Entities
    • AR-2: Split Bounded Context by Features
    • AR-3: Split Bounded Context by Owner
    • AR-4: Extract Aggregates by Volatility
    • AR-5: Extract Aggregates by Cohesion
    • AR-6: Merge Aggregates
    • AR-7: Merge Bounded Contexts
    • AR-8: Extract Shared Kernel
    • AR-9: Suspend Partnership
    • AR-10: Change Shared Kernel to Partnership
    • AR-11: Change Partnership to Shared Kernel
    Value-Driven Analysis and Design
    • Value-Driven Analysis and Design (VDAD) Support
    Service Cutter
    • Context Map Suggestions with Service Cutter
    • Service Cutter Configuration File (.servicecutter.yml)
    Reverse Engineering
    • Context Map Discovery
    Generators
    • Generators Overview
    • Context Map Generator
    • PlantUML Generator
    • BPMN Sketch Miner Generator
    • MDSL (Micro-)Service Contracts Generator
    • Service Cutter Generators
    • Generic Generator (Templating)
    Tutorials
    • Model Event Storming Results in Context Mapper
    • Event Sourcing and CQRS Modeling in Context Mapper
    • Generate Microservices From Context Map Using JHipster
    • Systematic Service Decomposition with Context Mapper and Service Cutter
    • Validating the Implementation against the Model (with ArchUnit)
    IDE Plugins and Extensions
    • Visual Studio Code Extension
    • Online IDE (no longer supported)
    • Eclipse Plugin
    • Feature Support

    Generic Generator (Templating)

    • Introduction
    • Data Model
    • Helper Functions
    • User Guide
    • Example Templates

    Introduction

    The generic generator is based on Freemarker templates. It allows Context Mapper users to generate arbitrary text files from CML Context Maps. One can generate for example Markdown, JSON, XML, or any other textual output formats by providing a corresponding Freemarker template (*.ftl file).

    Simple Example

    This simple example illustrates how the generator works. The following Freemarker template outputs the names of all Bounded Contexts on the Context Map:

    The Context Map '${contextMap.name}' contains the following Bounded Contexts:
    
    <#list contextMap.boundedContexts as bc>
    ${bc.name}
    </#list> 
    

    Applied to our insurance example the generator produces the following output:

    The Context Map 'InsuranceContextMap' contains the following Bounded Contexts:
    
    CustomerManagementContext
    CustomerSelfServiceContext
    PrintingContext
    PolicyManagementContext
    RiskManagementContext
    DebtCollection
    

    Data Model

    In order to write your own Freemarker templates, you have to know the data model exposed by Context Mapper. In the following we provide an overview over this CML model.

    Note: We do not document the tactic DDD parts within Bounded Contexts in all details. In case your template needs information on that level please use our JavaDoc documentation to obtain the necessary information about the data model.
    Note: The variable names of the model documented below must be used case-sensitively in Freemarker templates.

    Root Level

    The root level of the model contains the following elements:

    (root)
      |
      +- contextMap                    Context Map object
      |
      +- boundedContexts               Bounded Context list
      |
      +- domains                       Domains list
      |
      +- imports                       Imports list
      |
      +- useCases                      Use cases list
      |
      +- timeStamp                     Time stamp with current/generation time
      |
      +- fileName                      name of CML file
      |
      +- projectName                   name of Eclipse project
      |
      +- contextMapperVersion          version of the Context Mapper plugin and the CML language
      |
      +- userName                      name of the current system user
    

    The corresponding CML objects and their syntax can be found in our language reference: Context Map, Bounded Context, Domains and Subdomains, imports, use cases.

    Context Map

    The contextMap root element of the model contains the following data (the values in double quotes "..."are just examples):

    contextMap
      |
      +- name = "ExampleContextMap"
      |
      +- type = "SYSTEM_LANDSCAPE"
      |
      +- state = "TO_BE"
      |
      +- boundedContexts               List of Bounded Contexts that are added to the Context Map
      |
      +- relationships                 List of Context Map relationships
    

    Relationships

    If you use relationships, you must respect the different types as illustrated in our language meta model. The following types of relationships exist:

    • SymmetricRelationship
      • Partnership
      • SharedKernel
    • UpstreamDownstreamRelationship
      • CustomerSupplierRelationship

    Depending on the relationship type (symmetric or upstream-downstream), the objects have a different structure.

    The structure of a SymmetricRelationship is as follows:

    relationship
      |
      +- name = "ExampleRelationship"  Optional relationship name (nullable)
      |
      +- implementationTechnology = "Java Library"
      |
      +- participant1                  Bounded Context object (first relationship participant)
      |
      +- participant2                  Bounded Context object (second relationship participant)
    

    The structure of an UpstreamDownstreamRelationship on the other hand is as follows:

    relationship
      |
      +- name = "ExampleRelationship"  Optional relationship name (nullable)
      |
      +- implementationTechnology = "RESTful HTTP"
      |
      +- upstream                      Bounded Context object (upstream context)
      |
      +- downstream                    Bounded Context object (downstream context)
      |
      +- upstreamRoles                 List of upstream roles (OHS, PL)
      |   |
      |   +- (1st)
      |   |   |
      |   |   +- name = "OHS"
      |   |
      |   +- (2nd)
      |       |
      |       +- name = "PL"
      |
      +- downstreamRoles               List of downstream roles (ACL, CF)
      |   |
      |   +- (1st, 2nd)
      |       |
      |       +- name = "ACL"          Semantics only allows one role here (ACL or CF)
      |
      +- upstreamExposedAggregates     List of Aggregate objects
      |
      +- downstreamGovernanceRights
          |
          +- name = "INFLUENCER"
    

    Relationship Type Checking

    To respect the different structures when processing the relationship list, we provide a method that allows you to check the type of the relationship:

    <#if instanceOf(relationship, SymmetricRelationship)>
    ...
    </#if>
    
    <#if instanceOf(relationship, UpstreamDownstreamRelationship)>
    ...
    </#if>
    

    You can also check the type of concrete relationship:

    <#if instanceOf(relationship, Partnership)>
    ...
    </#if>
    
    <#if instanceOf(relationship, CustomerSupplierRelationship)>
    ...
    </#if>
    

    Bounded Context

    The boundedContexts root element of the model contains a list of BoundedContext objects. The BoundedContext object has the following structure:

    boundedContext
      |
      +- name = "CustomerManagement"
      |
      +- implementedDomainParts        List of implemented domain parts
      |   |
      |   +- (1st)                     (example: first element is a _Domain_)
      |   |   |
      |   |   +- name = "Insurance"
      |   |   |
      |   |   +- domainVisionStatement = "Insurance application vision statement ..."
      |   |   |
      |   |   +- subdomains            List of subdomains
      |   |
      |   +- (2nd)                     (example: second element is a _Subdomain_)
      |       |
      |       +- name = "CustomerManagement"
      |       |
      |       +- domainVisionStatement = "Customer management vision statement ..."
      |       |
      |       +- type
      |       |   |
      |       |   +- name = "CORE_DOMAIN"
      |       |
      |       +- entities              List of Entity objects
      |
      +- realizedBoundedContexts       List of Bounded Context objects
      |
      +- refinedBoundedContext         Bounded Context object
      |
      +- domainVisionStatement = "This Bounded Contexts goal is ..."
      |
      +- type
      |   |
      |   +- name = "FEATURE"
      |
      +- responsibilities              List of responsibilities (strings)
      |   |
      |   +- (1st)
      |   |   |
      |   |   +- "Managing customers"
      |   |
      |   +- (2nd)
      |       |
      |       +- "Managing addresses"
      |
      +- implementationTechnology = "Spring Boot"
      |
      +- knowledgeLevel
      |   |
      |   +- name = "META"
      |
      +- modules                       List of module objects (Sculptor)
      |   |
      |   +- (1st)
      |       |
      |       +- name = "ExampleModule"
      |       |
      |       +- aggregates            List of Aggregate objects
      |
      +- aggregates                    List of Aggregate objects
    

    Note: The attribute implementedDomainParts of the BoundedContext returns a list of DomainParts. A DomainPart can either be a Domain or a Subdomain. Both have a name and a domainVisionStatement. As long as you only use these two attributes you don’t have to check for the type. However, if you want to access the type attribute of a Subdomain you have to check if the DomainPart is a Subdomain first:

    <#if instanceOf(domainPart, Subdomain)>
    ...
    </#if>
    

    Aggregate

    Bounded Contexts contain a set of Aggregates that have the following structure (rough sketch, the JavaDoc has the details):

    aggregate
      |
      +- name = "Customers"
      |
      +- responsibilities              List of responsibilities (strings)
      |   |
      |   +- (1st)
      |       |
      |       +- "Managing customers"
      |
      +- useCases                      List of use case objects
      |
      +- owner                         Bounded Context object
      |
      +- knowledgeLevel
      |   |
      |   +- name = "META"
      |
      +- likelihoodForChange
      |   |
      |   +- name = "NORMAL"
      |
      +- services                      List of Service objects (Sculptor)
      |
      +- resources                     List of Resource objects (Sculptor)
      |
      +- consumers                     List of Consumer objects (Sculptor)
      |
      +- domainObjects                 List of SimpleDomainObject objects (Sculptor)
    

    We do not document the structures below Aggregates (Sculptor) here. Please consult the JavaDoc documentation of the Aggregate.

    Note: The domainObjects list contains all domain objects such as Entities, Value Objects, etc. Sculptor defines the following overall type hierarchy:

    • SimpleDomainObject
      • BasicType
      • DataTransferObject
      • DomainObject
        • Entity
        • Event
          • CommandEvent
          • DomainEvent
        • ValueObject
      • Enum
      • Trait

    To respect the different structures of these types, you again can use our instanceOf method:

    <#if instanceOf(domainObject, Entity)>
    ...
    </#if>
    

    As already mentioned, you find the structure of all these domain objects in our JavaDoc documentation.

    Domains

    The domains root element of the model contains a list of DomainPart objects which can either be Domains or Subdomains. Use our instanceOf method to check of which type a DomainPart is:

    <#if instanceOf(domainPart, Subdomain)>
    ...
    </#if>
    

    The structure of a Domain object is the following:

    domain
      |
      +- name = "Insurance"
      |
      +- domainVisionStatement = "Insurance domain vision statement ..."
      |
      +- subdomains                    List of Subdomain objects
    

    The structure of a Subdomain object is as follows:

    subdomain
      |
      +- name = "Insurance"
      |
      +- domainVisionStatement = "Insurance domain vision statement ..."
      |
      +- type
      |   |
      |   +- name = "CORE_DOMAIN"
      |
      +- entities                      List of Entity objects
    

    Imports

    CML models can import other files via imports. The mechanism is explained here. Imports can be accessed on the root level of the model (imports) and have the following structure:

    import
      |
      +- importURI = "./other-file.cml"
    

    Use Cases

    The useCases root element of the model contains a list of UseCase objects which have the following structure:

    usecase
      |
      +- name = "UpdateCustomer"
      |
      +- isLatencyCritical = false
      |
      +- nanoentitiesRead              List of nanoentities that are read by this use case (strings)
      |   |
      |   +- (1st)
      |   |   |
      |   |   +- "Customer.firstName"
      |   |
      |   +- (2nd)
      |       |
      |       +- "Customer.lastName"
      |
      +- nanoentitiesWritten           List of nanoentities that are written by this use case (strings)
          |
          +- (1st)
          |   |
          |   +- "Customer.firstName"
          |
          +- (2nd)
              |
              +- "Customer.lastName"
    

    Additional Root Attributes

    The following additional attributes are currently available on the root level of the model:

    • timestamp: generation time stamp (for example 26.02.2020 17:20:40 CET)
    • filename: name of the CML file (for example ExampleModel.cml)
    • projectName: name of the Eclipse project that contains the CML file
    • contextMapperVersion: the current version of Context Mapper that was used to generate the output (for example v5.9.4)
    • userName: the name of the user that generated the output (OS username)

    Helper Functions

    The following functions can be used in the Freemarker templates to help processing the model described above:

    Bounded Context Filtering

    The functions filterStructuralBoundedContexts and filterTeams can be used to filter teams and Bounded Contexts which are not teams respectively. The following example lists all Bounded Contexts that are not teams:

    <#list filterStructuralBoundedContexts(boundedContexts) as bc>
      Bounded Context: ${bc.name}
    </#list>
    

    This example on the other hand lists all teams:

    <#list filterTeams(boundedContexts) as bc>
      Bounded Context: ${bc.name}
    </#list>
    

    Type Checking

    The meta-model behind CML contains a few inheritance hierarchies which make it unavoidable that you sometimes have to check of which type an object is. Examples with relationships and domains vs. subdomains have already been shown above. The function instanceOf allows to check which type of relationship or subdomain an object has:

    <#if instanceOf(relationship, UpstreamDownstreamRelationship)>
    ...
    </#if>
    
    <#if instanceOf(domainPart, Subdomain)>
    ...
    </#if>
    

    Get Type String of ComplexType

    If you work on the tactic DDD level with attributes and methods (parameters and return types) you may want to render the type of an attribute, parameter, or return type. This part of the DSL is based on Sculptor, and the types are typically instances of the ComplexType object. Depending on if it is primitive type or a reference to another type, rendering the type as a string is quite cumbersome. The function getType which takes a ComplexType as a parameter returns a simple string representing the type:

    <#list simpleDomainObject.operations as operation>
      operation ${operation.name} returns type ${getType(operation.returnType)}
    </#list> 
    

    User Guide

    To use our generic, Freemarker template-based generator, you need two files within your workspace:

    • The input CML model (*.cml)
    • The Freemarker template (*.ftl)

    The generator can be called from the context menus of the CML editors in VS Code or Eclipse. A documentation how to call the generators can also be found here.

    Note: All generator outputs will be generated into the src-gen folder.

    Eclipse as well as VS Code will ask you to choose a *.ftl file from your filesystem and to define the output file name (which will then be generated into src-gen).

    Freemarker Version

    Context Mapper uses Freemarker, currently Version 2.3.30.

    Example Templates

    Eclipse

    The Context Mapper Eclipse plugin comes with sample Freemarker templates. Use the Freemarker Generator Template Examples wizard via File -> New -> Example… to create the sample project containing the Freemarker templates:

    Create Sample Project with Freemarker Templates (1)

    Create Sample Project with Freemarker Templates (2)

    Visual Studio Code

    In VS Code we do not deliver the example templates with the extension itself. However, you can just download the *.ftl files from here and use it with our generator in VS Code.

    Provided Examples

    The project currently contains the following example templates:

    • Ubiquitous language glossary written in Markdown (currently a full report)
      • Currently a full report of the model. A future version of the template will generate a glossary only.
    • JHipster Domain Language (JDL) template to generate Microservices from CML models
    • CSV files to export stakeholder and value register data (as part of the VDAD support)
    Improve this page on GitHub
    ← PreviousService Cutter Generators Next →Model Event Storming Results in Context Mapper
    © 2026 Context Mapper contributors
    • GitHub
    • Get Involved
    • Background & Publications
    • RSS