Appearance
Profiles & platforms (.profil)
This page explains how platform profiles are modeled in .profil files and how they interact with the canonical model (.cmn).
A platform profile typically defines:
- stereotypes – reusable annotations for model elements
- strategies – logic to compute derived property values
- outlets – where generated artifacts are written
- cartridges – groups of generators for a specific concern
- settings – wiring for dependency injection / implementation classes
- platforms – how cartridges, properties and conventions are combined
Platforms are packaged as normal Maven artifacts that also contain the Java/Xtend implementations of cartridges, strategies and settings, and often additional CMN base models (for example base types and resource method types).
1. Profile file structure
A .profil file is organised similarly to a CMN file:
- a package declaration at the top
- then groups of definitions: stereotypes, strategies, outlets, cartridges, settings and platforms
Example (simplified):
text
package org.joinedworkz.facilities.common.profiles.base
/* stereotypes */
stereotype entity applicable for complextype not propagated by specialization
/* outlets */
abstract outlet StandardOutput { ... }
outlet generatedOpenApi specialization of StandardOutput { ... }
/* cartridges */
cartridge OpenApiCartridge implementation="org.joinedworkz.common.OpenApiCartridge"
outlets=generatedOpenApi
/* settings */
setting CommonSetting implementation="org.joinedworkz.common.CommonSetting"
/* platforms */
platform Base setting=CommonSetting {
apply cartridge OpenApiCartridge
// property contributions ...
}Concrete CMN models select a platform via the platform header, for example platform Base (see Model file structure).
2. Stereotypes
Stereotypes are reusable annotations you can attach to model elements in .cmn files. They:
- have a name
- declare for which model element types they are applicable
- can have specialisation relationships
- can define how they are propagated
2.1 Declaring stereotypes
In a profile, stereotypes are declared like this (Base platform examples):
text
stereotype entity applicable for complextype not propagated by specialization
stereotype aggregate applicable for complextype not propagated by specialization
stereotype key applicable for field propagated by specialization, including
stereotype controller applicable for serviceKey aspects:
applicable forrestricts where the stereotype can be used (e.g.simpletype,complextype,field,service,operation,component, …).specialization ofexpresses inheritance between stereotypes, for exampleintegerandlongspecialisingnumber.propagated by ...controls how stereotypes propagate:specialization– along type inheritancereferencing– when something references another elementincluding– when elements are included/embedded
not propagated by ...can be used to explicitly stop propagation, e.g. forentityso that subtypes are not automatically entities.
2.2 Using stereotypes in CMN
In CMN models, stereotypes are applied by putting their names in angle brackets in front of an element. For example (simplified):
text
stereotype entity applicable for complextype
type<entity> Customer {
id: Id
name: String
}Here:
Customeris a complex type with theentitystereotype.idis a field with thekeystereotype.- Platforms can use this information to decide how to treat the type (e.g. as a persisted entity, as a logical entity, etc.).
3. Outlets
Outlets define where generated files are written and how generation treats those directories.
The Base profile defines an abstract outlet and several concrete ones, for example:
text
abstract outlet StandardOutput
createNotExistingDirectory = true
overwriteExistingFiles = true
markAsDerived = true
deleteFilesOnCleanBuild = true
cleanWholdDirectoryOnCleanBuild = false
keepLocalHistory = true
outlet generatedDiagram specialization of StandardOutput
directory = "./diagram"
outlet generatedSchema specialization of StandardOutput
directory = "./target/joinedworkz/schema"
outlet generatedOpenApi specialization of StandardOutput
directory = "./src/generated/resources/openapi"
outlet generatedOpenApiHtml specialization of StandardOutput
directory = "./diagram/api"Cartridges refer to outlets to decide where to write their outputs. The directories can later be overridden at project level via joinedworkz.properties (see Create a project with Maven).
4. Cartridges
A cartridge is a bundle of generators for a specific aspect of a platform. It declares:
- a name
- an implementation class
- the outlets it writes to
Examples from the Base profile:
text
cartridge DiagramCartridge implementation="org.joinedworkz.common.DiagramCartridge"
outlets=generatedDiagram
cartridge SchemaCartridge implementation="org.joinedworkz.common.SchemaCartridge"
outlets=generatedSchema
cartridge OpenApiCartridge implementation="org.joinedworkz.common.OpenApiCartridge"
outlets=generatedOpenApi, generatedOpenApiHtmlCartridges are not invoked directly from the CMN model. Instead, they are applied by platforms (see next section). A platform can also support disabling a cartridge at model level via the exclude clause in the CMN platform header, e.g.:
text
platform SpringBoot exclude DtoCartridgeThis keeps the platform profile generic while allowing per-model control.
5. Settings
A setting connects a platform to its implementation classes, typically via dependency injection.
Example:
text
setting CommonSetting implementation="org.joinedworkz.common.CommonSetting"The implementation class usually registers cartridges, generators, strategies and other services with a DI container. Derived platforms can override settings or replace specific strategies or generators by wiring different implementations.
Settings are mostly relevant when implementing platforms, not when consuming them in CMN models.
6. Platforms
A platform combines cartridges, property contributions and conventions to define how a canonical model is interpreted for a specific technology stack.
6.1 Base platform example
The Base platform (simplified) looks like this:
text
platform Base setting=CommonSetting {
/* apply cartridges */
apply cartridge DiagramCartridge
apply cartridge SchemaCartridge
apply cartridge OpenApiCartridge
contribute to simpletype<string> {
property minLength: INTEGER
property maxLength: INTEGER
property pattern: STRING
property javaType: STRING
property format: STRING
}
contribute to complextype<entity> {
property tableName: STRING not propagated by specialization
}
contribute to complextype<entity>.field {
property columnName: STRING
}
}Key ideas:
setting=CommonSettinglinks the platform to the DI configuration.apply cartridge ...lists the cartridges that belong to this platform.contribute to ...adds or overrides properties on model elements that have certain stereotypes (e.g.simpletype<string>,complextype<entity>).- Properties can also define propagation rules (
not propagated by specialization) and, in derived platforms, default values or overrides.
6.2 Platform inheritance
Platforms can inherit from other platforms:
text
platform Java specialization of Base {
// additional cartridges and contributions
contribute to simpletype<decimal> {
override javaType value="java.math.BigDecimal"
}
}Inheritance allows you to:
- reuse common behaviour (e.g. diagram and OpenAPI cartridges from Base),
- add platform-specific cartridges (e.g. Java or Spring Boot generators),
- refine property contributions (override or extend properties).
6.3 Binding CMN models to platforms
In CMN files, the header selects the platform, for example:
text
platform Baseor, with cartridge exclusions:
text
platform SpringBoot exclude DtoCartridgeThe generator then:
- loads the selected platform from the available profile modules,
- applies its cartridges to the model,
- uses property contributions, stereotypes and strategies defined by the platform to drive generation.
7. Strategies
Strategies are used to compute values for derived or calculated properties during generation.
They are declared in the profile, for example (Java platform):
text
strategy JavaNamingStrategy implementation="org.joinedworkz.common.java.Strategy"
strategy JavaTypeStrategy implementation="org.joinedworkz.common.java.JavaTypeStrategy"Strategies are then referenced in property contributions:
text
contribute to field {
property javaName: STRING strategy=JavaNamingStrategy
}
contribute to type {
property javaType: STRING strategy=JavaTypeStrategy
}At generation time, the strategy implementations:
- receive the relevant model element (field, type, …),
- compute the property value (e.g. a Java-friendly name or type),
- write it into the model’s derived properties for further use by generators.
Because strategies are wired via DI, derived platforms can easily swap in alternative implementations if needed.
8. Packaging and reuse
Each platform is typically delivered as a Maven module that contains:
- one or more
.profilfiles (platform profiles), - Java/Xtend implementations of cartridges, generators, strategies, settings and other helpers,
- optional CMN base models, such as:
- base type definitions (e.g.
String, numeric types), - resource method types (
create,read, etc.).
- base type definitions (e.g.
You make a platform available to your model module by adding it as a normal Maven dependency. The JoinedWorkz Maven plugin then:
- loads the platform profiles and implementations from the classpath,
- uses them when executing the generator for your models.
Platforms provided by JoinedSystems (such as the Base platform) are published to Maven Central and can be used freely. You can also define your own custom platforms and publish them within your organisation.
9. Next steps
From here you can:
- revisit the Modeling overview with a clearer understanding of how platforms influence generation;
- read Create a project with Maven to see how platforms are brought into a build via Maven dependencies;
- explore Modeling with JoinedWorkz Studio to see how platforms, stereotypes and validations are surfaced in the editor;
- consult the CMN reference for the exact syntax of
.profilconstructs: stereotypes, strategies, outlets, cartridges, settings and platforms.
