Skip to content

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:

xml
<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:

cmn
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; and
  • mappedValueOf(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 patternStereotype added by the profileIntended model role
findFirstBy*findFirstByRead the first matching value.
findBy*findByRead all matching values.
findOneBy*findOneByRead one matching value.
countWith*countWithCount matching values.
existsWith*existsWithTest whether a matching value exists.
updateJust*updateJustUpdate only selected values.
updateWhere*updateWhereIdentify a conditional update operation.
deleteWhere*deleteWhereDelete 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:

cmn
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:

cmn
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. Selects decorated or plain generated DTO names for the project. The default is decorated.
  • 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:

properties
java.dto.naming=plain

A CMN package can override the project setting, including with an explicit false:

cmn
package com.example.customer skipDtoPostfix=true

skipDtoPostfix=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:

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

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

cmn
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:

xml
<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:

bash
mvn clean package

The minimal model generates:

text
src/generated/java/com/example/customer/dto/Customer.java
src/generated/java/com/example/customer/type/CustomerStatus.java

Base OpenAPI output is generated only when the model also contains applicable resources.

The release examples keep those two concerns separate:

  • example-java-domain verifies DTO and enum generation from domain types;
  • example-java-rest-api verifies 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-java is 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.