Skip to content

joinedworkz.properties reference

joinedworkz.properties configures a JoinedWorkz model project without putting project-specific paths or generator choices into a reusable profile. It is optional.

Upgrade from 1.3.80

The diagnostics, strict path validation and first-class facility-property registry described here were not available as one consistent contract in release 1.3.80.

For a step-by-step configuration migration, see Upgrade from 1.3.80 to 1.3.81.

The keys below are the generic runtime patterns and the properties provided by the public JoinedWorkz facilities documented on this site. This is not a closed, product-wide registry. Other facilities can define additional joinedworkz.properties keys and outlets. The documentation of such a facility must define their types, defaults, audience, lifecycle, precedence and effect.

1. File location and loading

JoinedWorkz reads exactly one file for a model project:

EnvironmentLocation
Maven<Maven module base directory>/joinedworkz.properties
JoinedWorkz Studiojoinedworkz.properties in the Eclipse project root

In a multi-module project, the file normally belongs to the model module that runs the JoinedWorkz generator. A path such as model/joinedworkz.properties therefore means the root of a Maven module named model; it does not mean the CMN source directory inside another module.

JoinedWorkz does not overlay this file with:

  • a parent-directory properties file;
  • Maven project properties;
  • JVM system properties;
  • environment variables;
  • a second classpath resource.

A missing file and an empty file have the same effect: JoinedWorkz uses the declared defaults.

1.1 Java properties format

Maven and Studio both load the file with Java Properties.load(InputStream). Consequently:

  • keys are case-sensitive;
  • =, : or unescaped whitespace can separate a key and value;
  • leading whitespace and comments beginning with # or ! follow Java properties rules;
  • backslash escapes and \uXXXX Unicode escapes are interpreted;
  • the input-stream format uses ISO-8859-1; represent characters outside that character set with \uXXXX escapes.

Maven loads one cached snapshot for a generator build. Studio checks whether the file was created, removed or changed and refreshes the cached properties, output configuration and project runtime for the next generation invocation.

2. How keys become known and used

There are two sources of configuration knowledge:

  1. Runtime patterns are implemented by the generic generator, for example outlet routing and cartridge enablement.
  2. Facility properties are declared by profiles and referenced by a platform, setting, cartridge or cartridge application.

Profile declarations are the source of truth for facility-specific key metadata. JoinedWorkz collects declarations from the platforms that are actually generated. A key can therefore be:

  • known and used – an active platform or cartridge consumes it;
  • known but unused – an encountered platform declares it, but its specific consumer is inactive, for example because its cartridge is disabled or excluded;
  • unknown – no generated platform or generic runtime pattern declares it.

A facility that is merely present on the classpath does not make all its properties known. JoinedWorkz discovers declarations on demand while generating models with the corresponding platforms.

An active cartridge contributes its properties. A cartridge disabled through configuration remains known, but its own facility properties are unused. A cartridge excluded in CMN does not become used merely because a property mentions it.

2.1 Pattern keys and non-empty placeholders

A profile can declare a first-class configuration key as a pattern containing one or more named placeholders, for example override-package.<originalPackagePrefix>. Each placeholder represents one or more characters in the concrete property key; it must never be empty.

This rule applies independently to every placeholder in a profile-declared pattern. A key that otherwise has the pattern's literal structure but leaves a placeholder empty is invalid rather than unknown. For example, override-package. cannot match override-package.<originalPackagePrefix> and stops generation with JW_CONFIG_INVALID_KEY. Add the missing suffix or remove the property.

Generic runtime patterns are separate from profile-declared first-class properties and retain the matching contract documented for that particular pattern.

3. Audience and lifecycle

This reference uses two independent classifications:

  • Audience
    • PUBLIC: normal project configuration with a compatibility contract.
    • ADVANCED: supported only for deliberate, informed use; it can expose generator structure or incomplete feature combinations.
  • Lifecycle
    • STABLE: changes follow compatibility and deprecation rules.
    • EXPERIMENTAL: behavior can change without the stable compatibility guarantee.
    • DEPRECATED: retained for migration, but scheduled for removal.

Properties classified as internal are intentionally absent from this public reference. The existence of a key in source code or a published artifact does not make it public API.

3.1 Key index

These deliberately narrow tables index the properties described below. They are not a complete JoinedWorkz registry: additional facilities can declare their own keys and patterns.

Stable public configuration:

Key or patternPurpose
outlet.<outletName>.directoryOverride one outlet directory
outlet.<outletName>.<layer>.directoryRoute output with one effective layer
override-package.<originalPackagePrefix>Rewrite generated Java imports
rest.useVendorSpecificMimeTypeSelect vendor-specific REST media types
platform.springboot.flavorSelect the SpringBoot generation flavor
schemaMigration.modeSelect the Flyway migration workflow

Advanced configuration:

Key or patternPurpose
openapi.qualifiedSchemaNameUse qualified OpenAPI schema names
java.dto.namingSelect decorated or plain Java DTO names
generatedInfo.textReplace the generated Java header
cartridge.<cartridgeName>.enabledOverride cartridge enablement

4. Stable public configuration

4.1 outlet.<outletName>.directory

  • Owner: JoinedWorkz generator runtime
  • Audience / lifecycle: PUBLIC / STABLE
  • Type: non-blank relative path
  • Default: the effective outlet declaration in the selected profile
  • Scope: one known outlet
  • Effect: replaces the outlet's default output directory
  • Ownership: routing does not change whether the output is replaceable, first-cut, manual or persistent

Example:

properties
outlet.generatedJavaSource.directory=../backend/src/generated/java

The outlet name must be defined by a facility used in the build. Public JoinedWorkz outlet names and their default ownership are listed in Generated output, ownership and regeneration. Custom facilities can add other outlet names.

4.2 outlet.<outletName>.<layer>.directory

  • Owner: JoinedWorkz generator runtime
  • Audience / lifecycle: PUBLIC / STABLE
  • Type: non-blank relative path
  • Default: the global directory of the same outlet
  • Scope: one exact outlet and one exact effective layer
  • Effect: routes only files generated with that effective layer

Example:

properties
outlet.generatedJavaSource.api.directory=../api/src/generated/java

Each generated file has at most one effective layer for outlet routing. JoinedWorkz normally uses the layer declared by the CMN model. A generator can assign a different effective layer to a particular output, for example api for SpringBoot controller and API-interface files.

CMN layer names are case-sensitive identifiers. A generator-assigned effective layer is a case-sensitive, facility-defined name. Neither forms a fixed JoinedWorkz-wide list. For each generated file:

  1. JoinedWorkz uses the effective layer selected for that file;
  2. an exact outlet.<outletName>.<layer>.directory mapping wins when present; and
  3. without that exact mapping, JoinedWorkz uses outlet.<outletName>.directory, which itself falls back to the profile outlet default.

Output without an effective layer also uses the global outlet directory.

The mapping changes the target directory only. It does not rename Java packages and does not assign additional semantics to an otherwise arbitrary CMN layer.

4.3 Outlet path contract

Both outlet patterns use the same path contract:

  • paths are relative to the Maven module base directory or Eclipse project root;
  • . and .. segments are normalized;
  • a deliberate ../sibling-module/... route is allowed;
  • the normalized target must not be the module/project root or one of its ancestors;
  • absolute Unix paths, Windows drive paths, Windows root-relative paths and ${...} placeholders such as ${baseDir} are rejected;
  • / and \ are interpreted consistently as path separators.

Examples:

properties
# valid: dedicated directory in the current module
outlet.generatedOpenApi.directory=src/generated/resources/openapi

# valid: dedicated directory in a sibling module
outlet.generatedJavaSource.directory=../backend/src/generated/java

# invalid
outlet.generatedJavaSource.directory=${baseDir}/src/generated/java
outlet.generatedJavaSource.directory=/tmp/generated
outlet.generatedJavaSource.directory=..

Only route an outlet into a directory with compatible ownership and cleanup rules. In particular, do not mix replaceable output with first-cut files or versioned Flyway history.

4.4 override-package.<originalPackagePrefix>

  • Owner: Java facility
  • Audience / lifecycle: PUBLIC / STABLE
  • Type: non-blank target Java package prefix
  • Pattern parameter: non-empty original Java package prefix
  • Default: no import rewriting
  • Effect: rewrites matching imports emitted through the common Java generator

Example:

properties
override-package.org.iworkz.core=com.example.core
override-package.org.iworkz.core.exception=com.example.exception

The precedence is:

  • matching is case-sensitive and starts at the beginning of the qualified import;
  • an original prefix matches the same package or a child package at a package segment boundary;
  • the longest matching original prefix wins;
  • only the leading match is replaced;
  • wildcards are not supported.

Release 1.3.80 supports the mechanism, but overlapping original prefixes do not have deterministic precedence. Use only one mapping or non-overlapping prefixes with that release.

The mapping does not copy classes, modify their package declarations or add dependencies. See Package overrides for helper libraries for the complete replacement workflow.

4.5 rest.useVendorSpecificMimeType

  • Owner: Base OpenApiCartridge
  • Audience / lifecycle: PUBLIC / STABLE
  • Type: Boolean
  • Values: true or false, trimmed and case-insensitive
  • Default: false
  • Blank: invalid
  • Effect: enables vendor-specific REST media types for resources that do not specify the decision in CMN

Example:

properties
rest.useVendorSpecificMimeType=true

Precedence, from highest to lowest:

  1. CMN package vendorSpecificMimeType;
  2. rest.useVendorSpecificMimeType;
  3. false.

4.6 platform.springboot.flavor

  • Owner: SpringBoot setting
  • Audience / lifecycle: PUBLIC / STABLE
  • Type: enumeration
  • Values: legacy, modern
  • Default: legacy
  • Case: case-sensitive
  • Blank: invalid
  • Effect: selects the SpringBoot naming and mapping strategy set

Example:

properties
platform.springboot.flavor=modern

Use the lowercase forms exactly as shown. Changing the flavor can change replaceable generated Java output; clean, regenerate and build all consumers.

4.7 schemaMigration.mode

  • Owner: SpringBoot SchemaMigrationCartridge
  • Audience / lifecycle: PUBLIC / STABLE
  • Type: enumeration
  • Values: STRICT, DEVELOPMENT
  • Default: STRICT
  • Case: case-insensitive
  • Blank: uses the default
  • Effect: selects the Flyway migration workflow

Example:

properties
schemaMigration.mode=DEVELOPMENT

STRICT produces persistent, versioned migration history. DEVELOPMENT replaces the development migration and snapshot for rapid model iteration. Read Flyway schema migrations before changing the mode or cleaning its outlets.

5. Advanced configuration

5.1 openapi.qualifiedSchemaName

  • Owner: Base OpenApiCartridge
  • Audience / lifecycle: ADVANCED / STABLE
  • Type: Boolean
  • Values: true or false, trimmed and case-insensitive
  • Default: false
  • Blank: invalid
  • Effect: uses qualified names for generated OpenAPI schemas

Example:

properties
openapi.qualifiedSchemaName=true

A model-level qualifiedSchemaName setting can additionally enable qualified names. Setting this property to false does not override a model that enables them.

5.2 generatedInfo.text

  • Owner: Java facility
  • Audience / lifecycle: ADVANCED / STABLE
  • Type: string
  • Default: the standard header of the selected Java generator helper
  • Blank: allowed and produces no header text
  • Effect: replaces the complete header emitted by generators using the common Java class-generator helper

Example:

properties
generatedInfo.text=/* Generated by the project build */

Java properties escapes are interpreted before the generator receives the value. Use \n escapes if a multi-line header is required. The setting changes replaceable generated Java files; do not use it to insert manually maintained content.

5.3 cartridge.<cartridgeName>.enabled

  • Owner: JoinedWorkz generator runtime
  • Audience / lifecycle: ADVANCED / STABLE
  • Type: Boolean
  • Values: true or false, trimmed and case-insensitive
  • Default: the effective profile cartridge-application setting
  • Scope: one exact, case-sensitive cartridge name
  • Effect: enables or disables that cartridge for generated models

Example:

properties
cartridge.OpenApiCartridge.enabled=false

The SpringBoot integration-test cartridge is disabled by its profile application. Opt in to its supported generated Create-to-Read flow with:

properties
cartridge.IntegrationTestCartridge.enabled=true

Precedence, from highest to lowest:

  1. CMN exclude;
  2. cartridge.<cartridgeName>.enabled;
  3. profile cartridge-application setting.

For example:

cmn
platform SpringBoot exclude OpenApiCartridge

The exclusion belongs to that CMN root model. Submodels in the same file inherit it; another root model generated separately needs its own exclusion. An explicit cartridge.OpenApiCartridge.enabled=true cannot override the CMN clause. The enablement key and properties owned by the excluded cartridge remain known, but are unused when no generated root model activates that consumer.

Disabling a cartridge can leave an incomplete set of generated artifacts or stale files from an earlier run. Treat it as an architectural choice, clean only the cartridge's replaceable outputs and rebuild every consumer.

5.4 java.dto.naming

  • Owner: Java facility
  • Audience / lifecycle: ADVANCED / STABLE
  • Type: enumeration
  • Values: decorated, plain
  • Default: decorated
  • Case: case-insensitive
  • Blank: uses the default
  • Effect: selects the Java package and, for SpringBoot, the class-name decoration of generated DTOs

Example:

properties
java.dto.naming=plain

For a CMN type Customer in package com.example.customer, the effective names are:

  • Java decorated: com.example.customer.dto.Customer;
  • Java plain: com.example.customer.Customer;
  • SpringBoot decorated: com.example.customer.dto.CustomerDto;
  • SpringBoot plain: com.example.customer.Customer.

A CMN package can override the project default:

cmn
package com.example.customer skipDtoPostfix=true

skipDtoPostfix=true selects plain naming; false selects decorated naming. The property is inherited by nested package and subpackage blocks. Precedence, from highest to lowest, is:

  1. skipDtoPostfix on the concrete package;
  2. skipDtoPostfix on the nearest parent package;
  3. the CMN layer external, which implicitly selects plain naming;
  4. java.dto.naming; and
  5. the default decorated mode.

An explicit package value, including false, therefore overrides both the external rule and the project setting. The naming strategy is used for DTO declarations and generated references. If plain naming gives a DTO and an entity the same simple Java name, JoinedWorkz emits a qualified reference where required.

Changing the mode moves replaceable files and changes Java package or class names. Clean only the affected replaceable output, regenerate all models and compile every consumer. This setting does not add an Entity suffix and does not rename generated enum types.

6. Diagnostics

Invalid values are errors and stop generation. Unknown or unused properties are warnings so that custom facilities and staged multi-model builds are not rejected prematurely.

For a symptom-first workflow that also distinguishes Maven resolution, model validation, cartridges, outlets and consumer builds, see Troubleshooting.

CodeSeverityMeaning
JW_CONFIG_INVALID_FILEErrorThe file cannot be parsed as Java properties
JW_CONFIG_INVALID_KEYErrorA profile-pattern key has an empty placeholder
JW_CONFIG_INVALID_VALUEErrorA known key has an invalid type, value or path
JW_CONFIG_UNKNOWN_KEYWarningNo runtime pattern or generated platform declares the key
JW_CONFIG_UNKNOWN_OUTLETWarningAn outlet pattern names no outlet known in the Maven build
JW_CONFIG_UNKNOWN_CARTRIDGEWarningA cartridge pattern names no cartridge known in the Maven build
JW_CONFIG_UNUSED_KEYWarningThe key is known, but no generated model or active consumer uses it

6.1 Maven

For each generated platform Maven immediately validates the format of values whose declarations are known for that platform. Errors abort generation.

Only after all models and generator clusters of the module's plugin execution complete successfully does Maven evaluate unknown and unused keys. The final warning set is based on the union of platforms, outlets, cartridges and facility properties encountered in that execution. A failed generation does not emit a misleading final unknown/unused summary. In a multi-module reactor, each model module running the plugin performs its own audit.

Warnings appear in the Maven log with their stable code. For example, the misspelled key schemaMigration.mod produces JW_CONFIG_UNKNOWN_KEY and can suggest schemaMigration.mode.

Representative Maven generator diagnostics are:

  • invalid migration mode: JW_CONFIG_INVALID_VALUE, the configured value and Expected one of: STRICT, DEVELOPMENT;
  • empty profile-pattern placeholder, for example override-package.: JW_CONFIG_INVALID_KEY, the configured key and the expected non-empty placeholder;
  • invalid Boolean: JW_CONFIG_INVALID_VALUE and Expected 'true' or 'false';
  • malformed Java Properties input: JW_CONFIG_INVALID_FILE and the file name joinedworkz.properties;
  • unknown schemaMigration.mod: JW_CONFIG_UNKNOWN_KEY and Did you mean 'schemaMigration.mode'?;
  • a property whose cartridge consumer is disabled: JW_CONFIG_UNUSED_KEY and the exact property key.

The diagnostic code and, where applicable, the exact property key are the stable machine-readable parts. The surrounding Maven exception chain can add implementation-specific context.

6.2 JoinedWorkz Studio

An incremental Studio generation performs platform-local format validation only. It reports invalid files and invalid values as markers on joinedworkz.properties, but does not attempt a project-wide unknown/unused analysis.

This difference is intentional: an incremental invocation may see only part of the project's models and would otherwise report false warnings. Use a successful Maven build for the complete configuration audit.

7. Custom facilities and additional properties

A custom facility can extend the configuration surface. A profile can declare a first-class configuration property and reference it from a platform, setting, cartridge or cartridge application:

profile
package com.example.facility

import org.joinedworkz.facilities.common.profiles.java

'''Selects a custom generator mode.'''
configuration property CustomMode: ENUMERATION
    key="custom.mode"
    values="simple","extended"
    default="simple"
    audience="PUBLIC"
    lifecycle="STABLE"

outlet generatedCustomSource
    directory="./target/generated-custom"

cartridge CustomCartridge
    implementation="com.example.CustomCartridge"
    outlets=generatedCustomSource
    configurationProperties=CustomMode

platform Custom specialization of Java {
    apply cartridge CustomCartridge
}

This makes custom.mode known when the cartridge belongs to the generated platform. A disabled or excluded cartridge keeps the declaration known but marks its consumer property unused.

Facility authors must document at least:

  • exact key or pattern and owning facility;
  • value type, allowed values, default and blank/case handling;
  • audience and lifecycle;
  • which platform, setting, cartridge or cartridge application consumes it;
  • precedence over model or profile values;
  • output and ownership effects;
  • minimum supported JoinedWorkz version;
  • valid and invalid configuration examples.

Custom keys should use a facility-owned namespace. Profile-defined key patterns are rejected when they claim the runtime-owned outlet., cartridge. or override. prefixes.

8. What is not configurable here

Profile outlet flags such as overwriteExistingFiles, markAsDerived, deleteFilesOnCleanBuild and cleanWholdDirectoryOnCleanBuild are profile metadata. They are not project-level joinedworkz.properties keys.

Likewise, CMN packages, CMN layers, Java package rewriting and outlet directories are separate concepts:

  • a CMN package defines the technical model namespace;
  • a CMN layer normally becomes the effective layer for outlet routing;
  • an outlet property selects a physical output directory;
  • override-package.* rewrites generated Java imports.

For safe cleanup and file ownership, continue with Generated output, ownership and regeneration.