Java facility
Support status
Stable
The Java facility extends Base with Java type mappings and replaceable Java DTO and enum generation. It is useful when a project needs model-derived Java data types without selecting a full runtime framework.
1. Maven artifact and platform
Add the facility to the model module:
<dependency>
<groupId>org.joinedworkz.facilities</groupId>
<artifactId>common-java</artifactId>
<version>${joinedworkz.version}</version>
<scope>provided</scope>
</dependency>The artifact contributes profile package org.joinedworkz.facilities.common.profiles.java and platform Java. Java specializes Base, and the Maven dependency brings common-base transitively.
2. Supported modeling and generation
The Java platform inherits Base types, REST method types, OpenAPI and diagrams. Its DtoCartridge additionally:
- maps Base simple types to Java types;
- generates Java classes for non-virtual CMN field-container types except fieldsets;
- generates Java enums for CMN enumerations;
- handles fields, collections, dictionaries, inheritance and immutable fields according to the modeled type; and
- uses the declared CMN layer as the effective layer of generated Java output unless a specialized generator assigns another effective layer.
By default, generated Java DTOs use decorated naming: their package is the CMN namespace followed by .dto. The advanced plain naming mode instead uses the CMN namespace itself. Java DTO class names are unchanged in both modes. Generated enum types always use the CMN namespace followed by .type.
Java alone does not generate controllers, services, repositories, persistence configuration or an application bootstrap.
2.1 Integer-coded enumerations
For an enum<integer>, Java generates the named enum constants together with their explicit codes:
enum<integer> State {
ACTIVE: 10
PASSIVE: 20
}The generated enum provides:
getMappedValue()for the code of one constant;toMappedValue(State)for converting a constant to its code;fromMappedValue(Integer)for converting a code to its constant; andmappedValueOf(String)for converting an exact enum name to its code.
toMappedValue(null), fromMappedValue(null), and mappedValueOf(null) return null. fromMappedValue throws an IllegalArgumentException for an unknown code. mappedValueOf uses the Java enum name and therefore rejects an unknown or differently cased name.
The Java-platform implementation is self-contained. It does not require a Genesis runtime library for these mapping methods. OpenAPI still represents the enum through its names as a string enum; the integer codes do not change the wire contract.
2.2 Operation naming conventions
The Java profile assigns stereotypes to entity operations whose names match the following conventions. This model transformation is independent of a particular Java runtime or persistence facility.
| Operation-name pattern | Stereotype added by the profile | Intended model role |
|---|---|---|
findFirstBy* | findFirstBy | Read the first matching value. |
findBy* | findBy | Read all matching values. |
findOneBy* | findOneBy | Read one matching value. |
countWith* | countWith | Count matching values. |
existsWith* | existsWith | Test whether a matching value exists. |
updateJust* | updateJust | Update only selected values. |
updateWhere* | updateWhere | Identify a conditional update operation. |
deleteWhere* | deleteWhere | Delete matching values. |
The trailing * describes a name prefix; it is not written as part of a CMN operation. For example, both findBy and findBySku match findBy*. A common declaration uses field-reference parameters:
package org.example.catalog
import org.joinedworkz.facilities.common.base
import org.joinedworkz.facilities.common.profiles.java
platform Java
type<entity> CatalogItem {
id**: Id
sku*: String
active*: Boolean
findBy(sku)
findOneBy(sku)
countWith(active)
existsWith(sku)
}The effective stereotype is available after model transformation. JoinedWorkz Studio can therefore highlight a matching operation name with the semantic style for that stereotype even though the operation has no explicit <...> declaration.
These conventions define profile-level model semantics. They do not guarantee that every Java-specializing facility generates every convention. Consult the selected facility's documentation for its supported output contract.
The Java profile also declares explicit operation stereotypes such as find, findOne, execute, update, and delete. A complete CMN model that writes one of these stereotypes explicitly must import org.joinedworkz.facilities.common.profiles.java, as the example above does.
2.3 Dictionary fields
The Java DTO generator maps a CMN dictionary field to java.util.Map. The type before the brackets supplies the Java value type; the type inside the brackets supplies the Java key type:
type DictionaryDocument {
entries: String[String]
}The generated DTO therefore declares Map<String, String> entries and uses the same Map<K, V> type in its constructor, getter and setter. It also provides dictionary-oriented put... and putAll... helpers. For a general entries: ValueType[KeyType] declaration, the Java order is Map<KeyJavaType, ValueJavaType>.
This is the Java DTO-field contract. The Java facility alone does not generate service methods or REST controllers, so it does not establish a Java mapping for operation parameters or HTTP bodies. The separate SpringBoot dictionary-body contract documents that runtime boundary.
3. Public and advanced configuration
override-package.<originalPackagePrefix>— public. Rewrites a generated Java import from the most specific matching package prefix.java.dto.naming— advanced. Selectsdecoratedorplaingenerated DTO names for the project. The default isdecorated.generatedInfo.text— advanced. Replaces the complete generated Java file header. If it is absent, JoinedWorkz emits the standard header; a blank replacement is allowed.
The package-override workflow and its compatibility responsibilities are described in Facilities and platforms. Outlet routing uses outlet.generatedJavaSource.directory and, for output with an effective layer, outlet.generatedJavaSource.<layer>.directory.
3.1 DTO naming
Select plain DTO naming for the project in joinedworkz.properties:
java.dto.naming=plainA CMN package can override the project setting, including with an explicit false:
package com.example.customer skipDtoPostfix=trueskipDtoPostfix=true selects plain naming; false selects decorated naming. Nested package and subpackage blocks inherit the property. A value declared on the nearest enclosing package wins over a value on its parent.
The effective decision, from highest to lowest precedence, is:
skipDtoPostfixon the concrete package;skipDtoPostfixon the nearest parent package;- the
externallayer, which implicitly selects plain naming; java.dto.naminginjoinedworkz.properties; and- the default
decoratedmode.
An explicit package value has priority over the external layer. For example, external package com.example.customer skipDtoPostfix=false uses decorated naming.
For a CMN type Customer in com.example.customer, Java generates:
- decorated:
com.example.customer.dto.Customer; - plain:
com.example.customer.Customer.
The mode changes replaceable Java package declarations, file paths and type references. Clean the affected replaceable output, regenerate and compile all consumers after changing it. When plain naming gives a DTO and another generated Java type the same simple name, JoinedWorkz uses a qualified type reference where needed; the Java package still has to be valid for the project's own handwritten types.
See the java.dto.naming reference for value parsing and the complete configuration contract.
4. Outputs and ownership
The replaceable generatedJavaSource outlet defaults to src/generated/java.
The Java facility also inherits the replaceable Base OpenAPI and diagram outlets. Never put handwritten classes in a generated Java directory that is cleaned as one unit.
5. Minimal model
package com.example.customer
import org.joinedworkz.facilities.common.base
import org.joinedworkz.facilities.common.profiles.java
platform Java
type Customer {
id: Id
name: String
status: CustomerStatus
}
enum CustomerStatus {
ACTIVE
INACTIVE
}6. Build and expected result
Register the generated directory as a Maven compile source root, for example with the Build Helper Maven Plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<id>add-generated-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.basedir}/src/generated/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>Then run:
mvn clean packageThe minimal model generates:
src/generated/java/com/example/customer/dto/Customer.java
src/generated/java/com/example/customer/type/CustomerStatus.javaBase OpenAPI output is generated only when the model also contains applicable resources.
The release examples keep those two concerns separate:
example-java-domainverifies DTO and enum generation from domain types;example-java-rest-apiverifies Java DTOs and the inherited OpenAPI contract for a modeled resource.
Both are independent Java 21/Maven 3.9 modules and use mvn clean verify. Follow the Java facility examples for their release links, exact outputs and ownership rules.
7. Boundaries
common-javais a data-type generator, not a runtime application platform.- Maven must compile the effective outlet directory; generating a Java file does not register that directory automatically.
- The mapping methods of a Java-platform
enum<integer>are self-contained. Other specialized modeled constructs can reference helper-library APIs. Add the compatible runtime dependency or use a project-tested package override; do not hand-edit the generated import. - Layer-specific routing is supported by the common Java class generator. A specialized generator can preserve the model layer or assign a different effective layer to its output.
- Replaceable output has no protected-region or merge contract.
