Appearance
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:
- the canonical model (
.cmnfiles) – what your system should do - the platform metamodel (
.profilfiles) – 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
- services
- resources and resource methods
- components
- applications
1.1 Data types
Data types represent the information in your domain. CMN supports:
- simple types – typed aliases or constrained primitives
(for exampleString, 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 primitive 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.
Later, platform-specific generators map services to concrete implementations (e.g. service interfaces, REST controllers, messaging handlers, …) depending on the platform configuration.
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 (for example
GET,POST), - references to resource method types that define behaviour such as status codes, request/response structure and error handling.
Resource method types are usually imported from a base model. For example, the create and read method types might be defined as:
text
methodtype create POST consumes='*' produces=Id success=201
methodtype read GET instance=true produces='*' success=200 errorResponse=ErrorResponseYour model simply uses create() / read() and inherits the detailed semantics from the base model.
1.4 Components
Components group resources and services into deployable building blocks.
A component typically:
- provides resources (and sometimes services),
- can depend on other components,
- is later mapped to a deployable artifact (for example a microservice, a library, or a bounded context) by platform-specific generators.
By modelling components explicitly, you can control how your system is split across modules, services or applications without hard-wiring framework choices into the model.
1.5 Applications
An application represents a runnable system composed of components.
An application:
- contains components,
- acts as an entry point for generation of platform-specific artifacts (for example an executable service, a web application, …),
- can be used to define deployment boundaries at the model level.
Applications sit at the top of the canonical model and are an important hook for platform profiles when deciding which generators to run for which parts of the model.
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:
- which generators are applied,
- where generated artifacts are written (for example via outlet overrides),
- how platforms treat different parts of the model (e.g.
commons,webapp).
Layer-specific behaviour is typically configured in platform profiles and joinedworkz.properties. The Modeling section on layers explains this in more detail.
2. Platform metamodel (.profil)
While the canonical model describes what the system should do, the platform metamodel describes how that model is realised for a specific platform.
Platform profiles are defined in .profil files and include the following concepts:
- stereotypes
- strategies
- outlets
- cartridges
- settings
- platforms
Together, these elements control how generators interpret the canonical model and where they write their outputs.
2.1 Stereotypes
Stereotypes are reusable annotations that can be attached to model elements to influence generation.
A stereotype definition includes:
- its name,
- the model element types it can be applied to (for example types, services, resources, methods, components),
- optional configuration parameters.
Examples of what stereotypes can express:
- whether a resource should be secured,
- whether an operation is idempotent,
- whether a type should be treated as a value object vs. an entity.
Platform profiles can also define conventions for assigning stereotypes, for example based on name patterns (see platform section below).
2.2 Strategies
Strategies calculate the values of derived or calculated properties.
A strategy typically:
- has a name (for example
TableNameStrategy), - takes model information as input,
- returns a derived value (for example a physical table name, an index name, a queue name, …).
Strategies are referenced from the platform profile and executed during generation to fill in computed details without polluting the canonical model with platform-specific naming rules.
2.3 Outlets
Outlets define where generated artifacts are written.
Examples of outlets:
generatedJavaSource– for generated Java code,openapi– for OpenAPI specifications,diagram– for diagram files or visualizations.
An outlet has at least:
- a name,
- a default directory (which can be overridden at project level),
- possibly a type (for example source vs. resource).
Cartridges write their outputs into one or more outlets.
2.4 Cartridges
A cartridge is a bundle of generators for a specific aspect of a platform. It is the link between the canonical model and the actual generated artifacts.
A cartridge definition typically includes:
- which outlets it uses,
- which generators it contains,
- configuration options that can be influenced by platform or properties.
Examples of cartridges:
- a Java cartridge that generates DTOs and mappers,
- an OpenAPI cartridge that generates OpenAPI documents from resources,
- a diagram cartridge that visualises components and their relations.
Cartridges are activated through platforms; they are not invoked directly from the canonical model.
2.5 Settings
A setting is a technical element used to reference Java classes that are needed to instantiate cartridges and generators, for example via a dependency injection module.
Settings are mostly relevant when implementing a platform and are rarely touched by normal model authors. Conceptually they provide the glue between the platform profile and the implementation code of cartridges and generators.
2.6 Platforms
A platform ties everything together. It describes how the canonical model should be treated to produce artifacts for a particular technology stack.
A platform definition typically covers:
Which cartridges to apply
The platform lists the cartridges that belong to it. For example aBaseplatform might include an OpenAPI cartridge, a diagram cartridge and a debug cartridge.Platform-specific properties and overrides
The platform can add properties to model elements or override existing properties. This allows a platform to adjust behaviour without changing the canonical model.Stereotype assignment by convention
A platform can define rules that automatically assign stereotypes based on naming conventions. For example:- add a
findBystereotype to all methods whose name starts withfindBy*, - assign a specific stereotype to all components whose name matches a pattern.
- add a
Your .cmn models reference a platform by name, for example:
text
platform BaseDuring generation the referenced platform controls which cartridges are executed and how they interpret the model.
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:
- On save – saving a model file can automatically trigger generation for the affected parts of the model.
- 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:
- Entities & DTOs – details on defining simple, enum and complex types.
- APIs and resources – how to model services, resources and methods.
- Components and applications – structuring your system into deployable pieces.
- Platform profiles – syntax and semantics of
.profilfiles, including stereotypes, strategies, outlets and cartridges. - Layers and outlet routing – how to use layers and
joinedworkz.propertiesto control where generated artifacts go.
