Skip to content

Modeling overview

JoinedWorkz uses model-driven development based on a canonical model and platform-specific metamodels. Understanding how these pieces fit together helps you design models that can be reused across different technology stacks.

At a high level there are two modeling levels:

  1. the canonical model (.cmn files) – what your system should do
  2. the platform metamodel (.profile files) – how this model is realised on a given platform

This page gives you a conceptual overview. Later pages go into syntax details for each topic (data types, services, resources, components, platforms, …).


1. Canonical model (.cmn)

The canonical model describes the functional structure of your system using Canonical Model Notation (CMN). It is intentionally technology-neutral and focuses on what the system does, not on framework or implementation details.

A .cmn model can define the following core elements:

  • data types
  • reusable fields, relations, constants and constraints
  • services
  • resources and resource methods
  • components
  • applications

1.1 Data types

Data types represent the information in your domain. CMN supports:

  • simple types – scalar, facility-defined or specialised types (for example String, numeric types, or custom simple types with limits)
  • enums – a fixed set of named values
  • complex types – structures with named properties and types

Complex types are typically used for:

  • API payloads (requests/responses),
  • domain entities,
  • configuration and other structured data.

The base models (for example common-base) provide reusable simple types such as String and shared utility types. Your own models build on top of these.

1.2 Services

Services group operations that represent business capabilities. A service typically:

  • defines a set of methods,
  • uses data types from the same package or imported packages,
  • is independent of transport or protocol details.

A facility can map services to concrete artifacts such as service interfaces. The CMN declaration itself does not prescribe an implementation technology or promise a particular generated artifact.

1.3 Resources and endpoints

Resources describe externally visible APIs in a more transport-oriented form. They are often used for REST-style APIs.

A resource contains:

  • a resource path (for example /hello),
  • resource methods / endpoints,
  • references to resource method types that declare an HTTP verb and can provide defaults such as status codes or request/response properties.

Resource method types are usually imported from a base model. For example, the create and read method types might be defined as:

cmn
methodtype create POST consumes='*' produces=Id success=201
methodtype read   GET instance=true produces='*' success=200 errorResponse=ErrorResponse

Your model uses create() / read() and inherits the properties of those imported method types. The names and properties in this example are supplied by the Base facility; they are not built-in CMN keywords. A concrete resource method may additionally have a local name, for example read readGreeting(). Here read remains the method-type reference and readGreeting names that one operation.

1.4 Components

Components group resources and services into logical provided boundaries.

A component typically:

  • declares that it provides resources (and sometimes services),
  • can depend on other components,
  • can be interpreted by facility-specific cartridges to produce diagrams, OpenAPI documents, or implementation artifacts.

provide /customers assigns the referenced resource to the component's provided API boundary. It does not by itself state that the component implements the resource or that executable code has been generated.

1.5 Applications

An application represents a logical system boundary and composition of components.

An application:

  • lists owned components in consists of { ... },
  • can express dependencies on other components,
  • can be used as the scope of application and component diagrams.

Whether this composition becomes an executable application depends on the selected facility and a project-specific application shell. Base uses applications for diagrams; it does not make the CMN declaration itself runnable.

1.6 Packages and layers

Canonical models are organised into packages. A package defines a namespace for types, services, resources and components.

In addition to the package name, a package can belong to a layer. Layers are used to control aspects such as:

  • how platforms treat different parts of the model (e.g. core, api),
  • which layer-specific directory JoinedWorkz selects within an outlet.

The declared CMN layer normally becomes the effective layer for generated output. A generator can assign a different effective layer to a particular file. An exact layer-specific outlet mapping wins; otherwise the global outlet directory applies.

The layer is a free identifier written before package, for example api package com.example.customer. There is no layer keyword. Selected facilities may attach additional meaning to particular layer names.


2. Platform metamodel (.profile)

While the canonical model describes what the system should do, the platform metamodel describes how that model is realised. Facilities package this metamodel in .profile resources together with the corresponding generator implementations.

A Profile can provide:

  • named Platforms such as Base, Java or SpringBoot;
  • Cartridges that group generation behavior;
  • Outlets through which Cartridges write files;
  • stereotypes and properties consumed by the Platform; and
  • additional advanced implementation elements used by built-in Facilities.

Application developers normally do not edit these Profiles. They add the Facility to the model module's Maven dependencies, import its namespaces and select a Platform:

cmn
platform Base

The selected Platform determines which Cartridges interpret that model and which Outlets are available to them. A specialized Platform can inherit active behavior from its base, so SpringBoot, for example, also includes Java and Base generation behavior.

Continue with:


3. Validation and generation workflow

Modeling is closely tied to validation and generation. JoinedWorkz provides validation both in the Studio editor and in cartridges, and generation is optimised for fast feedback.

3.1 Validation in JoinedWorkz Studio

In JoinedWorkz Studio, CMN models are validated at different times and intensities:

  • lightweight checks while typing – quick feedback on basic syntax and simple consistency rules,
  • normal checks on save – more complete validation of the edited file,
  • full checks before generation – thorough validation across model files before generators run.

Validation can also be platform-specific:

  • base validation is done on the canonical model,
  • cartridges can perform additional checks for a given platform and report errors back into the editor.

All validation messages are shown as close as possible to the affected model element in the editor (for example as markers on the relevant line).

3.2 Generation triggers

In Studio, generation can be triggered in two ways:

  1. On save – saving a model file can automatically trigger generation for the affected parts of the model.
  2. Explicit generate command – via the main menu or context menus in the file/package explorer.

Generation progress, logging output and any errors are shown in a dedicated console view. Even for larger models, generation is typically fast (on the order of a few hundred milliseconds up to about one second, with longer times only in exceptional cases).

3.3 Generation via Maven

Outside of Studio, generation is usually performed via the Maven plugin:

  • the plugin runs in the chosen build phase (for example generate-sources),
  • it loads and validates the models,
  • applies the selected platform and cartridges,
  • writes the generated artifacts into the configured outlets.

This makes it easy to integrate JoinedWorkz into CI/CD pipelines and build servers without requiring Studio.


4. Where to go next

The following pages go into more detail about individual parts of the modeling stack: